int cp_heap_push(cp_heap *h, void *in) { int rc = 0; unsigned int he; if ((rc = cp_heap_txlock(h))) return rc; he = h->heap_end; #ifdef _HEAP_TRACE DEBUGMSG("cp_heap_push: %p\n", in); heap_info(h); #endif if ((rc = heap_resize(h))) goto DONE; if ((h->mode & COLLECTION_MODE_COPY) && h->copy) h->heap[he] = (*h->copy)(in); else h->heap[he] = in; siftup(h); #ifdef _HEAP_TRACE DEBUGMSG("cp_heap_push end\n"); heap_info(h); #endif DONE: cp_heap_txunlock(h); return rc; }
void cp_heap_destroy(cp_heap *h) { #ifdef __TRACE__ DEBUGMSG("cp_heap_destroy\n"); heap_info(h); #endif if (h) { if (h->heap) { if ((h->mode & COLLECTION_MODE_DEEP) && h->dtr) { int i; for (i = 1; i < h->heap_end; ++i) if (h->heap[i]) (*h->dtr)(h->heap[i]); } free(h->heap); } if (h->lock) { cp_mutex_destroy(h->lock); free(h->lock); } free(h); } }
static void siftdown(cp_heap *h, unsigned int p) { unsigned int c; #ifdef _HEAP_TRACE DEBUGMSG("siftdown start\n"); heap_info(h); fflush(stdout); #endif for (c = LEFTCHILD(p); c < h->heap_end; p = c, c = LEFTCHILD(p)) { #ifdef _HEAP_TRACE DEBUGMSG(" c = %i, h->heap_end = %i\n", c, h->heap_end); #endif if (h->comp(h->heap[c], h->heap[c + 1]) <= 0) c++; /* c points to the largest among the children of p */ if (h->comp(h->heap[p], h->heap[c]) <= 0) swap(&(h->heap[p]), &(h->heap[c])); else return; } if (c == h->heap_end && h->comp(h->heap[p], h->heap[c]) <= 0) swap(&(h->heap[p]), &(h->heap[c])); }
static int cmd_heap_dma_info(struct vmm_chardev *cdev) { return heap_info(cdev, FALSE, vmm_dma_heap_start_va(), vmm_dma_heap_size(), vmm_dma_heap_hksize(), vmm_dma_heap_free_size()); }
static int cmd_heap_info(struct vmm_chardev *cdev) { return heap_info(cdev, TRUE, vmm_normal_heap_start_va(), vmm_normal_heap_size(), vmm_normal_heap_hksize(), vmm_normal_heap_free_size()); }
cp_heap *cp_heap_create_by_option(int mode, int initial_size, cp_compare_fn comp, cp_copy_fn copy, cp_destructor_fn dtr) { int rc; cp_heap *h = (cp_heap *) calloc(1, sizeof(cp_heap)); if (h == NULL) return NULL; if ((mode & COLLECTION_MODE_NOSYNC) == 0) { h->lock = malloc(sizeof(cp_mutex)); if (h->lock == NULL) { free(h); return NULL; } if ((rc = cp_mutex_init(h->lock, NULL))) { free(h->lock); free(h); return NULL; } } if (initial_size) { for (h->heap_length = 0; h->heap_length < initial_size; h->heap_height++) h->heap_length += LEVELSIZE(h->heap_height) + 1; if ((h->heap = malloc(h->heap_length * sizeof(void *))) == NULL) { cp_heap_destroy(h); return NULL; } } else { h->heap = NULL; h->heap_height = 0; h->heap_length = 0; } h->heap_end = 1; h->comp = comp; h->copy = copy; h->dtr = dtr; h->mode = mode; #ifdef __TRACE__ DEBUGMSG("cp_heap_create_by_option\n"); heap_info(h); #endif return h; }
// return current memory usage in bytes size_t get_memory_usage_now() { size_t memory = 0; #if defined(__APPLE__) struct task_basic_info t_info; mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT; if (KERN_SUCCESS != task_info(mach_task_self(), TASK_BASIC_INFO, reinterpret_cast<task_info_t>(&t_info), &t_info_count)) { return 0; } memory = t_info.resident_size; #elif defined(__LIBCATAMOUNT__) && defined(REDSTORM_HEAP_INFO) size_t frags; unsigned long total_free, largest_free, total_used; heap_info( &frags, &total_free, &largest_free, &total_used ); memory = total_used * 1024; #elif defined(BGQ_LWK) uint64_t heap; Kernel_GetMemorySize(KERNEL_MEMSIZE_HEAP, &heap); memory = heap; #elif defined(PROCFS) unsigned long rss_pages = 0; // Read memory size data from /proc/pid/stat // see "man proc" for details. std::ifstream proc_stat("/proc/self/stat"); if (proc_stat) { std::string buf; proc_stat >> buf >> buf >> buf >> buf >> buf >> buf >> buf >> buf >> buf >> buf >> buf >> buf >> buf >> buf >> buf >> buf >> buf >> buf >> buf >> buf >> buf >> buf >> buf >> rss_pages; proc_stat.close(); } memory = rss_pages * sysconf( _SC_PAGESIZE); #endif /* Success */ return memory; }
static void siftup(cp_heap *h) { unsigned int c = h->heap_end - 1; while (c != 1 && h->comp(h->heap[PARENT(c)], h->heap[c]) <= 0) { #ifdef _HEAP_TRACE DEBUGMSG("siftup\n"); heap_info(h); fflush(stdout); #endif swap(&(h->heap[PARENT(c)]), &(h->heap[c])); c = PARENT(c); } }
/* returns the maximum allocatable memory, in Mbytes, using mallinfo() */ int ML_MaxMemorySize() { #ifdef ML_MALLINFO size_t fragments; long long int total_free, largest_free, total_used; /* int percent; */ #ifndef ML_TFLOP struct mallinfo M; #endif #ifdef ML_TFLOP unsigned long ultotal_free=0, ullargest_free=0, ultotal_used=0; #endif #ifdef ML_TFLOP #ifndef NO_HEAPINFO heap_info(&fragments, &ultotal_free, &ullargest_free, &ultotal_used); total_free=(int) (ultotal_free / 1024); largest_free= (int) (ullargest_free / 1024); total_used = (int) (ultotal_used /1024); #else total_free=0; largest_free=0; total_used=0; #endif #else /* use system call to get memory used information */ M = mallinfo(); fragments = M.ordblks + M.smblks + M.hblks; total_free = M.fsmblks + M.fordblks; total_used = M.hblkhd + M.usmblks + M.uordblks; /* total_free = ml_total_mem - total_used; */ largest_free = -1024; #endif /* convert to Kbytes */ return( (int)(total_used/(1024*1024)) ); #else return -1; #endif }
char * ML_memory_check(char *fmt, ... ) { #ifdef ML_MEMORY_CHK size_t fragments=0; int total_free=0, largest_free=0, total_used=0; int total_swap=0, total_swap_free=0, total_swap_used=0; static double start_time = -1.; double elapsed_time; int id, nnodes, i; ml_IntLoc isrcvec[ML_NIntStats],imaxvec[ML_NIntStats], iminvec[ML_NIntStats]; int isrcvec_copy[ML_NIntStats]; int iavgvec[ML_NIntStats]; ml_DblLoc dsrcvec[ML_NDblStats],dmaxvec[ML_NDblStats], dminvec[ML_NDblStats]; double dsrcvec_copy[ML_NDblStats]; double davgvec[ML_NDblStats]; static char *ml_memory_label = NULL; va_list ap; #ifdef ML_TFLOP unsigned long ultotal_free=0, ullargest_free=0, ultotal_used=0; #else struct mallinfo M; static int ml_total_mem = 0; #endif FILE *fid; # define ml_meminfo_size 23 int haveMemInfo=0, overflowDetected = 0; char method[80]; int mypid=0; /* allocate space for string that is printed with memory information */ if (ml_memory_label == NULL) { ml_memory_label = (char *) malloc(sizeof(char)*200); /* THIS MALLOC NEEDS TO STAY A */ /* MALLOC AND NOT AN ML_ALLOCATE */ ml_memory_label[0] = '\0'; } /* if fmt is NULL just return the current string associated with */ /* the memory printing. The idea is that an low level function */ /* can use this to get the string, append any additional info */ /* and use this when it invokes this routine a second time. */ if (fmt == NULL) return(ml_memory_label); /* Take variable argument and transform it to string that will */ /* is printed with memory statistics. */ va_start(ap, fmt); vsprintf(ml_memory_label,fmt, ap); va_end(ap); elapsed_time = GetClock(); if (start_time == -1.) start_time = elapsed_time; elapsed_time = elapsed_time - start_time; #ifdef ML_TFLOP /* Memory statistics for Red Storm. FYI, heap_info returns bytes. */ #ifndef NO_HEAPINFO heap_info(&fragments, &ultotal_free, &ullargest_free, &ultotal_used); #ifdef ML_MPI MPI_Comm_rank(MPI_COMM_WORLD,&mypid); #endif total_free=(int) (ultotal_free / (1024*1024)); largest_free= (int) (ullargest_free / (1024*1024)); total_used = (int) (ultotal_used / (1024*1024)); sprintf(method,"Using heap_info()"); #else total_free=0; largest_free=0; total_used=0; #endif #else /* Memory statistics for all other platforms, via the system call mallinfo() and reading file /proc/meminfo, which is available under most Linux OS's. */ M = mallinfo(); fid = fopen("/proc/meminfo","r"); if (fid != NULL) { char str[80], units[10]; int k; for (i=0; i< ml_meminfo_size; i++) { if (fscanf(fid,"%s%d%s", str, &k,units) == 3) { if (strcmp(str,"MemTotal:") == 0 && (ml_total_mem==0)) ml_total_mem = k/1024; if (strcmp(str,"MemFree:") == 0) {total_free = k/1024; } if (strcmp(str,"SwapTotal:") == 0) {total_swap = k/1024; } if (strcmp(str,"SwapFree:") == 0) {total_swap_free = k/1024; } } } fclose(fid); total_used = ml_total_mem - total_free; total_swap_used = total_swap - total_swap_free; sprintf(method,"Using /proc/meminfo"); haveMemInfo = 1; } /* If /proc/meminfo doesn't exist, use mallinfo() instead. */ if ( !haveMemInfo ) { if (ml_total_mem == 0) ml_total_mem = ML_MaxAllocatableSize(); if (M.hblkhd < 0) { /* try to fix overflow */ double delta = fabs(((double) INT_MIN) - ((double) M.hblkhd)) + 1; total_used = (int) ( (((double) INT_MAX) + delta) / (1024*1024) ); overflowDetected = 1; } /*Ignore this field upon overflow because I'm don't know how to handle it*/ if (M.uordblks > 0) total_used += M.uordblks / (1024*1024); total_free = ml_total_mem - total_used; sprintf(method,"Using mallinfo()"); } fragments = M.ordblks + M.hblks; largest_free = -1; #endif /*ifdef ML_TFLOP*/ /* Only print if fmt string is not empty */ /* This allows for an intialization of */ /* ml_total_mem without any printing */ if (strlen(fmt) == 0) return(ml_memory_label); /*isrcvec[0].value = fragments; */ isrcvec[0].value = 0; isrcvec[1].value = total_free; isrcvec[2].value = largest_free; isrcvec[3].value = total_used; isrcvec[4].value = total_free + total_used; /*TODO could this overflow?*/ isrcvec[5].value = (int) ( ((double)total_used*1000) / ((double)(total_free+total_used)) ); isrcvec[6].value = total_swap_free; isrcvec[7].value = total_swap_used; isrcvec[8].value = total_swap; /*TODO could this overflow?*/ isrcvec[9].value = (int) ( ((double)total_swap_used*1000) / ((double)(total_swap)) ); dsrcvec[0].value = elapsed_time; dsrcvec[1].value = fragments; #ifdef ML_MPI for (i =0; i < ML_NIntStats; i++) MPI_Comm_rank(MPI_COMM_WORLD,&(isrcvec[i].rank)); for (i =0; i < ML_NDblStats; i++) MPI_Comm_rank(MPI_COMM_WORLD,&(dsrcvec[i].rank)); #endif for (i =0; i < ML_NIntStats; i++) isrcvec_copy[i] = isrcvec[i].value; for (i =0; i < ML_NDblStats; i++) dsrcvec_copy[i] = dsrcvec[i].value; nnodes = 1; id = 0; #ifdef ML_MPI MPI_Comm_rank(MPI_COMM_WORLD,&id); MPI_Comm_size(MPI_COMM_WORLD,&nnodes); MPI_Reduce(isrcvec,imaxvec,ML_NIntStats,MPI_2INT,MPI_MAXLOC,0,MPI_COMM_WORLD); MPI_Reduce(isrcvec,iminvec,ML_NIntStats,MPI_2INT,MPI_MINLOC,0,MPI_COMM_WORLD); MPI_Reduce(isrcvec_copy,iavgvec,ML_NIntStats,MPI_INT,MPI_SUM,0,MPI_COMM_WORLD); MPI_Reduce(dsrcvec,dmaxvec,ML_NDblStats,MPI_DOUBLE_INT,MPI_MAXLOC,0,MPI_COMM_WORLD); MPI_Reduce(dsrcvec,dminvec,ML_NDblStats,MPI_DOUBLE_INT,MPI_MINLOC,0,MPI_COMM_WORLD); MPI_Reduce(dsrcvec_copy,davgvec,ML_NDblStats,MPI_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD); MPI_Reduce(&overflowDetected,&i,1,MPI_INT,MPI_MAX,0,MPI_COMM_WORLD); overflowDetected = i; #else for (i =0; i < ML_NIntStats; i++) { imaxvec[i].value = isrcvec[i].value; iminvec[i].value = isrcvec[i].value; iavgvec[i] = isrcvec[i].value; } for (i =0; i < ML_NDblStats; i++) { dmaxvec[i].value = dsrcvec[i].value; dminvec[i].value = dsrcvec[i].value; davgvec[i] = dsrcvec[i].value; } #endif /* uncomment lines below if you want individual processor information */ /* printf("%s(%d): blks = %ld, free = %ld, max free = %ld, used = %ld, total = %ld, %% used = %e, time = %e\n", ml_memory_label,id,fragments, total_free, largest_free, total_used, total_free+total_used, ((double)total_used)/((double)(total_free+total_used)),elapsed_time); */ if (id == 0 && ML_Get_PrintLevel() > 0) { for (i =0; i < ML_NIntStats; i++) iavgvec[i] = (int) (iavgvec[i]/((double) nnodes)); for (i =0; i < ML_NDblStats; i++) davgvec[i] = davgvec[i] / nnodes; printf("-------------------------------------------------------------\n"); printf("Summary Heap data (Mbytes) at %s\n",ml_memory_label); printf("%s\n",method); if (overflowDetected) printf("*WARNING* mallinfo() counter overflow detected\n"); printf(" avg min max\n"); printf("-------------------------------------------------------------\n"); printf(" blks %11d %11d (%5d) %11d (%5d) %s\n", (int) davgvec[1], (int) dminvec[1].value, dminvec[1].rank, (int) dmaxvec[1].value, dmaxvec[1].rank, ml_memory_label); printf(" free %11d %11d (%5d) %11d (%5d) %s\n", iavgvec[1], iminvec[1].value, iminvec[1].rank, imaxvec[1].value, imaxvec[1].rank, ml_memory_label); if (iavgvec[2] != -1) printf(" max free %11d %11d (%5d) %11d (%5d) %s\n", iavgvec[2], iminvec[2].value, iminvec[2].rank, imaxvec[2].value, imaxvec[2].rank, ml_memory_label); printf(" used %11d %11d (%5d) %11d (%5d) %s\n", iavgvec[3], iminvec[3].value, iminvec[3].rank, imaxvec[3].value, imaxvec[3].rank, ml_memory_label); printf(" total %11d %11d (%5d) %11d (%5d) %s\n", iavgvec[4], iminvec[4].value, iminvec[4].rank, imaxvec[4].value, imaxvec[4].rank, ml_memory_label); printf(" %% used %9.1f %9.1f (%5d) %9.1f (%5d) %s\n", ((double)iavgvec[5])/10., ((double)iminvec[5].value)/10., iminvec[5].rank, ((double)imaxvec[5].value)/10., imaxvec[5].rank, ml_memory_label); printf(" time %9.1f %9.1f (%5d) %9.1f (%5d) %s\n", davgvec[0],dminvec[0].value,dminvec[0].rank, dmaxvec[0].value, dmaxvec[0].rank, ml_memory_label); if (haveMemInfo) { printf(" swap free %11d %11d (%5d) %11d (%5d) %s\n", iavgvec[6], iminvec[6].value,iminvec[6].rank, imaxvec[6].value, iminvec[6].rank, ml_memory_label); printf(" swap used %11d %11d (%5d) %11d (%5d) %s\n", iavgvec[7], iminvec[7].value, iminvec[7].rank, imaxvec[7].value, imaxvec[7].rank, ml_memory_label); printf(" total swap %11d %11d (%5d) %11d (%5d) %s\n", iavgvec[8], iminvec[8].value, iminvec[8].rank, imaxvec[8].value, imaxvec[8].rank, ml_memory_label); printf(" %% swap used %9.1f %9.1f (%5d) %9.1f (%5d) %s\n", ((double)iavgvec[9])/10., ((double)iminvec[9].value)/10., iminvec[9].rank, ((double)imaxvec[9].value)/10., imaxvec[9].rank, ml_memory_label); } } /*if (id == 0 ... */ return(ml_memory_label); #else return(NULL); #endif } /*ML_memory_check*/
int main(int argc, char *argv[]) { register uint i,j; uint ant,n1,n2,n3; uint write_count,update,opt_delete,check2,dupp_keys,found_key; int error; ulong pos; unsigned long key_check; uchar record[128],record2[128],record3[128],key[10]; const char *filename,*filename2; HP_INFO *file,*file2; HP_SHARE *tmp_share; HP_KEYDEF keyinfo[MAX_KEYS]; HA_KEYSEG keyseg[MAX_KEYS*5]; HEAP_PTR UNINIT_VAR(position); HP_CREATE_INFO hp_create_info; CHARSET_INFO *cs= &my_charset_latin1; my_bool unused; MY_INIT(argv[0]); /* init my_sys library & pthreads */ filename= "test2"; filename2= "test2_2"; file=file2=0; get_options(argc,argv); bzero(&hp_create_info, sizeof(hp_create_info)); hp_create_info.max_table_size= 2*1024L*1024L; hp_create_info.keys= keys; hp_create_info.keydef= keyinfo; hp_create_info.reclength= reclength; hp_create_info.max_records= (ulong) flag*100000L; hp_create_info.min_records= (ulong) recant/2; write_count=update=opt_delete=0; key_check=0; keyinfo[0].seg=keyseg; keyinfo[0].keysegs=1; keyinfo[0].flag= 0; keyinfo[0].algorithm= HA_KEY_ALG_HASH; keyinfo[0].seg[0].type=HA_KEYTYPE_BINARY; keyinfo[0].seg[0].start=0; keyinfo[0].seg[0].length=6; keyinfo[0].seg[0].null_bit=0; keyinfo[0].seg[0].charset=cs; keyinfo[1].seg=keyseg+1; keyinfo[1].keysegs=2; keyinfo[1].flag=0; keyinfo[1].algorithm= HA_KEY_ALG_HASH; keyinfo[1].seg[0].type=HA_KEYTYPE_BINARY; keyinfo[1].seg[0].start=7; keyinfo[1].seg[0].length=6; keyinfo[1].seg[0].null_bit=0; keyinfo[1].seg[0].charset=cs; keyinfo[1].seg[1].type=HA_KEYTYPE_TEXT; keyinfo[1].seg[1].start=0; /* key in two parts */ keyinfo[1].seg[1].length=6; keyinfo[1].seg[1].null_bit=0; keyinfo[1].seg[1].charset=cs; keyinfo[2].seg=keyseg+3; keyinfo[2].keysegs=1; keyinfo[2].flag=HA_NOSAME; keyinfo[2].algorithm= HA_KEY_ALG_HASH; keyinfo[2].seg[0].type=HA_KEYTYPE_BINARY; keyinfo[2].seg[0].start=12; keyinfo[2].seg[0].length=8; keyinfo[2].seg[0].null_bit=0; keyinfo[2].seg[0].charset=cs; keyinfo[3].seg=keyseg+4; keyinfo[3].keysegs=1; keyinfo[3].flag=HA_NOSAME; keyinfo[3].algorithm= HA_KEY_ALG_HASH; keyinfo[3].seg[0].type=HA_KEYTYPE_BINARY; keyinfo[3].seg[0].start=37; keyinfo[3].seg[0].length=1; keyinfo[3].seg[0].null_bit=1; keyinfo[3].seg[0].null_pos=38; keyinfo[3].seg[0].charset=cs; bzero((char*) key1,sizeof(key1)); bzero((char*) key3,sizeof(key3)); printf("- Creating heap-file\n"); if (heap_create(filename, &hp_create_info, &tmp_share, &unused) || !(file= heap_open(filename, 2))) goto err; signal(SIGINT,endprog); printf("- Writing records:s\n"); strmov((char*) record," ..... key"); for (i=0 ; i < recant ; i++) { n1=rnd(1000); n2=rnd(100); n3=rnd(MY_MIN(recant*5,MAX_RECORDS)); make_record(record,n1,n2,n3,"Pos",write_count); if (heap_write(file,record)) { if (my_errno != HA_ERR_FOUND_DUPP_KEY || key3[n3] == 0) { printf("Error: %d in write at record: %d\n",my_errno,i); goto err; } if (verbose) printf(" Double key: %d\n",n3); } else { if (key3[n3] == 1) { printf("Error: Didn't get error when writing second key: '%8d'\n",n3); goto err; } write_count++; key1[n1]++; key3[n3]=1; key_check+=n1; } if (testflag == 1 && heap_check_heap(file,0)) { puts("Heap keys crashed"); goto err; } } if (testflag == 1) goto end; if (heap_check_heap(file,0)) { puts("Heap keys crashed"); goto err; } printf("- Delete\n"); for (i=0 ; i < write_count/10 ; i++) { for (j=rnd(1000)+1 ; j>0 && key1[j] == 0 ; j--) ; if (j != 0) { sprintf((char*) key,"%6d",j); if (heap_rkey(file,record,0,key,6, HA_READ_KEY_EXACT)) { printf("can't find key1: \"%s\"\n",(char*) key); goto err; } if (heap_delete(file,record)) { printf("error: %d; can't delete record: \"%s\"\n", my_errno,(char*) record); goto err; } opt_delete++; key1[atoi((char*) record+keyinfo[0].seg[0].start)]--; key3[atoi((char*) record+keyinfo[2].seg[0].start)]=0; key_check-=atoi((char*) record); if (testflag == 2 && heap_check_heap(file,0)) { puts("Heap keys crashed"); goto err; } } else puts("Warning: Skipping delete test because no dupplicate keys"); } if (testflag==2) goto end; if (heap_check_heap(file,0)) { puts("Heap keys crashed"); goto err; } printf("- Update\n"); for (i=0 ; i < write_count/10 ; i++) { n1=rnd(1000); n2=rnd(100); n3=rnd(MY_MIN(recant*2,MAX_RECORDS)); make_record(record2, n1, n2, n3, "XXX", update); if (rnd(2) == 1) { if (heap_scan_init(file)) goto err; j=rnd(write_count-opt_delete); while ((error=heap_scan(file,record) == HA_ERR_RECORD_DELETED) || (!error && j)) { if (!error) j--; } if (error) goto err; } else { for (j=rnd(1000)+1 ; j>0 && key1[j] == 0 ; j--) ; if (!key1[j]) continue; sprintf((char*) key,"%6d",j); if (heap_rkey(file,record,0,key,6, HA_READ_KEY_EXACT)) { printf("can't find key1: \"%s\"\n",(char*) key); goto err; } } if (heap_update(file,record,record2)) { if (my_errno != HA_ERR_FOUND_DUPP_KEY || key3[n3] == 0) { printf("error: %d; can't update:\nFrom: \"%s\"\nTo: \"%s\"\n", my_errno,(char*) record, (char*) record2); goto err; } if (verbose) printf("Double key when tried to update:\nFrom: \"%s\"\nTo: \"%s\"\n", (char*) record, (char*) record2); } else { key1[atoi((char*) record+keyinfo[0].seg[0].start)]--; key3[atoi((char*) record+keyinfo[2].seg[0].start)]=0; key1[n1]++; key3[n3]=1; update++; key_check=key_check-atoi((char*) record)+n1; } if (testflag == 3 && heap_check_heap(file,0)) { puts("Heap keys crashed"); goto err; } } if (testflag == 3) goto end; if (heap_check_heap(file,0)) { puts("Heap keys crashed"); goto err; } for (i=999, dupp_keys=found_key=0 ; i>0 ; i--) { if (key1[i] > dupp_keys) { dupp_keys=key1[i]; found_key=i; } sprintf((char*) key,"%6d",found_key); } if (dupp_keys > 3) { if (!silent) printf("- Read first key - next - delete - next -> last\n"); DBUG_PRINT("progpos",("first - next - delete - next -> last")); if (heap_rkey(file,record,0,key,6, HA_READ_KEY_EXACT)) goto err; if (heap_rnext(file,record3)) goto err; if (heap_delete(file,record3)) goto err; key_check-=atoi((char*) record3); key1[atoi((char*) record+keyinfo[0].seg[0].start)]--; key3[atoi((char*) record+keyinfo[2].seg[0].start)]=0; opt_delete++; ant=2; while ((error=heap_rnext(file,record3)) == 0 || error == HA_ERR_RECORD_DELETED) if (! error) ant++; if (ant != dupp_keys) { printf("next: I can only find: %d records of %d\n", ant,dupp_keys); goto end; } dupp_keys--; if (heap_check_heap(file,0)) { puts("Heap keys crashed"); goto err; } if (!silent) printf("- Read last key - delete - prev - prev - opt_delete - prev -> first\n"); if (heap_rprev(file,record)) goto err; if (heap_delete(file,record3)) goto err; key_check-=atoi((char*) record3); key1[atoi((char*) record+keyinfo[0].seg[0].start)]--; key3[atoi((char*) record+keyinfo[2].seg[0].start)]=0; opt_delete++; if (heap_rprev(file,record3) || heap_rprev(file,record3)) goto err; if (heap_delete(file,record3)) goto err; key_check-=atoi((char*) record3); key1[atoi((char*) record+keyinfo[0].seg[0].start)]--; key3[atoi((char*) record+keyinfo[2].seg[0].start)]=0; opt_delete++; ant=3; while ((error=heap_rprev(file,record3)) == 0 || error == HA_ERR_RECORD_DELETED) { if (! error) ant++; } if (ant != dupp_keys) { printf("next: I can only find: %d records of %d\n", ant,dupp_keys); goto end; } dupp_keys-=2; if (heap_check_heap(file,0)) { puts("Heap keys crashed"); goto err; } } else puts("Warning: Not enough duplicated keys: Skipping delete key check"); if (!silent) printf("- Read (first) - next - delete - next -> last\n"); DBUG_PRINT("progpos",("first - next - delete - next -> last")); if (heap_scan_init(file)) goto err; while ((error=heap_scan(file,record3) == HA_ERR_RECORD_DELETED)) ; if (error) goto err; if (heap_delete(file,record3)) goto err; key_check-=atoi((char*) record3); opt_delete++; key1[atoi((char*) record+keyinfo[0].seg[0].start)]--; key3[atoi((char*) record+keyinfo[2].seg[0].start)]=0; ant=0; while ((error=heap_scan(file,record3)) == 0 || error == HA_ERR_RECORD_DELETED) if (! error) ant++; if (ant != write_count-opt_delete) { printf("next: Found: %d records of %d\n",ant,write_count-opt_delete); goto end; } if (heap_check_heap(file,0)) { puts("Heap keys crashed"); goto err; } puts("- Test if: Read rrnd - same - rkey - same"); DBUG_PRINT("progpos",("Read rrnd - same")); pos=rnd(write_count-opt_delete-5)+5; heap_scan_init(file); i=5; while ((error=heap_scan(file,record)) == HA_ERR_RECORD_DELETED || (error == 0 && pos)) { if (!error) pos--; if (i-- == 0) { bmove(record3,record,reclength); position=heap_position(file); } } if (error) goto err; bmove(record2,record,reclength); if (heap_rsame(file,record,-1) || heap_rsame(file,record2,2)) goto err; if (memcmp(record2,record,reclength)) { puts("heap_rsame didn't find right record"); goto end; } puts("- Test of read through position"); if (heap_rrnd(file,record,position)) goto err; if (memcmp(record3,record,reclength)) { puts("heap_frnd didn't find right record"); goto end; } printf("- heap_info\n"); { HEAPINFO info; heap_info(file,&info,0); /* We have to test with opt_delete +1 as this may be the case if the last inserted row was a duplicate key */ if (info.records != write_count-opt_delete || (info.deleted != opt_delete && info.deleted != opt_delete+1)) { puts("Wrong info from heap_info"); printf("Got: records: %ld(%d) deleted: %ld(%d)\n", info.records,write_count-opt_delete,info.deleted,opt_delete); } } #ifdef OLD_HEAP_VERSION { uint check; printf("- Read through all records with rnd\n"); if (heap_extra(file,HA_EXTRA_RESET) || heap_extra(file,HA_EXTRA_CACHE)) { puts("got error from heap_extra"); goto end; } ant=check=0; while ((error=heap_rrnd(file,record,(ulong) -1)) != HA_ERR_END_OF_FILE && ant < write_count + 10) { if (!error) { ant++; check+=calc_check(record,reclength); } } if (ant != write_count-opt_delete) { printf("rrnd: I can only find: %d records of %d\n", ant, write_count-opt_delete); goto end; } if (heap_extra(file,HA_EXTRA_NO_CACHE)) { puts("got error from heap_extra(HA_EXTRA_NO_CACHE)"); goto end; } } #endif printf("- Read through all records with scan\n"); if (heap_reset(file) || heap_extra(file,HA_EXTRA_CACHE)) { puts("got error from heap_extra"); goto end; } ant=check2=0; heap_scan_init(file); while ((error=heap_scan(file,record)) != HA_ERR_END_OF_FILE && ant < write_count + 10) { if (!error) { ant++; check2+=calc_check(record,reclength); } } if (ant != write_count-opt_delete) { printf("scan: I can only find: %d records of %d\n", ant, write_count-opt_delete); goto end; } #ifdef OLD_HEAP_VERSION if (check != check2) { puts("scan: Checksum didn't match reading with rrnd"); goto end; } #endif if (heap_extra(file,HA_EXTRA_NO_CACHE)) { puts("got error from heap_extra(HA_EXTRA_NO_CACHE)"); goto end; } for (i=999, dupp_keys=found_key=0 ; i>0 ; i--) { if (key1[i] > dupp_keys) { dupp_keys=key1[i]; found_key=i; } sprintf((char*) key,"%6d",found_key); } printf("- Read through all keys with first-next-last-prev\n"); ant=0; for (error=heap_rkey(file,record,0,key,6, HA_READ_KEY_EXACT); ! error ; error=heap_rnext(file,record)) ant++; if (ant != dupp_keys) { printf("first-next: I can only find: %d records of %d\n", ant, dupp_keys); goto end; } ant=0; for (error=heap_rprev(file,record) ; ! error ; error=heap_rprev(file,record)) { ant++; check2+=calc_check(record,reclength); } if (ant != dupp_keys) { printf("last-prev: I can only find: %d records of %d\n", ant, dupp_keys); goto end; } if (testflag == 4) goto end; printf("- Reading through all rows through keys\n"); if (!(file2=heap_open(filename, 2))) goto err; if (heap_scan_init(file)) goto err; while ((error=heap_scan(file,record)) != HA_ERR_END_OF_FILE) { if (error == 0) { if (heap_rkey(file2,record2,2,record+keyinfo[2].seg[0].start,8, HA_READ_KEY_EXACT)) { printf("can't find key3: \"%.8s\"\n", record+keyinfo[2].seg[0].start); goto err; } } } heap_close(file2); printf("- Creating output heap-file 2\n"); hp_create_info.keys= 1; hp_create_info.max_records= 0; hp_create_info.min_records= 0; if (heap_create(filename2, &hp_create_info, &tmp_share, &unused) || !(file2= heap_open_from_share_and_register(tmp_share, 2))) goto err; printf("- Copying and removing records\n"); if (heap_scan_init(file)) goto err; while ((error=heap_scan(file,record)) != HA_ERR_END_OF_FILE) { if (error == 0) { if (heap_write(file2,record)) goto err; key_check-=atoi((char*) record); write_count++; if (heap_delete(file,record)) goto err; opt_delete++; } pos++; } printf("- Checking heap tables\n"); if (heap_check_heap(file,1) || heap_check_heap(file2,1)) { puts("Heap keys crashed"); goto err; } if (my_errno != HA_ERR_END_OF_FILE) printf("error: %d from heap_rrnd\n",my_errno); if (key_check) printf("error: Some read got wrong: check is %ld\n",(long) key_check); end: printf("\nFollowing test have been made:\n"); printf("Write records: %d\nUpdate records: %d\nDelete records: %d\n", write_count,update,opt_delete); heap_clear(file); if (heap_close(file) || (file2 && heap_close(file2))) goto err; heap_delete_table(filename2); hp_panic(HA_PANIC_CLOSE); my_end(MY_GIVE_INFO); return(0); err: printf("Got error: %d when using heap-database\n",my_errno); (void) heap_close(file); return(1); } /* main */