static void do_event_loop(int timeout, bool sort_with_prio) { int i, nr; refresh: event_loop_refresh = false; nr = epoll_wait(efd, events, nr_events, timeout); if (sort_with_prio) xqsort(events, nr, epoll_event_cmp); if (nr < 0) { if (errno == EINTR) return; sd_err("epoll_wait failed: %m"); exit(1); } else if (nr) { for (i = 0; i < nr; i++) { struct event_info *ei; ei = (struct event_info *)events[i].data.ptr; ei->handler(ei->fd, events[i].events, ei->data); if (event_loop_refresh) goto refresh; } } }
static void vsort_xqsort(struct vsort_timing *vt, size_t loops) { size_t n = loops; while (n-- > 0) { memcpy(vt->copy, vt->data, vt->len); xqsort(vt->copy, vt->items, vt->isize, vsort_long_cmp); } }
void xqsort(void *base, size_t nel, size_t width, int (*compar)(const void *, const void *)) { char *i; char *lo, *hi; char *last,*mid; size_t size,lsize,rsize; if (nel < 2 || width == 0) return; lo = base; hi = (char *)base + (nel - 1)*width; size = (hi - lo) / width + 1; /* number of elements to sort */ mid = lo + (size / 2) * width; /* find middle element */ swap(lo,mid,width); last = lo; i = base + width; while( i <= hi ) { if (compar(lo,i) > 0) { last = last + width; swap(i,last,width); } i = i + width; } swap(lo,last,width); lsize = (last - lo) / width ; /* number of left elements */ rsize = (hi - last) / width ; /* number of right elements */ xqsort(lo,lsize ,width,compar); xqsort(last + width,rsize ,width,compar); return; }
// vuniq sorts the vector and then discards duplicates, // in the manner of sort | uniq. void vuniq(Vec *v) { int i, n; xqsort(v->p, v->len, sizeof(v->p[0]), strpcmp); n = 0; for(i=0; i<v->len; i++) { if(n>0 && streq(v->p[i], v->p[n-1])) xfree(v->p[i]); else v->p[n++] = v->p[i]; } v->len = n; }
/** * Dump the links sorted by decreasing leak size. */ G_GNUC_COLD void leak_dump(const leak_set_t *ls) { int count; struct filler filler; int i; leak_set_check(ls); count = htable_count(ls->stacks); if (count == 0) goto leaks_by_place; /* * Linearize hash table into an array before sorting it by * decreasing leak size. */ filler.leaks = xpmalloc(sizeof(struct leak) * count); filler.count = count; filler.idx = 0; filler.kt = LEAK_KEY_STACK; htable_foreach(ls->stacks, fill_array, &filler); xqsort(filler.leaks, count, sizeof(struct leak), leak_size_cmp); /* * Dump the leaks by allocation place. */ g_warning("leak summary by stackframe and total decreasing size:"); g_warning("distinct calling stacks found: %d", count); for (i = 0; i < count; i++) { struct leak *l = &filler.leaks[i]; size_t avg = l->lr->size / (0 == l->lr->count ? 1 : l->lr->count); g_warning("%zu bytes (%zu block%s, average %zu byte%s) from:", l->lr->size, l->lr->count, l->lr->count == 1 ? "" : "s", avg, 1 == avg ? "" : "s"); stacktrace_atom_decorate(stderr, l->u.sa, STACKTRACE_F_ORIGIN | STACKTRACE_F_SOURCE); } xfree(filler.leaks); leaks_by_place: count = htable_count(ls->places); if (count == 0) return; /* * Linearize hash table into an array before sorting it by * decreasing leak size. */ filler.leaks = xpmalloc(sizeof(struct leak) * count); filler.count = count; filler.idx = 0; filler.kt = LEAK_KEY_PLACE; htable_foreach(ls->places, fill_array, &filler); xqsort(filler.leaks, count, sizeof(struct leak), leak_size_cmp); /* * Dump the leaks by allocation place. */ g_warning("leak summary by origin and total decreasing size:"); g_warning("distinct allocation points found: %d", count); for (i = 0; i < count; i++) { struct leak *l = &filler.leaks[i]; size_t avg = l->lr->size / (0 == l->lr->count ? 1 : l->lr->count); g_warning("%zu bytes (%zu block%s, average %zu byte%s) from \"%s\"", l->lr->size, l->lr->count, l->lr->count == 1 ? "" : "s", avg, 1 == avg ? "" : "s", l->u.place); } xfree(filler.leaks); }
/* * Initialize the data vdi * * @vid: the vdi where the allocator resides */ int oalloc_init(uint32_t vid) { struct strbuf buf = STRBUF_INIT; struct sd_inode *inode = xmalloc(sizeof(struct sd_inode)); struct header hd = { .nr_free = 1, }; struct free_desc fd = { .start = 1, /* Use first object as the meta object */ .count = MAX_DATA_OBJS - 1, }; int ret; strbuf_add(&buf, &hd, sizeof(hd)); strbuf_add(&buf, &fd, sizeof(fd)); ret = sd_read_object(vid_to_vdi_oid(vid), (char *)inode, sizeof(*inode), 0); if (ret != SD_RES_SUCCESS) { sd_err("failed to read inode, %" PRIx32", %s", vid, sd_strerror(ret)); goto out; } ret = sd_write_object(vid_to_data_oid(vid, 0), buf.buf, buf.len, 0, true); if (ret != SD_RES_SUCCESS) { sd_err("failed to create meta object for %" PRIx32", %s", vid, sd_strerror(ret)); goto out; } sd_inode_set_vid(inode, 0, vid); ret = sd_inode_write_vid(inode, 0, vid, vid, 0, false, false); if (ret != SD_RES_SUCCESS) { sd_err("failed to update inode, %" PRIx32", %s", vid, sd_strerror(ret)); goto out; } out: strbuf_release(&buf); free(inode); return ret; } /* * Allocate the objects and update the free list. * * Callers are expected to call oalloc_new_finish() to update the inode bitmap * after filling up the data. * * @vid: the vdi where the allocator resides * @start: start index of the objects to allocate * @count: number of the objects to allocate */ int oalloc_new_prepare(uint32_t vid, uint64_t *start, uint64_t count) { char *meta = xvalloc(SD_DATA_OBJ_SIZE); struct header *hd; struct free_desc *fd; uint64_t oid = vid_to_data_oid(vid, 0), i; int ret; ret = sd_read_object(oid, meta, SD_DATA_OBJ_SIZE, 0); if (ret != SD_RES_SUCCESS) { sd_err("failed to read meta %" PRIx64 ", %s", oid, sd_strerror(ret)); goto out; } hd = (struct header *)meta; fd = (struct free_desc *)(meta + oalloc_meta_length(hd)) - 1; sd_debug("used %"PRIu64", nr_free %"PRIu64, hd->used, hd->nr_free); for (i = 0; i < hd->nr_free; i++, fd--) { sd_debug("start %"PRIu64", count %"PRIu64, fd->start, fd->count); if (fd->count > count) break; } if (i == hd->nr_free) { ret = SD_RES_NO_SPACE; goto out; } *start = fd->start; fd->start += count; fd->count -= count; hd->used += count; /* Update the meta object */ ret = sd_write_object(oid, meta, oalloc_meta_length(hd), 0, false); if (ret != SD_RES_SUCCESS) sd_err("failed to update meta %"PRIx64 ", %s", oid, sd_strerror(ret)); out: free(meta); return ret; } /* * Update the inode map of the vid * * @vid: the vdi where the allocator resides * @start: start index of the objects to update * @count: number of the objects to update */ int oalloc_new_finish(uint32_t vid, uint64_t start, uint64_t count) { struct sd_inode *inode = xmalloc(sizeof(struct sd_inode)); int ret; ret = sd_read_object(vid_to_vdi_oid(vid), (char *)inode, sizeof(*inode), 0); if (ret != SD_RES_SUCCESS) { sd_err("failed to read inode, %" PRIx64 ", %s", vid_to_vdi_oid(vid), sd_strerror(ret)); goto out; } sd_debug("start %"PRIu64" end %"PRIu64, start, start + count - 1); sd_inode_set_vid_range(inode, start, (start + count - 1), vid); ret = sd_inode_write(inode, 0, false, false); if (ret != SD_RES_SUCCESS) { sd_err("failed to update inode, %" PRIx64", %s", vid_to_vdi_oid(vid), sd_strerror(ret)); goto out; } out: free(inode); return ret; } static int free_desc_cmp(struct free_desc *a, struct free_desc *b) { return -intcmp(a->start, b->start); } static inline int update_and_merge_free_desc(char *meta, uint64_t start, uint64_t count, uint32_t vid) { struct header *hd = (struct header *)meta; struct free_desc *tail, *fd = HEADER_TO_FREE_DESC(hd); uint64_t i, j; /* Try our best to merge it in place, or append it to tail */ for (i = 0; i < hd->nr_free; i++) { if (start + count == fd->start) { fd->start = start; fd->count += count; break; } else if(fd->start + fd->count == start) { fd->count +=count; break; } fd++; } if (i == hd->nr_free) { if (hd->nr_free >= MAX_FREE_DESC) return SD_RES_NO_SPACE; tail = (struct free_desc *)(meta + oalloc_meta_length(hd)); tail->start = start; tail->count = count; hd->nr_free++; } hd->used -= count; xqsort(HEADER_TO_FREE_DESC(hd), hd->nr_free, free_desc_cmp); /* Merge as hard as we can */ j = hd->nr_free - 1; tail = (struct free_desc *)(meta + oalloc_meta_length(hd)) - 1; for (i = 0; i < j; i++, tail--) { struct free_desc *front = tail - 1; sd_debug("start %"PRIu64", count %"PRIu64, tail->start, tail->count); if (tail->start + tail->count > front->start) sd_emerg("bad free descriptor found at %"PRIx32, vid); if (tail->start + tail->count == front->start) { front->start = tail->start; front->count += tail->count; memmove(tail, tail + 1, sizeof(*tail) * i); hd->nr_free--; } } return SD_RES_SUCCESS; } /* * Discard the allocated objects and update the free list of the allocator * * Caller should check the return value since it might fail. * * @vid: the vdi where the allocator resides * @start: start index of the objects to free * @count: number of the objects to free */ int oalloc_free(uint32_t vid, uint64_t start, uint64_t count) { char *meta = xvalloc(SD_DATA_OBJ_SIZE); struct header *hd; uint64_t oid = vid_to_data_oid(vid, 0), i; struct sd_inode *inode = xmalloc(sizeof(struct sd_inode)); int ret; ret = sd_read_object(vid_to_vdi_oid(vid), (char *)inode, sizeof(*inode), 0); if (ret != SD_RES_SUCCESS) { sd_err("failed to read inode, %" PRIx64 ", %s", vid_to_vdi_oid(vid), sd_strerror(ret)); goto out; } sd_debug("discard start %"PRIu64" end %"PRIu64, start, start + count - 1); sd_inode_set_vid_range(inode, start, (start + count - 1), 0); ret = sd_inode_write(inode, 0, false, false); if (ret != SD_RES_SUCCESS) { sd_err("failed to update inode, %" PRIx64", %s", vid_to_vdi_oid(vid), sd_strerror(ret)); goto out; } ret = sd_read_object(oid, meta, SD_DATA_OBJ_SIZE, 0); if (ret != SD_RES_SUCCESS) { sd_err("failed to read meta %" PRIx64 ", %s", oid, sd_strerror(ret)); goto out; } ret = update_and_merge_free_desc(meta, start, count, vid); if (ret != SD_RES_SUCCESS) goto out; /* XXX use aio to speed up remove of objects */ for (i = 0; i < count; i++) { struct sd_req hdr; int res; sd_init_req(&hdr, SD_OP_REMOVE_OBJ); hdr.obj.oid = vid_to_data_oid(vid, start + i); res = exec_local_req(&hdr, NULL); /* * return the error code if it does not * success or can't find obj. */ if (res != SD_RES_SUCCESS && res != SD_RES_NO_OBJ) ret = res; } hd = (struct header *)meta; ret = sd_write_object(oid, meta, oalloc_meta_length(hd), 0, false); if (ret != SD_RES_SUCCESS) { sd_err("failed to update meta %"PRIx64 ", %s", oid, sd_strerror(ret)); goto out; } sd_debug("used %"PRIu64", nr_free %"PRIu64, hd->used, hd->nr_free); out: free(meta); free(inode); return ret; }
/** * Check which of qsort(), xqsort(), xsort() or smsort() is best for sorting * aligned arrays with a native item size of OPSIZ. At identical performance * level, we prefer our own sorting algorithms instead of libc's qsort() for * memory allocation purposes. * * @param items amount of items to use in the sorted array * @param idx index of the virtual routine to update * @param verbose whether to be verbose * @param which either "large" or "small", for logging */ static void vsort_init_items(size_t items, unsigned idx, int verbose, const char *which) { struct vsort_testing tests[] = { { vsort_qsort, qsort, 0.0, 0, "qsort" }, { vsort_xqsort, xqsort, 0.0, 2, "xqsort" }, { vsort_xsort, xsort, 0.0, 1, "xsort" }, { vsort_tqsort, tqsort, 0.0, 1, "tqsort" }, { vsort_smsort, smsort, 0.0, 1, "smsort" }, /* Only for almost sorted */ }; size_t len = items * OPSIZ; struct vsort_timing vt; size_t loops, highest_loops; unsigned i; g_assert(uint_is_non_negative(idx)); g_assert(idx < N_ITEMS(vsort_table)); vt.data = vmm_alloc(len); vt.copy = vmm_alloc(len); vt.items = items; vt.isize = OPSIZ; vt.len = len; random_bytes(vt.data, len); highest_loops = loops = vsort_loops(items); /* The -1 below is to avoid benchmarking smsort() for the general case */ retry_random: for (i = 0; i < N_ITEMS(tests) - 1; i++) { tests[i].v_elapsed = vsort_timeit(tests[i].v_timer, &vt, &loops); if (verbose > 1) { s_debug("%s() took %.4f secs for %s array (%zu loops)", tests[i].v_name, tests[i].v_elapsed * loops, which, loops); } if (loops != highest_loops) { highest_loops = loops; /* Redo all the tests if the number of timing loops changes */ if (i != 0) goto retry_random; } } /* * When dealing with a large amount of items, redo the tests twice with * another set of random bytes to make sure we're not hitting a special * ordering case. */ if (items >= VSORT_ITEMS) { unsigned j; for (j = 0; j < 2; j++) { random_bytes(vt.data, len); for (i = 0; i < N_ITEMS(tests) - 1; i++) { tests[i].v_elapsed += vsort_timeit(tests[i].v_timer, &vt, &loops); if (verbose > 1) { s_debug("%s() spent %.6f secs total for %s array", tests[i].v_name, tests[i].v_elapsed, which); } if (loops != highest_loops) { highest_loops = loops; /* Redo all the tests if the number of loops changes */ s_info("%s(): restarting %s array tests with %zu loops", G_STRFUNC, which, loops); goto retry_random; } } } } xqsort(tests, N_ITEMS(tests) - 1, sizeof tests[0], vsort_testing_cmp); vsort_table[idx].v_sort = vsort_routine(tests[0].v_routine, items); if (verbose) { s_info("vsort() will use %s() for %s arrays", vsort_routine_name(tests[0].v_name, items), which); } /* * Now sort the data, then randomly perturb them by swapping a few items * so that the array is almost sorted. */ xqsort(vt.data, vt.items, vt.isize, vsort_long_cmp); vsort_perturb_sorted_array(vt.data, vt.items, vt.isize); retry_sorted: for (i = 0; i < N_ITEMS(tests); i++) { tests[i].v_elapsed = vsort_timeit(tests[i].v_timer, &vt, &loops); if (verbose > 1) { s_debug("%s() on almost-sorted took %.4f secs " "for %s array (%zu loops)", tests[i].v_name, tests[i].v_elapsed * loops, which, loops); } if (loops != highest_loops) { highest_loops = loops; /* Redo all the tests if the number of timing loops changes */ if (i != 0) goto retry_sorted; } } xqsort(tests, N_ITEMS(tests), sizeof tests[0], vsort_testing_cmp); vsort_table[idx].v_sort_almost = vsort_routine(tests[0].v_routine, items); if (verbose) { s_info("vsort_almost() will use %s() for %s arrays", vsort_routine_name(tests[0].v_name, items), which); } vmm_free(vt.data, len); vmm_free(vt.copy, len); }
int sort(int argc ,char * argv[]) { FILE *fp; char *lineptr[MAXLINES]; /* pointers to text lines */ char *tmp; int i = 0; int j = 0; int lines = 0; char buf[256]; char sort_type[3]; if( argc == 2) strcpy(sort_type,"-o"); else strcpy(sort_type,argv[2]); fp = fopen(argv[1],"a+"); if ( NULL == fp) { printf("File does not exists\n"); return -1; } while( fgets(buf,256,fp)) { tmp = (char *)malloc(strlen(buf)*sizeof(char)); strcpy(tmp,buf); lineptr[lines] = tmp; lines++; } for ( i = 0; i<sizeof(sort_op)/sizeof(sort_op[0]);i++) { if ( strcmp(sort_type,sort_op[i].type) == 0) { printf("type is %s\n",sort_op[i].type); pfsort = sort_op[i].pf; xqsort(lineptr, lines, sizeof(char *), pfsort); break; } } fputs("--- after sort --- \n",fp); while(lines) { fputs(lineptr[j],fp); lines--; j++; } fclose(fp); return 0; }