static void router_test2(void) { int i; struct node_t* node; struct node_t* result[8]; static struct node_t s_nodes[100000]; uint8_t id[N_NODEID] = { 0xAB, 0xCD, 0xEF, 0x89, }; heap_t* heap, *heap2; struct router_t* router; router = router_create(id); heap = heap_create(node_compare_less, (void*)id); heap_reserve(heap, 8 + 1); for (i = 0; i < sizeof(s_nodes) / sizeof(s_nodes[0]); i++) { int v = rand(); memset(&s_nodes[i], 0, sizeof(s_nodes[i])); memcpy(s_nodes[i].id, &v, sizeof(v)); s_nodes[i].ref = 1; if (0 == router_add(router, s_nodes[i].id, &s_nodes[i].addr, &node)) { heap_push(heap, node); if (heap_size(heap) > 8) { node_release((struct node_t*)heap_top(heap)); heap_pop(heap); } } } assert(8 == heap_size(heap)); assert(8 == router_nearest(router, id, result, 8)); heap2 = heap_create(node_compare_less, (void*)id); heap_reserve(heap2, 8); for (i = 0; i < 8; i++) { heap_push(heap2, result[i]); } assert(heap_size(heap) == heap_size(heap2)); for (i = 0; i < 8; i++) { assert(heap_top(heap2) == heap_top(heap)); heap_pop(heap); heap_pop(heap2); } router_destroy(router); heap_destroy(heap); heap_destroy(heap2); printf("router test ok!\n"); }
void case_heap_pushpop() { struct heap *heap = heap(heap_cmp); int a = 3, b = 2, c = 4; assert(*(int *)heap_pushpop(heap, (void *)&a) == 3); assert(heap_push(heap, (void *)&b) == HEAP_OK); assert(heap_push(heap, (void *)&c) == HEAP_OK); assert(*(int *)heap_pushpop(heap, (void *)&a) == 2); heap_free(heap); }
void case_heap_len() { struct heap *heap = heap(heap_cmp); assert(heap_len(heap) == 0); int a = 1, b = 2, c = 3; assert(heap_push(heap, (void *)&a) == HEAP_OK); assert(heap_push(heap, (void *)&b) == HEAP_OK); assert(heap_push(heap, (void *)&c) == HEAP_OK); assert(heap_len(heap) == 3); heap_free(heap); }
Flow* createFlow(Packet* p, bool virtual_f) { Flow* f = flow_create(p); if (virtual_f == TRUE) heap_push(virtual_flows, f); else heap_push(flows, f); return f; }
void solve_maze() { int i,j,x,y,bx,by,tx,ty,goal,nx,ny,nbx,nby,cost,dist; for(i=0;i<MAXDIM*MAXDIM*MAXDIM*MAXDIM;i++) { st[i].dist = MAXDIM*MAXDIM*MAXDIM*MAXDIM*MAXDIM*MAXDIM+1; st[i].heap = st[i].last = 0; } heap_init(); for(i=0;i<r;i++) for(j=0;j<c;j++) switch(m[i][j]) { case 'S': x = j; y = i; m[i][j] = '.'; break; case 'B': bx = j; by = i; m[i][j] = '.'; break; case 'T': tx = j; ty = i; m[i][j] = '.'; break; } heap_push(x,y,bx,by,0,0); while(heapsize != 0) { heap_pop(&x,&y,&bx,&by,&dist); for(i=0;i<4;i++) { nx = x+dx[i]; ny = y+dy[i]; cost = 1; if(nx == bx && ny == by) { nbx = bx+dx[i]; nby = by+dy[i]; cost += MAXDIM*MAXDIM*MAXDIM*MAXDIM; } else { nbx = bx; nby = by; } if(nx >= 0 && nx < c && ny >= 0 && ny < r && nbx >= 0 && nbx < c && nby >= 0 && nby < r && m[ny][nx] == '.' && m[nby][nbx] == '.') heap_push(nx,ny,nbx,nby,dist+cost,cost==1?walk[i]:push[i]); } } x = y = 0; for(i=0;i<r;i++) for(j=0;j<c;j++) if(st[j+i*MAXDIM+tx*MAXDIM*MAXDIM+ty*MAXDIM*MAXDIM*MAXDIM].dist < st[x+y*MAXDIM+tx*MAXDIM*MAXDIM+ty*MAXDIM*MAXDIM*MAXDIM].dist) { x = j; y = i; } goal = x+y*MAXDIM+tx*MAXDIM*MAXDIM+ty*MAXDIM*MAXDIM*MAXDIM; if(st[goal].dist > MAXDIM*MAXDIM*MAXDIM*MAXDIM*MAXDIM*MAXDIM) printf("Impossible."); else rec_print(x,y,tx,ty); printf("\n\n"); }
int main() { struct heap heap; int result = heap_init(&heap, int_compare); assert(result == 0); assert(heap_empty(&heap)); assert(heap_size(&heap) == 0); static const intptr_t VALUES[] = {12, 2955, 7, 99, 51, 1, 691050}; static const intptr_t EXPECTED[] = {1, 7, 12, 51, 99, 2955, 691050}; int count = sizeof(VALUES) / sizeof(VALUES[0]); for (int i = 0; i < count; i++) { result = heap_push(&heap, (void*)VALUES[i]); assert(result == 0); } assert(heap_size(&heap) == count); assert(!heap_empty(&heap)); assert((intptr_t)heap_min(&heap) == (intptr_t)1); assert(heap_size(&heap) == count); for (int i = 0; i < count; i++) { intptr_t value = (intptr_t)heap_pop_min(&heap); assert(value == EXPECTED[i]); } assert(heap_empty(&heap)); assert(heap_size(&heap) == 0); assert(heap_min(&heap) == NULL); assert(heap_pop_min(&heap) == NULL); // Repeat reordered static const intptr_t VALUES2[] = {2955, 12, 691050, 99, 51, 1, 7}; for (int i = 0; i < count; i++) { result = heap_push(&heap, (void*)VALUES2[i]); assert(result == 0); } for (int i = 0; i < count; i++) { intptr_t value = (intptr_t)heap_pop_min(&heap); assert(value == EXPECTED[i]); } assert(heap_empty(&heap)); assert(heap_size(&heap) == 0); assert(heap_min(&heap) == NULL); assert(heap_pop_min(&heap) == NULL); heap_free(&heap); return 0; }
/* n-way merge sort to stdout */ void merge_sort(const seq_dumps_t* d, int (*cmp)(const void*, const void*)) { FILE** files = malloc_or_die(d->n * sizeof(FILE*)); size_t i; for (i = 0; i < d->n; ++i) { files[i] = fopen(d->fns[i], "rb"); if (files[i] == NULL) { fprintf(stderr, "Cannot open temporary file %s for reading.\n", d->fns[i]); exit(EXIT_FAILURE); } } fastq_t** fs = malloc_or_die(d->n * sizeof(fastq_t*)); seq_t** seqs = malloc_or_die(d->n * sizeof(seq_t*)); for (i = 0; i < d->n; ++i) { fs[i] = fastq_create(files[i]); seqs[i] = seq_create(); } /* A binary heap of indexes to fs. We use this to repeatedly pop the * smallest fastq entry. */ size_t* heap = malloc_or_die(d->n * sizeof(size_t)); /* heap size */ size_t m = 0; for (i = 0; i < d->n; ++i) { if (fastq_read(fs[i], seqs[i])) { heap_push(heap, d->n, &m, seqs, cmp, i); } } while (m > 0) { i = heap_pop(heap, &m, seqs, cmp); fastq_print(stdout, seqs[i]); if (fastq_read(fs[i], seqs[i])) { heap_push(heap, d->n, &m, seqs, cmp, i); } } for (i = 0; i < d->n; ++i) { seq_free(seqs[i]); fastq_free(fs[i]); fclose(files[i]); } free(files); free(fs); }
void case_heap_pop() { struct heap *heap = heap(heap_cmp); int a = 3, b = 1, c = 2, d = 4; assert(heap_push(heap, (void *)&a) == HEAP_OK); assert(heap_push(heap, (void *)&b) == HEAP_OK); assert(heap_push(heap, (void *)&c) == HEAP_OK); assert(heap_push(heap, (void *)&d) == HEAP_OK); assert(heap_len(heap) == 4); assert(*(int *)heap_pop(heap) == 1); assert(*(int *)heap_pop(heap) == 2); assert(*(int *)heap_pop(heap) == 3); assert(*(int *)heap_pop(heap) == 4); assert(heap_len(heap) == 0); heap_free(heap); }
static int heap_push_many(heap *h, size_t ni, heap_item *hi) { size_t i; for (i = 0; i < ni; ++i) if (heap_push(h, hi[i])) return FAILURE; return SUCCESS; }
huf_tree huf_build_tree(symbol *data, size_t length){ huf_node *trees = (huf_node *)malloc_or_die(2*HUF_SYMBOLS*sizeof(huf_node)); huf_node *newTree = trees; heap_node heapNodes[HUF_SYMBOLS]; heap_node *newHeapNode = heapNodes; heap_node *_heap[HUF_SYMBOLS]; heap_node **heap = _heap-1; size_t heapSize = 0; int freqs[HUF_SYMBOLS]; symbol s; int i; for(s=0; s<HUF_SYMBOLS; s++){ freqs[s] = 0; } for(i=0; i<length; i++){ freqs[data[i]]++; } freqs[HUF_EOF] = 1; for(s=0; s<HUF_SYMBOLS; s++){ if(freqs[s]>0){ newTree->symbol = s; newTree->left = NULL; newTree->right = NULL; newHeapNode->tree = newTree++; newHeapNode->freq = freqs[s]; heap_push(heap, heapSize++, newHeapNode++); } } for(; heapSize>=2; heapSize--){ heap_node *n1 = heap_pop(heap, heapSize); heap_node *n2 = heap_pop(heap, heapSize-1); newTree->left = n1->tree; newTree->right = n2->tree; n2->tree = newTree++; // reuse the old heap node n2->freq += n1->freq; heap_push(heap, heapSize-2, n2); } huf_tree t = {heap_pop(heap, heapSize)->tree, trees}; return t; }
void memory_init() { U8 *p_end = (U8*) &Image$$RW_IRAM1$$ZI$$Limit; int i; // 4 bytes Padding p_end += 4; // Allocate memory for pcb pointers gp_pcbs = (PCB**) p_end; p_end += NUM_PROCS * sizeof(PCB*); for (i = 0; i < NUM_PROCS; i++) { gp_pcbs[i] = (PCB*) p_end; p_end += sizeof(PCB); gp_pcbs[i]->message_queue = (MSG_QUEUE*) p_end; gp_pcbs[i]->message_queue->first = NULL; gp_pcbs[i]->message_queue->last = NULL; p_end += sizeof(MSG_QUEUE); } // Timeout queue gp_timeout_queue = (MSG_QUEUE*) p_end; gp_timeout_queue->first = NULL; gp_timeout_queue->last = NULL; p_end += sizeof(MSG_QUEUE); // Input buffer from uart gp_input_buffer = (char*) p_end; p_end += 20 * sizeof(char); for (i = 0; i < 20; i++) { gp_input_buffer[i] = NULL; } // Allocate memory for priority queue gp_pcb_queue = (PROC_QUEUE**) p_end; p_end += NUM_PROC_PRIORITY * sizeof(PROC_QUEUE*); for (i = 0; i < NUM_PROC_PRIORITY; i++) { gp_pcb_queue[i] = (PROC_QUEUE*) p_end; gp_pcb_queue[i]->first = NULL; gp_pcb_queue[i]->last = NULL; p_end += sizeof(PROC_QUEUE); } // Prepare alloc_stack() for stack memory allocation gp_stack = (U32*) RAM_END_ADDR; if ((U32) gp_stack & 0x04) { --gp_stack; } // Allocate memory for heap p_heap = NULL; for (i = 0; i < NUM_MEMORY_BLOCKS; i++) { MEMORY_BLOCK *block = (MEMORY_BLOCK*) p_end; heap_push(&p_heap, block); p_end += sizeof(MEMORY_BLOCK*) + MEMORY_BLOCK_SIZE; } }
void case_heap_clear() { struct heap *heap = heap(heap_cmp); int a = 1; assert(heap_push(heap, (void *)&a) == HEAP_OK); assert(heap_len(heap) == 1); assert(heap_cap(heap) == 1); heap_clear(heap); assert(heap_len(heap) == 0); heap_free(heap); }
void my_heapsort(int* numbers, int size) { int i; int* heap = malloc(sizeof(int) * size); for (i = 0; i < size; i++) { heap_push(heap, i, numbers[i]); } for (i = 0; i < size; i++) { numbers[i] = heap_pop(heap, size - i); } }
void heap_sort(T *array, int size) { for(int heap_size = 0; heap_size < size; heap_size++) { heap_push(array, heap_size, array[heap_size]); } for(int heap_size = size; heap_size > 0; heap_size--) { array[heap_size-1] = heap_pop(array, heap_size); } }
// pop next flow, dequeue next packet, push flow back to heap Packet* removePacketFromBuffer(bool virtual_f) { FHeap* heap = virtual_f ? virtual_flows : flows; Flow* flow = heap_front(heap); heap_pop(heap, flow); Packet* pkt = flow_dequeue(flow); heap_push(heap, flow); return pkt; }
static void MY_enqueue(struct run_queue *rq, struct proc_struct *proc) { proc->rq = rq; // running queue that contains process rq->proc_num ++; // heap part heap_entry_t elm; elm.proc = (int *)proc; elm.x = proc->pt; heap_push(heap, elm); }
void heapsort(int *arr, int num_elems) { int i; heap *h=heap_new(); for(i=0; i<num_elems; i++) { heap_push(h, arr[i]); } for(i=0; i<num_elems; i++) { arr[i]=heap_pop(h); } heap_free(h); }
void case_heap_push(struct bench_ctx *ctx) { struct heap *heap = heap(&heap_bench_cmp); int i; bench_ctx_reset_start_at(ctx); for (i = 0; i < ctx->n; i++) { heap_push(heap, &i); } bench_ctx_reset_end_at(ctx); heap_free(heap); }
void FinderActor::addToFoundPeers(Peer::SPtr p) { Distance dist(requestedId, p->id); for(auto it = foundPeers.begin(); it != foundPeers.end(); it++) { if((*it).second->id == p->id) { return; } } heap_push(foundPeers, std::make_pair(dist, p)); if(foundPeers.size() > (unsigned long) countToFind) { heap_pop_no_res(foundPeers); } }
void timer_add_debug(const char *function, const char *file, int line, suptimer_t *tmr, int increment) { debug_assert(tmr->target == IMPOSSIBLE_FUTURE, "Adding already running timer (%s) at %s in %s:%i.", tmr->name, function, file, line); timer_fill_target(tmr, increment); #if DEBUG_TIMERS debug_log(10, "add_timer(%s, %i)\n", tmr->name, increment); #endif heap_push(&timers, &tmr->item); }
void FinderActor::addToShortList(Peer::SPtr p) { Distance dist(requestedId, p->id); //I have a problem with containers here I need a container that can be a priority_queue //on which I can make a search for an element. //I'm making a manual search instead for(auto it = shortlist.begin(); it != shortlist.end(); it++) { if((*it).first == dist) { return; } } heap_push(shortlist, std::make_pair(dist, p)); if((int)shortlist.size() > FIND_PARALLEL_QUERIES) { heap_pop_no_res(shortlist); } }
void case_heap_repalce() { struct heap *heap = heap(heap_cmp); int a = 3, b = 2, c = 5, d = 7, e = 4, f = 6, g = 1, h = 4; assert(heap_push(heap, (void *)&a) == HEAP_OK); assert(heap_push(heap, (void *)&b) == HEAP_OK); assert(heap_push(heap, (void *)&c) == HEAP_OK); assert(heap_push(heap, (void *)&d) == HEAP_OK); assert(heap_push(heap, (void *)&e) == HEAP_OK); assert(heap_push(heap, (void *)&f) == HEAP_OK); assert(heap_push(heap, (void *)&g) == HEAP_OK); assert(1 == *(int *)heap_replace(heap, (void *)&h)); assert(2 == *(int *)heap_pop(heap)); assert(3 == *(int *)heap_pop(heap)); assert(4 == *(int *)heap_pop(heap)); heap_free(heap); }
/**************************************************************************************** * Function name - tq_dispatch_nearest_timer * * Description - Removes nearest timer from the queue, calls for handle_timer () * of the timer node kept as timer context. Internally performs * necessary rearrangements of the queue, re-schedules periodic * timers and manages memory agaist mpool, if required. * * Input - *tq - pointer to a timer queue, e.g. heap * *vp_param - void pointer passed parameter * now_time - current time since epoch in msec * * Return Code/Output - On success - 0, on error -1 ****************************************************************************************/ int tq_dispatch_nearest_timer (timer_queue*const tq, void* vp_param, unsigned long now_time) { heap* h = (heap *) tq; hnode* top_node = heap_top_node ((heap *const) tq); hnode* node = heap_pop ((heap *const) tq, ((timer_node *) top_node->ctx)->period ? 1 : 0); timer_node* tnode = (timer_node *) node->ctx; int rval = tnode->func_timer (tnode, vp_param, now_time); if (rval) goto node_return; if (tnode->period) { tnode->next_timer = now_time + tnode->period; if (heap_push (tq, node, 1) == -1) { fprintf (stderr, "%s - error: heap_push () failed.\n", __func__); rval = -1; goto node_return; } return 0; } node_return: if (tnode->period) { release_kept_timer_id (tq, tnode->timer_id); } node_reset (node); if (mpool_return_obj (h->nodes_mpool, (allocatable *)node) == -1) { return -1; } return rval; }
void heap_update(Heap *heap, void *data, float new_cost) { int i; int current; current = -1; for (i = 0; i < heap->tail; i++) { if (heap->buffer[i].data == data) { current = i; break; } } if (current == -1) { heap_push(heap, data, new_cost); } else { heap_bubble_up(heap, current); } }
void case_heap_del() { struct heap *heap = heap(heap_cmp); int a = 3, b = 2, c = 5, d = 7, e = 4, f = 6, g = 1, h = 4; assert(heap_push(heap, (void *)&a) == HEAP_OK); assert(heap_push(heap, (void *)&b) == HEAP_OK); assert(heap_push(heap, (void *)&c) == HEAP_OK); assert(heap_push(heap, (void *)&d) == HEAP_OK); assert(heap_push(heap, (void *)&e) == HEAP_OK); assert(heap_push(heap, (void *)&f) == HEAP_OK); assert(heap_push(heap, (void *)&g) == HEAP_OK); assert(4 == *(int *)heap_del(heap, 4)); /* this assert means nothing */ assert(heap_len(heap) == 6); assert(1 == *(int *)heap_pop(heap)); assert(2 == *(int *)heap_pop(heap)); assert(3 == *(int *)heap_pop(heap)); assert(heap_push(heap, (void *)&h) == HEAP_OK); assert(4 == *(int *)heap_pop(heap)); assert(5 == *(int *)heap_pop(heap)); assert(6 == *(int *)heap_pop(heap)); assert(7 == *(int *)heap_pop(heap)); heap_free(heap); }
/**************************************************************************************** * Function name - tq_schedule_timer * * Description - Schedules timer, using timer-node information * * Input - *tq - pointer to an allocated timer queue, e.g. heap * *tnode - pointer to the user-allocated timer node with filled * next-timer and, optionally, period. Timer handling function * should be also set to the tnode to be dispatched by * tq_dispatch_nearest_timer(), * * Return Code/Output - On success - timer-id to be used in tq_cancel_timer (), * on error -1 ****************************************************************************************/ long tq_schedule_timer (timer_queue*const tq, timer_node* const tnode) { if (!tq || !tnode) { fprintf (stderr, "%s - error: wrong input.\n", __func__); return -1; } // mark timer-id as not valid tnode->timer_id = -1; if (tnode->period && tnode->period < TQ_RESOLUTION) { fprintf (stderr, "%s - error: tnode fields outside of valid range: next_timer (%ld), period (%ld).\n", __func__, tnode->next_timer, tnode->period); return -1; } heap * h = (heap *) tq; hnode* new_hnode = (hnode *) mpool_take_obj (h->nodes_mpool); if (!new_hnode) { fprintf (stderr, "%s - error: allocation of a new hnode from pool failed.\n", __func__); return -1; } else { new_hnode->ctx = tnode; } /* Push the new timer node to the heap. Zero passed as an indication, that it is a new timer rather than re-scheduling of a periodic timer. */ return (tnode->timer_id = heap_push (tq, new_hnode, 0)); }
int k_release_memory_block(void *memory_block) { PCB* blocked_process; if (memory_block == NULL) { return RTX_ERR; } // Check for blocked resources blocked_process = (PCB*) process_peek_block(gp_pcb_queue); if (blocked_process != NULL) { // Give block to blocked resource blocked_process->memory_block = (U32*) memory_block; blocked_process->state = READY; // Switch process if higher priority unblocked k_release_processor(); } else { // Push back onto heap heap_push(&p_heap, memory_block); } return RTX_OK; }
static void test_heap(void) { const size_t nums_size = rand() % 3000 + 1; int *nums = malloc(nums_size * sizeof *nums); for (size_t i = 0; i < nums_size; i++) nums[i] = rand(); const size_t heap_size = rand() % 1000 + 1; int *heap_data = malloc(heap_size * sizeof *nums); struct heap heap = VB_HEAP_INIT(heap_data, heap_size); for (size_t i = 0; i < nums_size; i++) heap_push(&heap, nums[i]); heap_finish(&heap); qsort(nums, nums_size, sizeof *nums, intpcmp); for (size_t i = 0; i < heap.size; i++) assert(heap.data[i] == nums[i]); free(nums); free(heap_data); }
BOOL priqueue_insert(struct PriQueue *priqueue, void *data) { assert(priqueue != NULL); return heap_push(priqueue->heap, data); }
void sort(char *inputfile, char *outputfile, int numattrs, int attributes[], int bufsize) { // open stream to read data file printf("Buffer size: %d bytes\n", bufsize); printf("Block size: %d bytes\n", DISK_BLOCK_SIZE); printf("Reading from: %s\n", inputfile); FILE *in = fopen(inputfile, "r"); // read metadata metadata m; m.record_size = m.header_size = 0; fread(&m.numattrs, sizeof(unsigned int), 1, in); m.header_size += sizeof(unsigned int) + 2 * m.numattrs * sizeof(int); m.attrlist = (attribute *) malloc(sizeof(attribute) * m.numattrs); printf("Header size: %d bytes\n", m.header_size); int i, j; for (i = 0; i < m.numattrs; i++) { fread(&m.attrlist[i].type, sizeof(int), 1, in); fread(&m.attrlist[i].size, sizeof(int), 1, in); m.record_size += m.attrlist[i].size; } printf("Record size: %d bytes\n", m.record_size); _meta = m; _meta.num_comp_attrs = numattrs; _meta.comparable_attrs = attributes; // max no. of disk blocks that fit in the buffer int num_records_in_buffer = bufsize / m.record_size; int num_records_in_block = DISK_BLOCK_SIZE / m.record_size; int num_blocks_in_buffer = bufsize / DISK_BLOCK_SIZE; printf("Records in block: %d\n", num_records_in_block); printf("Blocks in buffer: %d \n", num_blocks_in_buffer); // the buffer char *buffer = (char *) malloc(bufsize); // create the initial set of runs size_t records_read, records_written; i = 0; char run_name[20]; FILE *out; unsigned int num_recs_read = 0; unsigned int num_recs_written = 0; while (1) { records_read = fread(buffer, m.record_size, num_records_in_buffer, in); if (records_read == 0) break; num_recs_read += records_read; // sort the chunk qsort(buffer, records_read, m.record_size, compare_records); // write sorted chunk to a run file i++; sprintf(run_name, "run_%d.bin", i); out = fopen(run_name, "w"); write_metadata(out, m); records_written = fwrite(buffer, m.record_size, records_read, out); num_recs_written += records_written; fclose(out); } printf("Read %d records from input file.\n", num_recs_read); // number of generated runs int init_num_runs = i; printf("Number of initial runs generated: %d\nMerging...\n", i); /********************************* MERGE ********************************/ // number of runs in a pass int num_runs = init_num_runs; // max no. of runs we can merge at once int max_merge_runs = (bufsize / DISK_BLOCK_SIZE) - 1; int start = 1; int interm_runp = 1; char temp_run_name[20]; int runs_left_this_pass = num_runs; // run multiple passes over the runs to merge into one file while (1) { // check if we have to move to the next pass if (runs_left_this_pass == 0) { start = 1; interm_runp = 1; int merged_at_once = (num_runs < max_merge_runs ? num_runs : max_merge_runs); if (num_runs == merged_at_once) { // the final merged output of all runs is in run_1.bin // rename it to 'outputfile' rename("run_1.bin", outputfile); printf("Done.\nOutput written to: %s\n", outputfile); break; } num_runs = (num_runs / merged_at_once) + 1 * (num_runs % merged_at_once != 0); runs_left_this_pass = num_runs; } // decide how many runs to merge at once int merge_at_once = (runs_left_this_pass < max_merge_runs ? runs_left_this_pass : max_merge_runs); sprintf(temp_run_name, "run_temp.bin"); // how much to read from one run file int blocks_per_run = (bufsize / (merge_at_once + 1)) / DISK_BLOCK_SIZE; int records_per_run = blocks_per_run * num_records_in_block; int bytes_per_run = blocks_per_run * num_records_in_block * m.record_size; // read from runs into buffer FILE **runs = (FILE **) malloc(merge_at_once * sizeof(FILE *)); char **run_pointers = (char **) malloc((merge_at_once + 1) * sizeof(char *)); char **run_bp = (char **) malloc((merge_at_once + 1) * sizeof(char *)); char **run_ep = (char **) malloc((merge_at_once + 1) * sizeof(char *)); heap *HEAP = (heap *) malloc(sizeof(heap)); heap_init(HEAP, compare_records); for (i = 0; i < merge_at_once; i++) { sprintf(run_name, "run_%d.bin", i + start); runs[i] = fopen(run_name, "r"); fseek(runs[i], m.header_size, SEEK_SET); char *buffer_start_addr = buffer + i * bytes_per_run; fread(buffer_start_addr, num_records_in_block * m.record_size, blocks_per_run, runs[i]); run_bp[i] = buffer_start_addr; heap_push(HEAP, run_bp[i]); run_pointers[i] = run_bp[i] + m.record_size; run_ep[i] = run_bp[i] + bytes_per_run; } // the output buffer run_bp[i] = run_pointers[i] = buffer + i * bytes_per_run; // open a temporary run file for storing merged contents of all the generated runs FILE *temp_out = fopen(temp_run_name, "w"); write_metadata(temp_out, m); fclose(temp_out); // read chunks of data from each run file into a heap // and write to a temp run file until all the run files become empty num_recs_read = 0; int push = 0; int read_from_runs = 0; while (1) { // get min record from heap, and compute the index of the parent run void *min_rec = heap_pop(HEAP); if (!min_rec) { // write out whatever is left in the output buffer and exit if (run_pointers[merge_at_once] > run_bp[merge_at_once]) { FILE *output_run = fopen(temp_run_name, "a"); size_t check = fwrite(run_bp[merge_at_once], 1, run_pointers[merge_at_once] - run_bp[merge_at_once], output_run); fclose(output_run); // printf("Emptying output buffer, writing %d bytes\n", check); } break; } int min_rec_run = get_run_number(min_rec, run_bp, merge_at_once); // copy the min record popped from the heap into the output run memcpy(run_pointers[merge_at_once], min_rec, m.record_size); run_pointers[merge_at_once] += m.record_size; // fetch a new record from the run and push into heap, // adjusting the run pointer if (run_pointers[min_rec_run - 1] < run_ep[min_rec_run - 1]) { heap_push(HEAP, run_pointers[min_rec_run - 1]); push++; run_pointers[min_rec_run - 1] += m.record_size; } else if (run_pointers[min_rec_run - 1] >= run_ep[min_rec_run - 1]) { size_t check = fread(run_bp[min_rec_run - 1], m.record_size, records_per_run, runs[min_rec_run - 1]); read_from_runs += check; // reset the run pointer if (check > 0) { run_pointers[min_rec_run - 1] = run_bp[min_rec_run - 1]; run_ep[min_rec_run - 1] = run_bp[min_rec_run - 1] + check * m.record_size; // push first record from fresh lot into heap heap_push(HEAP, run_pointers[min_rec_run - 1]); push++; run_pointers[min_rec_run - 1] += m.record_size; } } // check for overflow of the output run, // write to output run if an overflow is detected if (run_pointers[merge_at_once] >= run_bp[merge_at_once] + bytes_per_run) { FILE *output_run = fopen(temp_run_name, "a"); size_t check = fwrite(run_bp[merge_at_once], m.record_size, records_per_run, output_run); fclose(output_run); num_recs_read += check; // reset the run pointer run_pointers[merge_at_once] = run_bp[merge_at_once]; } } // clean up heap_destroy(HEAP); free(HEAP); free(run_ep); free(run_bp); free(run_pointers); for (i = 0; i < merge_at_once; i++) fclose(runs[i]); free(runs); // delete run files used to build this run file for (i = 0; i < merge_at_once; i++) { sprintf(run_name, "run_%d.bin", i + start); remove(run_name); } // compute number of runs left in this pass runs_left_this_pass -= merge_at_once; start += merge_at_once; // rename temp file to run_<index>.bin sprintf(run_name, "run_%d.bin", interm_runp); interm_runp++; rename(temp_run_name, run_name); // printf("Merged %d - %d into %s\n", start - merge_at_once, start - 1, run_name); } /************************* END MERGE *************************************/ // clean up free(m.attrlist); free(buffer); // close the input data file fclose(in); }