Пример #1
0
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");
}
Пример #2
0
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);
}
Пример #3
0
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);
}
Пример #4
0
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;
}
Пример #5
0
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");
}
Пример #6
0
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;
}
Пример #7
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);
}
Пример #8
0
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);
}
Пример #9
0
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;
}
Пример #10
0
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;
}
Пример #11
0
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;
	}
}
Пример #12
0
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);
}
Пример #13
0
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);
    }
}
Пример #15
0
// 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;
}
Пример #16
0
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);
}
Пример #17
0
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);
}
Пример #18
0
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);
}
Пример #19
0
    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);
        }
    }
Пример #20
0
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);
}
Пример #21
0
    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);
        }
    }
Пример #22
0
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);
}
Пример #23
0
/****************************************************************************************
* 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;
}
Пример #24
0
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);
	}
}
Пример #25
0
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);
}
Пример #26
0
/****************************************************************************************
* 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));
}
Пример #27
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;
}
Пример #28
0
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);
}
Пример #29
0
BOOL
priqueue_insert(struct PriQueue *priqueue, void *data)
{
	assert(priqueue != NULL);
	return heap_push(priqueue->heap, data);
}
Пример #30
0
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);
}