Exemplo n.º 1
0
/**
 * @brief TEST_CASE - Sanity test of some key skiplist APIs using integers.
 */
static int simple( void )
{
	unsigned int i;
	skiplist_node_t *iter;
	skiplist_t *skiplist;

	skiplist = skiplist_create( SKIPLIST_PROPERTY_NONE, 5, int_compare, int_fprintf, NULL );
	if( !skiplist )
		return -1;

	if( skiplist_contains( skiplist, 10, NULL ) )
		return -1;

	if( !skiplist_remove( skiplist, 10 ) )
		return -1;

	for( i = 0; i < 10; ++i )
	{
		if( skiplist_insert( skiplist, i ) )
			return -1;
		if( !skiplist_contains( skiplist, i, NULL ) )
			return -1;
	}

	for( i = 0; i < 100; ++i )
	{
		unsigned int value = rand();
		if( skiplist_insert( skiplist, value ) )
			return -1;
		if( !skiplist_contains( skiplist, value, NULL ) )
			return -1;
	}

	for( i = 5; i < 10; ++i )
		if( skiplist_remove( skiplist, i ) )
			return -1;

	for( iter = skiplist_begin( skiplist );
	     iter != skiplist_end();
	     iter = skiplist_next( iter ) )
	{
		uintptr_t value = skiplist_node_value( iter, NULL );
		if( value >= 5 && value < 10 )
			return -1;
	}

	for( i = 0; i < skiplist_size( skiplist, NULL ); ++i )
		skiplist_at_index( skiplist, i, NULL );

	if( skiplist_fprintf_filename( "simple.dot", skiplist ) )
		return -1;

	skiplist_destroy( skiplist );

	return 0;
}
Exemplo n.º 2
0
/**
 * @brief TEST_CASE - Confirms that duplicate entries are disallowed when the skiplist is a set.
 */
static int duplicate_entries_disallowed( void )
{
	unsigned int i;
	skiplist_node_t *iter;
	skiplist_t *skiplist;

	skiplist = skiplist_create( SKIPLIST_PROPERTY_UNIQUE, 5, int_compare, int_fprintf, NULL );
	if( !skiplist )
		return -1;

	for( i = 0; i < 2; ++i )
	{
		unsigned int j;
		for( j = 0; j < 5; ++j )
		{
			if( skiplist_insert( skiplist, j ) )
				return -1;
			if( skiplist_size( skiplist, NULL ) != (i ? 5 : j+1) )
				return -1;
		}
	}

	for( i = 0; i < 5; ++i )
		if( !skiplist_contains( skiplist, i, NULL ) )
			return -1;

	for( i = 0, iter = skiplist_begin( skiplist ); iter != skiplist_end(); iter = skiplist_next( iter ), ++i )
		if( skiplist_node_value( iter, NULL ) != i )
			return -1;

	if( skiplist_fprintf_filename( "duplicate_entries_disallowed.dot", skiplist ) )
		return -1;

	return 0;
}
Exemplo n.º 3
0
skiplist*
skiplist_clone(skiplist* list, dict_key_datum_clone_func clone_func)
{
    ASSERT(list != NULL);

    skiplist* clone = skiplist_new(list->cmp_func, list->del_func,
				   list->max_link);
    if (clone) {
	skip_node* node = list->head->link[0];
	while (node) {
	    bool inserted = false;
	    void** datum = skiplist_insert(clone, node->key, &inserted);
	    if (!datum || !inserted) {
		skiplist_free(clone);
		return NULL;
	    }
	    *datum = node->datum;
	    node = node->link[0];
	}
	if (clone_func) {
	    node = clone->head->link[0];
	    while (node) {
		clone_func(&node->key, &node->datum);
		node = node->link[0];
	    }
	}
    }
    return clone;
}
Exemplo n.º 4
0
int main()
{
    int arr[] = {3, 6, 9, 2, 11, 1, 4}, i;
    skiplist list;
    skiplist_init(&list);
 
    printf("Insert:--------------------\n");
    for (i = 0; i < sizeof(arr)/sizeof(arr[0]); i++) {
        skiplist_insert(&list, arr[i], arr[i]);
    }
    skiplist_dump(&list);
 
    printf("Search:--------------------\n");
    int keys[] = {3, 4, 7, 10, 111};
 
    for (i = 0; i < sizeof(keys)/sizeof(keys[0]); i++) {
        snode *x = skiplist_search(&list, keys[i]);
        if (x) {
            printf("key = %d, value = %d\n", keys[i], x->value);
        } else {
            printf("key = %d, not fuound\n", keys[i]);
        }
    }
 
    printf("Search:--------------------\n");
    skiplist_delete(&list, 3);
    skiplist_delete(&list, 9);
    skiplist_dump(&list);
 
    return 0;
}
Exemplo n.º 5
0
/* skiplist_insert_copy SKIPLIST KEY KLEN VALUE VLEN
 * Make a copy of VLEN bytes of VALUE data in SKIPLIST's private pool, and
 * insert a pointer to the copy under the given KLEN-byte KEY. */
int skiplist_insert_copy(skiplist S, const void *key, const size_t klen, const void *val, const size_t vlen) {
    void *v;
    v = pool_malloc(S->P, vlen);
    memcpy(v, val, vlen);
    if (!skiplist_insert(S, key, klen, v)) {
        pool_free(S->P, v); /* XXX */
        return 0;
    } else
        return 1;
}
Exemplo n.º 6
0
int main(int argc, char **argv)
{
    skiplist *list = skiplist_new(compare_word);
    assert(list != NULL);
    

    FILE *f = fopen("../_test/wordlist.txt", "r");
    assert(f != NULL);

    char *key;
    int i = 0;
    long long start, stop;

    start = get_ustime_sec();
    while (!feof(f)) {
        i++;
        key = (char *)malloc(sizeof(char) * 30);
        assert(key != NULL);

        fscanf(f, "%s\n", key);
        skiplist_insert(list, key, &value);
    }
    stop = get_ustime_sec();
    fclose(f);
    
    printf("put %d word in skiplist cost time %lldμs\n", i, stop-start);
    
    /* 查询 */
    char test[30] = "comically";
    int *t = skiplist_search(list, test);
    if (t) {
        printf("%s in wordlist and value = %d\n", test, *t);
    } else {
        printf("%s not in wordlist\n", test);
    }


    skiplist_delete(list, test);

    t = skiplist_search(list, test);
    if (t) {
        printf("%s in wordlist\n", test);
    } else {
        printf("%s not in wordlist\n", test);
    }

    /**
     * 在删除 Hashmap 前,需要自己管理 Key, Value 指向的内存
     * 这里并没有释放 Key 内存
     */
    skiplist_free(list);
    return 0;
}
Exemplo n.º 7
0
int main() {
    struct skiplist *s;
    struct node *p;
    int i,level;

    s = skiplist_create();
    for(i=0; i<20; i++) {
        skiplist_insert(s,rand()%40);
    }
    print(s);
    return 0;
}
Exemplo n.º 8
0
int
main(int argc, char **argv)
{
    ut_init(basename(argv[0]));

    ut_testing("skiplist_create(6, 50, libhl_cmp_keys_int32, free)");
    skiplist_t *skl = skiplist_create(6, 50, libhl_cmp_keys_int32, free);
    if (skl)
        ut_success();
    else
        ut_failure("Can't create a new binomial heap");

    ut_testing("skiplist_insert(0..99)");
    int i;
    for (i = 0; i < 100; i++) { 
        char *val = malloc(4);
        snprintf(val, 4, "%d", i);
        skiplist_insert(skl, &i, sizeof(i), val);
    }
    ut_validate_int(skiplist_count(skl), 100);

    int test_key = 50;
    ut_testing("skiplist_search(50) = \"50\"");
    char *val = skiplist_search(skl, &test_key, sizeof(int));
    ut_validate_string(val, "50");

    
    ut_testing("skiplist_remove(50, &old_value)");
    val = NULL;
    int rc = skiplist_remove(skl, &test_key, sizeof(int), (void **)&val);
    ut_validate_int(rc, 0);

    ut_testing("old_value is \"50\"");
    ut_validate_string(val, "50");
    free(val);

    ut_testing("skiplist_search(50) = NULL");

    val = skiplist_search(skl, &test_key, sizeof(int));
    ut_validate_string(val, NULL);


    skiplist_destroy(skl);

    ut_summary();

    return ut_failed;
}
Exemplo n.º 9
0
struct skiplist *_read_mmap(struct sst *sst, size_t count)
{
	int i;
	int fd;
	int result;
	int fcount;
	int blk_sizes;
	char file[FILE_PATH_SIZE];
	struct sst_block *blks;
	struct skiplist *merge = NULL;
	struct footer footer;
	int fsize = sizeof(struct footer);

	memset(file, 0, FILE_PATH_SIZE);
	snprintf(file, FILE_PATH_SIZE, "%s/%s", sst->basedir, sst->name);

	fd = open(file, O_RDWR, 0644);
	result = lseek(fd, -fsize, SEEK_END);
	if(result == -1)
		abort();

	result = read(fd, &footer, fsize);
	if(result == -1)
		abort();

	fcount = from_be32(footer.count);
	blk_sizes = fcount * sizeof(struct sst_block);

	blks = mmap(0, blk_sizes, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
	if(blks == MAP_FAILED) {
		__DEBUG(LEVEL_ERROR, "%s", "Error: sst_bloom un-mmapping the file");
		goto out;
	}

	merge = skiplist_new(fcount + count + 1);
	for(i = 0; i < fcount; i++) {
		skiplist_insert(merge, blks[i].key, from_be64(blks[i].offset), ADD);
	}

	if(munmap(blks, blk_sizes) == -1) {
		__DEBUG(LEVEL_ERROR, "%s", "read_map:un-mmapping the file");
	}

out:
	close(fd);
	return merge;
}
Exemplo n.º 10
0
/**
 * @brief TEST_CASE - Confirms incorrect inputs are handled gracefully for skiplist_next.
 */
static int abuse_skiplist_next( void )
{
	skiplist_t *skiplist;

	skiplist = skiplist_create( SKIPLIST_PROPERTY_NONE, 5, int_compare, int_fprintf, NULL );
	if( !skiplist )
		return -1;

	if( skiplist_insert( skiplist, 1 ) )
		return -1;

	if( skiplist_next( NULL ) )
		return -1;

	skiplist_destroy( skiplist );
	return 0;
}
Exemplo n.º 11
0
int main(int argc, char *argv[]) {
  srand(clock());
  SkipList_t *ptrSl = skiplist_alloc(10,1);
  int64_t i;
  for (i = 1; i <= 10; i++) {
    skiplist_insert(ptrSl, i, (void*)(i*i));
    SlKey_t slKey;
    int64_t cValue;
    if (skiplist_index(ptrSl, (i+1)/2-1, &slKey, (void**)(&cValue))) {
      assert(slKey == (i+1)/2);
    } else {
      assert(0);
    }
  }
  for (i = 0; i < 10; i++) {
    SlKey_t slKey;
    int64_t cValue;
    if (skiplist_index(ptrSl, i, &slKey, (void**)(&cValue))) {
      assert(slKey == i+1);
    } else {
      assert(0);
    }
  }
  int32_t ixRm = 5;
  assert(skiplist_delete(ptrSl, ixRm));
  for (i = 1; i <= 10; i++) {
    int64_t cValue = (int64_t)skiplist_find(ptrSl, i);
    if (i != ixRm) {
      assert(cValue == i*i);
    } else {
      assert(cValue == 0);
    }
  }
  for (i = 1; i <= 10; i+=2) {
    int32_t fSuccess = skiplist_delete(ptrSl,i);
    if (i != ixRm) {
      assert(fSuccess);
    } else {
      assert(!fSuccess);
    }
  }
  skiplist_free(ptrSl);
  return 1;
}
Exemplo n.º 12
0
int index_add(struct index *idx, struct slice *sk, struct slice *sv)
{
	uint64_t value_offset;
	struct skiplist *list;
	struct skiplist *new_list;

	value_offset = log_append(idx->log, sk, sv);
	list = idx->list;

	if(!list) {
		__DEBUG(LEVEL_ERROR, "ERROR: List<%d> is NULL", idx->lsn);
		return 0;
	}

	if(!skiplist_notfull(list)) {
		idx->bg_merge_count++;

		/* If the detached-merge thread isnot finished, hold on it
		 * Notice: it will block the current process,
		 * but it happens only once in a thousand years on production environment.
		 */
		pthread_mutex_lock(&idx->merge_mutex);

		/* start to merge with detached thread */
		pthread_t tid;
		idx->park->list = list;
		idx->park->lsn = idx->lsn;
		pthread_mutex_unlock(&idx->merge_mutex);
		pthread_create(&tid, &idx->attr, _merge_job, idx);

		idx->mtbl_rem_count = 0;
		new_list = skiplist_new(idx->max_mtbl_size);
		idx->list = new_list;

		idx->lsn++;
		log_next(idx->log, idx->lsn);
	}

	skiplist_insert(idx->list, sk->data, value_offset, sv == NULL ? DEL : ADD);
	idx->mtbl_rem_count++;
	return 1;
}
Exemplo n.º 13
0
static int test_insert()
{
    int i;
    int result;
    int64_t start_time;
    int64_t end_time;
    void *value;

    instance_count = 0;
    start_time = get_current_time_ms();
    for (i=0; i<COUNT; i++) {
        if ((result=skiplist_insert(&sl, numbers + i)) != 0) {
            return result;
        }
        instance_count++;
    }
    assert(instance_count == COUNT);

    end_time = get_current_time_ms();
    printf("insert time used: %"PRId64" ms\n", end_time - start_time);

    start_time = get_current_time_ms();
    for (i=0; i<COUNT; i++) {
        value = skiplist_find(&sl, numbers + i);
        assert(value != NULL && *((int *)value) == numbers[i]);
    }
    end_time = get_current_time_ms();
    printf("find time used: %"PRId64" ms\n", end_time - start_time);

    start_time = get_current_time_ms();
    i = 0;
    skiplist_iterator(&sl, &iterator);
    while ((value=skiplist_next(&iterator)) != NULL) {
        i++;
        assert(i == *((int *)value));
    }
    assert(i==COUNT);

    end_time = get_current_time_ms();
    printf("iterator time used: %"PRId64" ms\n", end_time - start_time);
    return 0;
}
Exemplo n.º 14
0
int main(int argc, char *argv[]) {
    int i, n, seed, key;

    SkipList skiplist;
    Cell *node;

    if (argc < 2 || argc > 3) {
        printf("Usage: %s <n> [seed]\n", argv[0]);
        exit(1);
    }

    n = atoi(argv[1]);

    if (argc == 3) seed = atoi(argv[2]);
    else seed = time(NULL);
    srand(seed);

    skiplist_init(&skiplist);

    printf("[+] dump key: \n");
    printf("    (i    , key)\n");
    for (i = 0; i < n; i++) {
        key = rand() % SKIPLIST_MAX_KEY;
        printf("    (%-4d , %4d)\n", i, key);
        skiplist_insert(&skiplist, key);
        skiplist_vertical_print(&skiplist);

    }
    skiplist_vertical_print(&skiplist);
    /*node = skiplist_search(&skiplist, 15);*/
    if (NULL)
        printf("[+] key %d found.\n", node->key);
    else
        printf("[-] Key 15 not found.\n");
    return 0;
}
Exemplo n.º 15
0
int main(int argc, char** argv) {

    if (argc != 2) {
        printf("Usage: %s HPROF_FILE\n", argv[0]);
        exit(1);
    }

    FILE* hprof_fp = fopen(argv[1], "r");
    die(hprof_fp == NULL, "File error");

    hprof_header* header;
    char version[19];
    u4 ident_size;

    int count = fread(version, sizeof(version), 1, hprof_fp);
    die(count != 1, "Unable to read hprof header");

    count = fread(&ident_size, sizeof(u4), 1, hprof_fp);
    die(count != 1, "Unable to read hprof header");

    int success = fseek(hprof_fp, sizeof(u8), SEEK_CUR);
    die(success != 0, "Could not seek forward in the file");

    printf("Header: version=%s identsize=%ju\n",
            version,
            (uintmax_t) be32_to_native(ident_size));

    // For now just reuse it
    hprof_record_header* record_header = calloc(1, sizeof(hprof_record_header));
    hprof_heap_summary* heap_summary = calloc(1, sizeof(hprof_heap_summary));

    // The string table is a skip list that should give us
    // O(n log n) insertion and O(log n) lookup, This is not as 
    // good as a malloc'd array, but does not suffer from the
    // out of order issues that the string id's present us with
    skiplist_t *string_table = malloc(sizeof(skiplist_t));
    skiplist_init(string_table);
    skiplist_set_cmp_fn(string_table, stringtable_cmp);
    skiplist_set_search_fn(string_table, stringtable_search);
    skiplist_set_destroy_fn(string_table, __destroy);

    skiplist_t *class_table = malloc(sizeof(skiplist_t));
    skiplist_init(class_table);
    skiplist_set_cmp_fn(class_table, classtable_cmp);
    skiplist_set_search_fn(class_table, classtable_search);
    skiplist_set_destroy_fn(class_table, __destroy);

    while(1) {
        if (feof(hprof_fp)) {
            break;
        }

        //read_record_header(record_header, hprof_fp);
        funpack(hprof_fp, "bd>d>",
            &record_header->tag,
            &record_header->profiling_ms,
            &record_header->remaining_bytes);

        //printf("Tag=%ju\n", (uintmax_t) record_header->tag);
        switch(record_header->tag) {
            case UTF8:
                //printf("UTF8\n");
                ;
                hprof_utf8 *utf8 = malloc(sizeof(hprof_utf8));
                
                funpack(hprof_fp, "q>", &utf8->id);
                //fread(&utf8->id, sizeof(id), 1, hprof_fp);
                long bytes_remain = record_header->remaining_bytes - sizeof(id);

                // Awesome, hprof strings are utf8, this is good ! the only established
                // C type is char and its a byte wide :D
                utf8->num_chars = bytes_remain / sizeof(char);
                utf8->hprof_offset = ftell(hprof_fp);

                skiplist_insert(string_table, utf8);

                fseek(hprof_fp, bytes_remain, SEEK_CUR);
                break;
            case LOAD_CLASS:
                //printf("LOAD_CLASS\n");
                ;

                hprof_load_class *class = malloc(sizeof(hprof_load_class));
                fread(&class->serial_number, sizeof(u4), 1, hprof_fp);
                class->serial_number = be32_to_native(class->serial_number);
                fseek(hprof_fp, sizeof(id) + sizeof(u4), SEEK_CUR);
                fread(&class->name_id, sizeof(id), 1, hprof_fp);
                class->name_id = be64_to_native(class->name_id);

                skiplist_insert(class_table, class);
                //fseek(hprof_fp, be32_to_native(record_header->remaining_bytes), SEEK_CUR);
                break;
            case UNLOAD_CLASS:
                //printf("UNLOAD_CLASS\n");
                fseek(hprof_fp, record_header->remaining_bytes, SEEK_CUR);
                break;
            case FRAME:
                //printf("FRAME\n");
                
                // This is bad !!! If it is slow think about doing two complete passes to 
                // make all the I/O as sequential as possible
                // This implementation is going to jump all over the hprof file

                ;
                long curr_pos = ftell(hprof_fp);
                id ids[4];
                fread(&ids, sizeof(id), 4, hprof_fp);

                u4 class_serial_num;
                fread(&class_serial_num, sizeof(u4), 1, hprof_fp);
                class_serial_num = be32_to_native(class_serial_num);
                hprof_load_class *clazz = (hprof_load_class*) skiplist_search(class_table, &class_serial_num);

                i4 line_num;
                fread(&line_num, sizeof(i4), 1, hprof_fp);
                line_num = be32_to_native(line_num);

                char *method_name = read_string(be64_to_native(ids[1]), string_table, hprof_fp);
                char *method_sig  = read_string(be64_to_native(ids[2]), string_table, hprof_fp);
                char *source_file = read_string(be64_to_native(ids[3]), string_table, hprof_fp);

                char *class_name = "<UNKNOWN_CLASS>";
                if(clazz != NULL) {
                    class_name = read_string(clazz->name_id, string_table, hprof_fp);
                }

                // SOMETIMES NULL
                //printf("%s\n", read_string(ids[3], string_table, hprof_fp));
                
                class_name  = (class_name  == NULL) ? "<UNKNOWN_CLASS>"      : class_name;
                method_name = (method_name == NULL) ? "<UNKNOWN_METHOD>"     : method_name;
                method_sig  = (method_sig  == NULL) ? "<UNKNOWN_METHOD_SIG>" : method_sig;
                source_file = (source_file == NULL) ? "<UNKNOWN_SOURCE>"     : source_file;

                switch(line_num) {
                    case -1:
                        printf("Class %s\n \tMethod=%s\n\tSource=%s @ <UNKNOWN>\n",
                                class_name, method_name, source_file);
                        break;
                    case -2:
                        printf("Class %s\n \tMethod=%s\n\tSource=%s @ <COMPILED_METHOD>\n",
                                class_name, method_name, source_file);
                        break;
                    case -3:
                        printf("Class %s\n \tMethod=%s\n\tSource=%s @ <NATIVE_METHOD>\n",
                                class_name, method_name, source_file);
                        break;
                    default:
                        printf("Class %s\n \tMethod=%s\n\tSource=%s @ %ji\n",
                                class_name, method_name, source_file, (intmax_t) line_num);
                        break;
                }

                break;
            case TRACE:
                //printf("TRACE\n");
                ;
                hprof_stacktrace* stacktrace = calloc(1, sizeof(hprof_stacktrace));

                fread(&stacktrace->serial_number, sizeof(u4), 1, hprof_fp);
                fread(&stacktrace->thread_number, sizeof(u4), 1, hprof_fp);
                fread(&stacktrace->number_frames, sizeof(u4), 1, hprof_fp);

                printf("StackTrace serial_num=%ju "
                       "thread_num=%ju num_frames=%ju\n",
                       (uintmax_t) be64_to_native(stacktrace->serial_number),
                       (uintmax_t) be64_to_native(stacktrace->thread_number),
                       (uintmax_t) be64_to_native(stacktrace->number_frames));

                for (int i=0; i < be32_to_native(stacktrace->number_frames); i++) {
                    id frame_id;
                    fread(&frame_id, sizeof(id), 1, hprof_fp);
                    printf("FrameID=%ju\n", (uintmax_t) be64_to_native(frame_id));
                }

                free(stacktrace);

                break;
            case ALLOC_SITES:
                //printf("ALLOC_SITES\n");
                fseek(hprof_fp, be32_to_native(record_header->remaining_bytes), SEEK_CUR);
                break;
            case HEAP_SUMMARY:
                //printf("HEAP SUMMARY\n");
                fread(&heap_summary->live_bytes, sizeof(u4), 1, hprof_fp);
                fread(&heap_summary->live_instances, sizeof(u4), 1, hprof_fp);
                fread(&heap_summary->allocated_bytes, sizeof(u8), 1, hprof_fp);
                fread(&heap_summary->allocated_instances, sizeof(u8), 1, hprof_fp);
                printf("Heap summary:\n\tReachable bytes=%ju\n\t"
                       "Reachable instances=%ju\n\t"
                       "Allocated bytes=%ju\n\t"
                       "Allocated instances=%ju\n",
                       (uintmax_t) be32_to_native(heap_summary->live_bytes),
                       (uintmax_t) be32_to_native(heap_summary->live_instances),
                       (uintmax_t) be64_to_native(heap_summary->allocated_bytes),
                       (uintmax_t) be64_to_native(heap_summary->allocated_instances));
                break;
            case START_THREAD:
                //printf("START_THREAD\n");
                fseek(hprof_fp, be32_to_native(record_header->remaining_bytes), SEEK_CUR);
                break;
            case END_THREAD:
                //printf("END_THREAD\n");
                fseek(hprof_fp, be32_to_native(record_header->remaining_bytes), SEEK_CUR);
                break;
            case HEAP_DUMP:
                //printf("HEAP_DUMP\n");
                fseek(hprof_fp, be32_to_native(record_header->remaining_bytes), SEEK_CUR);
                break;
            case CPU_SAMPLES:
                //printf("CPU_SAMPLES\n");
                fseek(hprof_fp, be32_to_native(record_header->remaining_bytes), SEEK_CUR);
                break;
            case CONTROL_SETTINGS:
                //printf("CONTROL_SETTINGS\n");
                fseek(hprof_fp, be32_to_native(record_header->remaining_bytes), SEEK_CUR);
                break;
            case HEAP_DUMP_SEGMENT:
                //printf("HEAP_DUMP_SEGMENT\n");
                fseek(hprof_fp, be32_to_native(record_header->remaining_bytes), SEEK_CUR);
                break;
            case HEAP_DUMP_END:
                //printf("HEAP_DUMP_END\n");
                fseek(hprof_fp, be32_to_native(record_header->remaining_bytes), SEEK_CUR);
                exit(1);
                break;
            default:
                printf("BANG\n");
                exit(1);
                break;
        }

        //printf("%lu\n", ftell(hprof_fp));
    }

    skiplist_destroy(string_table);
    free(string_table);

    skiplist_destroy(class_table);
    free(class_table);

    fclose(hprof_fp);
    return 0;
}
Exemplo n.º 16
0
/**
 * @brief TEST_CASE - Measures insertion trade off between number of elements in the list and number of links per node.
 */
static int link_trade_off_insert( void )
{
#define MAX_LINKS (SKIPLIST_MAX_LINKS)
#define INSERTIONS_LOG2 (16)

	struct timespec stamps[INSERTIONS_LOG2 + 2];
	FILE *fp;
	unsigned int links;
	unsigned int i;
	const char *seperator;

	fp = fopen( "link_trade_off_insert.gplot", "w" );
	if( !fp ) return -1;
	fprintf(fp, "set term qt\n");
	fprintf(fp, "set key off\n");
	fprintf(fp, "set logscale\n");
	fprintf(fp, "set grid xtics ytics mxtics mytics\n");
	fprintf(fp, "set style textbox opaque noborder\n");
	fprintf(fp, "set title \"Average Insertion Time for Skiplists with Varying Link Counts\"\n");
	fprintf(fp, "set xlabel \"Number of Elements in the Skiplist\"\n");
	fprintf(fp, "set ylabel \"Average Time for One Insertion (ns)\"\n");
	fprintf(fp, "plot " );
	seperator = "";
	for( i = 0; i < MAX_LINKS; ++i )
	{
		fprintf(fp, "%s\"link_trade_off_insert_%u.dat\" using 1:2 with lines lt -1,"
		        "\"\" using 1:2:($0*0+%u) with labels center boxed notitle",
		        seperator, i + 1, i + 1);
		seperator = ",\\\n\t";
	}
	fprintf(fp, "\n");
	fprintf(fp, "pause -1\n");
	fclose( fp );

	for( links = MAX_LINKS; links > 0; --links )
	{
		skiplist_t *skiplist;
		char filename[64];
		unsigned int next;

		sprintf( filename, "link_trade_off_insert_%u.dat", links );
		fp = fopen( filename, "w" );
		if( !fp ) return -1;

		skiplist = skiplist_create( SKIPLIST_PROPERTY_NONE, links, int_compare, int_fprintf, NULL );
		if( !skiplist ) return -1;

		next = 0;
		for( i = 0; i < (1 << INSERTIONS_LOG2); ++i )
		{
			/* Sample at powers of 2. */
			if( (i & (i - 1)) == 0 )
			{
				time_stamp( &stamps[next] );

				/* Stop trying if it's taking too long. */
				if( next && time_diff_ns( &stamps[next - 1], &stamps[next] ) > 300000000LLU )
					break;

				++next;
			}

			if( skiplist_insert( skiplist, rand() ) )
				return -1;
		}
		time_stamp( &stamps[next] );
		++next;

		skiplist_destroy( skiplist );

		for( i = 1; i < next; ++i )
		{
			const unsigned int node_count = 1 << (i - 1);
			fprintf(fp, "%u\t%f\n", node_count,
			        time_diff_ns( &stamps[0], &stamps[i] ) / (double)node_count );
		}

		fclose( fp );
	}

#undef MAX_LINKS
#undef INSERTIONS_LOG2
	return 0;
}
Exemplo n.º 17
0
/**
 * @brief TEST_CASE - Measures lookup trade off between number of elements in the list and number of links per node.
 */
static int link_trade_off_lookup( void )
{
#define MAX_LINKS (SKIPLIST_MAX_LINKS)
#define INSERTIONS_LOG2 (16)
	unsigned int i;
	FILE *fp;
	const char *seperator;

	fp = fopen( "link_trade_off_lookup.gplot", "w" );
	if( !fp ) return -1;
	fprintf(fp, "set term qt\n");
	fprintf(fp, "set key off\n");
	fprintf(fp, "set logscale\n");
	fprintf(fp, "set grid xtics ytics mxtics mytics\n");
	fprintf(fp, "set style textbox opaque noborder\n");
	fprintf(fp, "set title \"Average Lookup Time for Skiplists with Varying Link Counts\"\n");
	fprintf(fp, "set xlabel \"Number of Elements in the Skiplist\"\n");
	fprintf(fp, "set ylabel \"Average Time for One Lookup (ns)\"\n");
	fprintf(fp, "plot " );

	seperator = "";
	for( i = 0; i < MAX_LINKS; ++i )
	{
		fprintf(fp, "%s\"link_trade_off_lookup.dat\" using 1:%u with lines lt -1,"
		        "\"\" using 1:%u:($0*0+%u) with labels center boxed notitle",
		        seperator, i + 2, i + 2, i + 1);
		seperator = ",\\\n\t";
	}
	fprintf(fp, "\n");
	fprintf(fp, "pause -1\n");
	fclose( fp );

	fp = fopen( "link_trade_off_lookup.dat", "w" );
	if( !fp ) return -1;

	for( i = 1; i < (1 << INSERTIONS_LOG2); i <<= 1 )
	{
		unsigned int links;
		fprintf( fp, "%u", i );
		for( links = 1; links <= MAX_LINKS; ++links )
		{
			unsigned int j;
			skiplist_t *skiplist;
			struct timespec start, end;

			skiplist = skiplist_create( SKIPLIST_PROPERTY_NONE, links, int_compare, int_fprintf, NULL );
			if( !skiplist ) return -1;

			for( j = 0; j < i; ++j )
				if( skiplist_insert( skiplist, j ) )
					return -1;

			time_stamp( &start );
			for( j = 0; j < i; ++j )
				if( !skiplist_contains( skiplist, j, NULL ) )
					return -1;
			time_stamp( &end );
			fprintf( fp, "\t%f", time_diff_ns( &start, &end ) / (double)i );
			skiplist_destroy( skiplist );
		}
		fprintf( fp, "\n" );
	}

	fclose( fp );

#undef MAX_LINKS
#undef INSERTIONS_LOG2
	return 0;
}
Exemplo n.º 18
0
/*
 * this is pretty ugly, but it is used to find a free spot in the
 * tree for a new iommu allocation.  We start from a given
 * hint and try to find an aligned range of a given size.
 *
 * Send the slot pointer, and we'll update it with the location
 * we found.
 *
 * This will return -EAGAIN if we found a good spot but someone
 * raced in and allocated it before we could.  This gives the
 * caller the chance to update their hint.
 *
 * This will return -EEXIST if we couldn't find anything at all
 *
 * returns 0 if all went well, or some other negative error
 * if things went badly.
 */
int skiplist_insert_hole(struct sl_list *list, unsigned long hint,
			 unsigned long limit,
			 unsigned long size, unsigned long align,
			 struct sl_slot *slot,
			 gfp_t gfp_mask)
{
	unsigned long last_end = 0;
	struct sl_node *p;
	struct sl_leaf *leaf;
	int i;
	int ret = -EEXIST;
	int preload_token;
	int pending_level;

	preload_token = skiplist_preload(list, gfp_mask);
	if (preload_token < 0) {
		return preload_token;
	}
	pending_level = pending_insert_level(preload_token);

	/* step one, lets find our hint */
	rcu_read_lock();
again:

	last_end = max(last_end, hint);
	last_end = align_start(last_end, align);
	slot->key = align_start(hint, align);
	slot->size = size;
	leaf = __skiplist_lookup_leaf(list, &p, hint, 1);
	if (!p)
		p = list->head;

	if (leaf && !verify_key_in_leaf(leaf, hint, size)) {
		goto again;
	}

again_lock:
	sl_lock_node(p);
	if (sl_node_dead(p)) {
		sl_unlock_node(p);
		goto again;
	}

	if (p != list->head) {
		leaf = sl_entry(p);
		/*
		 * the leaf we found was past the hint,
		 * go back one
		 */
		if (sl_max_key(leaf) > hint) {
			struct sl_node *locked = p;
			p = p->ptrs[0].prev;
			sl_unlock_node(locked);
			goto again_lock;
		}
		last_end = align_start(sl_max_key(sl_entry(p)), align);
	}

	/*
	 * now walk at level 0 and find a hole.  We could use lockless walks
	 * if we wanted to bang more on the insertion code, but this
	 * instead holds the lock on each node as we inspect it
	 *
	 * This is a little sloppy, insert will return -eexist if we get it
	 * wrong.
	 */
	while(1) {
		leaf = sl_next_leaf(list, p, 0);
		if (!leaf)
			break;

		/* p and leaf are locked */
		sl_lock_node(&leaf->node);
		if (last_end > sl_max_key(leaf))
			goto next;

		for (i = 0; i < leaf->nr; i++) {
			if (last_end > leaf->keys[i])
				continue;
			if (leaf->keys[i] - last_end >= size) {

				if (last_end + size > limit) {
					sl_unlock_node(&leaf->node);
					goto out_rcu;
				}

				sl_unlock_node(p);
				slot->key = last_end;
				slot->size = size;
				goto try_insert;
			}
			last_end = leaf->keys[i] + leaf->ptrs[i]->size;
			last_end = align_start(last_end, align);
			if (last_end + size > limit) {
				sl_unlock_node(&leaf->node);
				goto out_rcu;
			}
		}
next:
		sl_unlock_node(p);
		p = &leaf->node;
	}

	if (last_end + size <= limit) {
		sl_unlock_node(p);
		slot->key = last_end;
		slot->size = size;
		goto try_insert;
	}

out_rcu:
	/* we've failed */
	sl_unlock_node(p);
	rcu_read_unlock();
	preempt_enable();

	return ret;

try_insert:
	/*
	 * if the pending_level is zero or there is room in the
	 * leaf, we're ready to insert.  This is true most of the
	 * time, and we won't have to drop our lock and give others
	 * the chance to race in and steal our spot.
	 */
	if (leaf && (pending_level == 0 || leaf->nr < SKIP_KEYS_PER_NODE) &&
	    !sl_node_dead(&leaf->node) && (slot->key >= sl_min_key(leaf) &&
	    slot->key + slot->size <= sl_max_key(leaf))) {
		ret = find_or_add_key(list, slot->key, size, leaf, slot,
				      preload_token, NULL);
		rcu_read_unlock();
		goto out;
	}
	/*
	 * no such luck, drop our lock and try the insert the
	 * old fashioned way
	 */
	if (leaf)
		sl_unlock_node(&leaf->node);

	rcu_read_unlock();
	ret = skiplist_insert(list, slot, preload_token, NULL);

out:
	/*
	 * if we get an EEXIST here, it just means we lost the race.
	 * return eagain to the caller so they can update the hint
	 */
	if (ret == -EEXIST)
		ret = -EAGAIN;

	preempt_enable();
	return ret;
}
Exemplo n.º 19
0
/**
 * @brief TEST_CASE - Confirms incorrect inputs are handled gracefully for skiplist_insert.
 */
static int abuse_skiplist_insert( void )
{
	if( !skiplist_insert( NULL, 0 ) )
		return -1;
	return 0;
}
Exemplo n.º 20
0
static int test_stable_sort()
{
#define RECORDS 32
    int i;
    int result;
    int index1;
    int index2;
    int delete_count;
    int total_delete_count;
    Skiplist sl;
    SkiplistIterator iterator;
    Record records[RECORDS];
    Record *record;
    Record target;
    void *value;

    instance_count = 0;
    result = skiplist_init_ex(&sl, 12, compare_record,
            free_test_func, 128, skiplist_type);
    if (result != 0) {
        return result;
    }

    for (i=0; i<RECORDS; i++) {
        records[i].line = i + 1;
        records[i].key = i + 1;
    }

    for (i=0; i<RECORDS/4; i++) {
        index1 = (RECORDS - 1) * (int64_t)rand() / (int64_t)RAND_MAX;
        index2 = RECORDS - 1 - index1;
        if (index1 != index2) {
            records[index1].key = records[index2].key;
        }
    }

    for (i=0; i<RECORDS; i++) {
        if ((result=skiplist_insert(&sl, records + i)) != 0) {
            return result;
        }
        instance_count++;
    }
    assert(instance_count == RECORDS);

    for (i=0; i<RECORDS; i++) {
        value = skiplist_find(&sl, records + i);
        assert(value != NULL && ((Record *)value)->key == records[i].key);
    }

    i = 0;
    skiplist_iterator(&sl, &iterator);
    while ((value=skiplist_next(&iterator)) != NULL) {
        i++;
        record = (Record *)value;
        printf("%d => #%d\n", record->key, record->line);
    }
    assert(i==RECORDS);

    target.key = 10;
    target.line = 0;
    if (skiplist_find_all(&sl, &target, &iterator) == 0) {
        printf("found key: %d\n", target.key);
    }
    i = 0;
    while ((value=skiplist_next(&iterator)) != NULL) {
        i++;
        record = (Record *)value;
        printf("%d => #%d\n", record->key, record->line);
    }
    printf("found record count: %d\n", i);

    total_delete_count = 0;
    for (i=0; i<RECORDS; i++) {
        if ((result=skiplist_delete_all(&sl, records + i,
                        &delete_count)) == 0)
        {
            total_delete_count += delete_count;
        }
        assert((result == 0 && delete_count > 0) ||
                (result != 0 && delete_count == 0));
    }
    assert(total_delete_count == RECORDS);
    assert(instance_count == 0);

    i = 0;
    skiplist_iterator(&sl, &iterator);
    while ((value=skiplist_next(&iterator)) != NULL) {
        i++;
    }
    assert(i == 0);

    skiplist_destroy(&sl);
    assert(instance_count == 0);

    return 0;
}
Exemplo n.º 21
0
/**
 * @brief TEST_CASE - Sanity test of some key skiplist APIs using a pointer to data items.
 */
static int pointers( void )
{
	skiplist_t *skiplist;
	const coord_t coords[] =
	{
		/* Simple in order insertion. */
		{5,5},
		{7,5},

		/* Duplicate x with increasing y. */
		{5,6},
		{5,8},

		/* Duplicate x with decreasing y. */
		{7,4},
		{7,0},

		/* Decreasing x. */
		{4,5},
		{3,5},

		/* Increasing x. */
		{9,0},
		{10,0},

		/* Duplicate values. */
		{9,0},
		{5,5},

		/* Zero. */
		{0,0},

		/* Huge. */
		{UINT_MAX,UINT_MAX}
	};

	unsigned int i;
	skiplist_node_t *iter;
	coord_t tmp;

	skiplist = skiplist_create( SKIPLIST_PROPERTY_NONE, 8, coord_compare, coord_fprintf, NULL );
	if( !skiplist ) return -1;

	for( i = 0; i < sizeof(coords) / sizeof(coords[0]); ++i )
		if( skiplist_insert( skiplist, (uintptr_t) &coords[i] ) )
			return -1;

	/* Output skiplist for debugging purposes. */
	if( skiplist_fprintf_filename( "pointers.dot", skiplist ) )
		return -1;

	/* Confirm skiplist is in the correct order. */
	tmp.x = 0;
	tmp.y = 0;
	for( iter = skiplist_begin( skiplist ); iter != skiplist_end(); iter = skiplist_next( iter ) )
	{
		coord_t *cur = (coord_t *)skiplist_node_value( iter, NULL );
		if( cur->x < tmp.x ) return -1;
		if( cur->x == tmp.x && cur->y < tmp.y ) return -1;
		tmp = *cur;
	}

	/* Confirm the skiplist contains what we expect. */
	for( i = 0; i < sizeof(coords) / sizeof(coords[0]); ++i )
		if( !skiplist_contains( skiplist, (uintptr_t) &coords[i], NULL ) )
			return -1;

	/* If we use a different pointer to point to the same values the skiplist should skill contain it. */
	tmp = coords[0];
	if( !skiplist_contains( skiplist, (uintptr_t) &tmp, NULL ) )
		return -1;

	/* Free resources. */
	skiplist_destroy( skiplist );

	return 0;
}
Exemplo n.º 22
0
int
main(void)
{
        int i;
        struct timeval start, end;

        int *key = (int *)malloc(N * sizeof(int));
        if (key == NULL) {
                exit(-1);
        }

        struct skiplist *list = skiplist_new();
        if (list == NULL) {
                exit(-1);
        }

        printf("Test start!\n");
        printf("Add %d nodes...\n", N);

        /* Insert test */
        srandom(time(NULL));
        gettimeofday(&start, NULL);
        for (i = 0; i < N; i++) {
                int value = key[i] = (int)random();
                skiplist_insert(list, key[i], value);
        }
        gettimeofday(&end, NULL);
        printf("time span: %ldms\n", (end.tv_sec - start.tv_sec)*1000 + (end.tv_usec - start.tv_usec)/1000);
#ifdef SKIPLIST_DEBUG
        skiplist_dump(list);
#endif

        /* Search test 1 */
        printf("Now search each node by key...\n");
        gettimeofday(&start, NULL);
        for (i = 0; i < N; i++) {
                struct skipnode *node = skiplist_search_by_key(list, key[i]);
                if (node != NULL) {
#ifdef SKIPLIST_DEBUG
                        printf("key:0x%08x value:0x%08x\n", node->key, node->value);
#endif
                } else {
                        printf("Not found:0x%08x\n", key[i]);
                }
#ifdef SKIPLIST_DEBUG
                printf("key rank:%d\n", skiplist_key_rank(list, key[i]));
#else
                //skiplist_key_rank(list, key[i]);
#endif
        }
        gettimeofday(&end, NULL);
        printf("time span: %ldms\n", (end.tv_sec - start.tv_sec)*1000 + (end.tv_usec - start.tv_usec)/1000);

        /* Search test 2 */
        printf("Now search each node by rank...\n");
        gettimeofday(&start, NULL);
        for (i = 0; i < N; i++) {
                struct skipnode *node = skiplist_search_by_rank(list, i + 1);
                if (node != NULL) {
#ifdef SKIPLIST_DEBUG
                        printf("rank:%d value:0x%08x\n", i + 1, node->value);
#endif
                } else {
                        printf("Not found:%d\n", i + 1);
                }
        }
        gettimeofday(&end, NULL);
        printf("time span: %ldms\n", (end.tv_sec - start.tv_sec)*1000 + (end.tv_usec - start.tv_usec)/1000);

        /* Delete test */
        printf("Now remove all nodes...\n");
        gettimeofday(&start, NULL);
        for (i = 0; i < N; i++) {
                skiplist_remove(list, key[i]);
        }
        gettimeofday(&end, NULL);
        printf("time span: %ldms\n", (end.tv_sec - start.tv_sec)*1000 + (end.tv_usec - start.tv_usec)/1000);
#ifdef SKIPLIST_DEBUG
        skiplist_dump(list);
#endif

        printf("End of Test.\n");
        skiplist_delete(list);

        return 0;
}
Exemplo n.º 23
0
static int __init skiplist_init(void)
{
	int i;
	struct timeval start, end;
	struct skiplist *list;
	struct skipnode *node;
	int res = 0;

	int *key = kmalloc(N * sizeof(int), GFP_KERNEL);
	if (key == NULL) {
		printk("-ENOMEM\n");
		return -1;
	}

	printk("Starting initialization...\n");
	list = skiplist_create();
        if (list == NULL) {
		printk("-ENOMEM\n");
		return -1;
        }

	printk("Started initialization...\n");
        printk("Test start!\n");

	/* Test 01 */ 
	printk("Test 01: adding and search %d nodes testing!\n", N);
        printk("Add %d nodes...\n", N);

        do_gettimeofday(&start);
        for (i = 0; i < N; i++) {
                int value = key[i] = i;
               	skiplist_insert(list, key[i], value);
        }
        do_gettimeofday(&end);
        printk("time span:% ldms\n", (end.tv_sec - start.tv_sec)*1000 + (end.tv_usec - start.tv_usec)/1000);
#ifdef SKIPLIST_DEBUG
        skiplist_dump(list);
#endif

        /* Search test */
        printk("Now search %d node...\n", N);
        do_gettimeofday(&start);

        for (i = 0; i < N; i++) {
                struct skipnode *node = skiplist_search(list, key[i]);

                if (node != NULL) {
#ifdef SKIPLIST_DEBUG
                        printk("key:%d value:%d\n", node->key, node->value);
#endif
                } else {
                        printk("Not found:%d\n", key[i]);
			res = 1;
			break;
                }
        }
        do_gettimeofday(&end);
        printk("time span:% ldms\n", (end.tv_sec - start.tv_sec)*1000 + (end.tv_usec - start.tv_usec)/1000);
	if (res) {
		printk("Test 01: failed!\n");
		goto out_clean;
	} else {
		printk("Test 01: success!\n");
	}

	/* Test 02 */

	printk("Test 02: search single node (%d/2) testing!\n", N);
	node = skiplist_search(list, N/2);
	if (node && node->value == N/2) {
		printk("Test 02: Success!\n");
	} else {
		printk("Test 02: Failed!\n");
		res = 1;
		goto out_clean;
	}

	/* Test 03 */

	printk("Test 03: remove single node (%d/2) testing!\n", N);
	skiplist_remove(list, N/2);
	node = skiplist_search(list, N/2);
	if (!node) {
		printk("Test 03: Success!\n");
	} else {
		printk("Test 03: Failed (key:%d)!\n", node->key);
		res = 1;
		goto out_clean;
	}

	/* Test 04 */

	printk("Test 04: search single node equal or great than (%d/2) testing!\n", N);
	printk("Test 04: case 1: no equal node (%d/2) \n", N);
	node = skiplist_search_first_eq_big(list, N/2);
	if (!node || node->value != (N/2 + 1)) {
		printk("Test 04: Failed!\n");
		res = 1;
		goto out_clean;
	}

	printk("Test 04: case 2: has equal node (%d/2 + 1) \n", N);
	node = skiplist_search_first_eq_big(list, N/2 + 1);
	if (node && node->value == (N/2 + 1)) {
		printk("Test 04: Success!\n");
	} else {
		printk("Test 04: Failed!\n");
		res = 1;
		goto out_clean;
	}

	/* Test 05 */
	res = 0;
	printk("Test 05: remove all nodes\n");
        for (i = 0; i < N; i++) {
                skiplist_remove(list, key[i]);
        }

        for (i = 0; i < N; i++) {
		node = skiplist_search(list, key[i]);
		if (node) {
			res = 1;
			break;
		}
	}

	if (res)
		printk("Test 05: Failed!\n");
	else
		printk("Test 05: Success!\n");

#ifdef SKIPLIST_DEBUG
        skiplist_dump(list);
#endif

        printk("End of Test.\n");
out_clean:	

        skiplist_destroy(list);

        return 0;
}