59 #include "lib/random.h"
66 #define DEBUG DEBUG_NONE
69 #define BRANCH_FACTOR 2
70 #define BUCKET_SIZE 128
71 #define NODE_LIMIT 511
74 #if (1 << NODE_DEPTH) != (NODE_LIMIT + 1)
75 #error "NODE_DEPTH is set incorrectly."
78 #define EMPTY_NODE(node) ((node)->min == 0 && (node)->max == 0)
79 #define EMPTY_PAIR(pair) ((pair)->key == 0 && (pair)->value == 0)
81 typedef uint16_t maxheap_key_t;
82 typedef uint16_t maxheap_value_t;
91 typedef struct heap_node heap_node_t;
93 struct key_value_pair {
95 maxheap_value_t value;
99 struct key_value_pair pairs[BUCKET_SIZE];
101 typedef struct bucket bucket_t;
104 db_storage_id_t heap_storage;
105 db_storage_id_t bucket_storage;
107 uint8_t next_free_slot[NODE_LIMIT];
109 typedef struct heap heap_t;
111 struct bucket_cache {
118 static struct bucket_cache bucket_cache[DB_HEAP_CACHE_LIMIT];
119 MEMB(heaps, heap_t, DB_HEAP_INDEX_LIMIT);
121 static struct bucket_cache *get_cache(heap_t *,
int);
122 static struct bucket_cache *get_cache_free(
void);
123 static void invalidate_cache(
void);
124 static maxheap_key_t transform_key(maxheap_key_t);
125 static int heap_read(heap_t *,
int, heap_node_t *);
126 static int heap_write(heap_t *,
int, heap_node_t *);
127 static int heap_insert(heap_t *, maxheap_key_t, maxheap_key_t);
128 static int heap_find(heap_t *, maxheap_key_t key,
int *iterator);
130 static void heap_print(heap_t *);
132 static int bucket_read(heap_t *,
int, bucket_t *);
133 static struct bucket_cache *bucket_load(heap_t *,
int);
134 static int bucket_append(heap_t *,
int,
struct key_value_pair *);
135 static int bucket_split(heap_t *,
int);
137 static db_result_t create(index_t *);
138 static db_result_t destroy(index_t *);
139 static db_result_t load(index_t *);
140 static db_result_t release(index_t *);
141 static db_result_t insert(index_t *, attribute_value_t *, tuple_id_t);
142 static db_result_t
delete(index_t *, attribute_value_t *);
143 static tuple_id_t get_next(index_iterator_t *);
145 index_api_t index_maxheap = {
157 static struct bucket_cache *
158 get_cache(heap_t *heap,
int bucket_id)
162 for(i = 0; i < DB_HEAP_CACHE_LIMIT; i++) {
163 if(bucket_cache[i].heap == heap && bucket_cache[i].bucket_id == bucket_id) {
164 return &bucket_cache[i];
170 static struct bucket_cache *
175 for(i = 0; i < DB_HEAP_CACHE_LIMIT; i++) {
176 if(bucket_cache[i].heap ==
NULL) {
177 return &bucket_cache[i];
184 invalidate_cache(
void)
188 for(i = 0; i < DB_HEAP_CACHE_LIMIT; i++) {
189 if(bucket_cache[i].heap !=
NULL) {
190 bucket_cache[i].heap =
NULL;
197 transform_key(maxheap_key_t key)
204 heap_read(heap_t *heap,
int bucket_id, heap_node_t *node)
206 if(DB_ERROR(storage_read(heap->heap_storage, node,
207 DB_MAX_FILENAME_LENGTH + (
unsigned long)bucket_id *
sizeof(*node),
sizeof(*node)))) {
215 heap_write(heap_t *heap,
int bucket_id, heap_node_t *node)
217 if(DB_ERROR(storage_write(heap->heap_storage, node,
218 DB_MAX_FILENAME_LENGTH + (
unsigned long)bucket_id *
sizeof(*node),
sizeof(*node)))) {
226 heap_insert(heap_t *heap, maxheap_key_t min, maxheap_key_t max)
231 PRINTF(
"DB: Insert node (%ld,%ld) into the heap\n", (
long)min, (
long)max);
237 for(i = 0; i < NODE_LIMIT;) {
238 if(heap_read(heap, i, &node) == 0) {
239 PRINTF(
"DB: Failed to read heap node %d\n", i);
243 if(EMPTY_NODE(&node)) {
246 if(heap_write(heap, i, &node) == 0) {
247 PRINTF(
"DB: Failed to write heap node %d\n", i);
251 }
else if(node.min <= min && max <= node.max) {
252 i = BRANCH_FACTOR * i + 1;
258 PRINTF(
"DB: No more nodes available\n");
263 heap_find(heap_t *heap, maxheap_key_t key,
int *iterator)
265 maxheap_key_t hashed_key;
268 static heap_node_t node;
270 hashed_key = transform_key(key);
272 for(i = *iterator; i < NODE_LIMIT;) {
273 if(heap_read(heap, i, &node) == 0) {
276 if(EMPTY_NODE(&node)) {
278 }
else if(node.min <= hashed_key && hashed_key <= node.max) {
279 first_child = BRANCH_FACTOR * i + 1;
281 if(first_child >= NODE_LIMIT) {
284 *iterator = first_child;
296 heap_print(heap_t *heap)
306 branch_amount = BRANCH_FACTOR;
309 if(heap_read(heap, i, &node) == 0 || EMPTY_NODE(&node)) {
313 for(j = 0; j < level_count; j++) {
316 PRINTF(
"(%ld,%ld)\n", (
long)node.min, (
long)node.max);
317 if(level_count == 0) {
319 }
else if(branch_count + 1 == branch_amount) {
322 branch_amount = branch_amount * BRANCH_FACTOR;
331 bucket_read(heap_t *heap,
int bucket_id, bucket_t *bucket)
335 if(heap->next_free_slot[bucket_id] == 0) {
338 size = heap->next_free_slot[bucket_id];
341 size *=
sizeof(
struct key_value_pair);
343 if(DB_ERROR(storage_read(heap->bucket_storage, bucket,
344 (
unsigned long)bucket_id *
sizeof(*bucket), size))) {
351 static struct bucket_cache *
352 bucket_load(heap_t *heap,
int bucket_id)
355 struct bucket_cache *cache;
357 cache = get_cache(heap, bucket_id);
362 cache = get_cache_free();
365 cache = get_cache_free();
371 if(bucket_read(heap, bucket_id, &cache->bucket) == 0) {
376 cache->bucket_id = bucket_id;
378 if(heap->next_free_slot[bucket_id] == 0) {
379 for(i = 0; i < BUCKET_SIZE; i++) {
380 if(EMPTY_PAIR(&cache->bucket.pairs[i])) {
385 heap->next_free_slot[bucket_id] = i;
388 PRINTF(
"DB: Loaded bucket %d, the next free slot is %u\n", bucket_id,
389 (
unsigned)heap->next_free_slot[bucket_id]);
395 bucket_append(heap_t *heap,
int bucket_id,
struct key_value_pair *pair)
397 unsigned long offset;
399 if(heap->next_free_slot[bucket_id] >= BUCKET_SIZE) {
400 PRINTF(
"DB: Invalid write attempt to the full bucket %d\n", bucket_id);
404 offset = (
unsigned long)bucket_id *
sizeof(bucket_t);
405 offset += heap->next_free_slot[bucket_id] *
sizeof(
struct key_value_pair);
407 if(DB_ERROR(storage_write(heap->bucket_storage, pair, offset,
sizeof(*pair)))) {
411 heap->next_free_slot[bucket_id]++;
417 bucket_split(heap_t *heap,
int bucket_id)
421 int small_bucket_index;
422 int large_bucket_index;
424 if(heap_read(heap, bucket_id, &node) == 0) {
428 mean = node.min + ((node.max - node.min) / 2);
430 PRINTF(
"DB: Split bucket %d (%ld, %ld) at mean value %ld\n", bucket_id,
431 (
long)node.min, (
long)node.max, (
long)mean);
433 small_bucket_index = heap_insert(heap, node.min, mean);
434 if(small_bucket_index < 0) {
438 large_bucket_index = heap_insert(heap, mean + 1, node.max);
439 if(large_bucket_index < 0) {
448 insert_item(heap_t *heap, maxheap_key_t key, maxheap_value_t value)
451 int bucket_id, last_good_bucket_id;
452 struct key_value_pair pair;
454 for(heap_iterator = 0, last_good_bucket_id = -1;;) {
455 bucket_id = heap_find(heap, key, &heap_iterator);
459 last_good_bucket_id = bucket_id;
461 bucket_id = last_good_bucket_id;
464 PRINTF(
"DB: No bucket for key %ld\n", (
long)key);
471 if(heap->next_free_slot[bucket_id] == BUCKET_SIZE) {
472 PRINTF(
"DB: Bucket %d is full\n", bucket_id);
473 if(bucket_split(heap, bucket_id) == 0) {
478 bucket_id = heap_find(heap, key, &heap_iterator);
484 if(bucket_append(heap, bucket_id, &pair) == 0) {
488 PRINTF(
"DB: Inserted key %ld (hash %ld) into the heap at bucket_id %d\n",
489 (
long)key, (
long)transform_key(key), bucket_id);
495 create(index_t *index)
497 char heap_filename[DB_MAX_FILENAME_LENGTH];
498 char bucket_filename[DB_MAX_FILENAME_LENGTH];
505 bucket_filename[0] =
'\0';
509 filename = storage_generate_file(
"heap",
510 (
unsigned long)NODE_LIMIT *
sizeof(heap_node_t));
511 if(filename ==
NULL) {
512 PRINTF(
"DB: Failed to generate a heap file\n");
513 return DB_INDEX_ERROR;
516 memcpy(index->descriptor_file, filename,
517 sizeof(index->descriptor_file));
519 PRINTF(
"DB: Generated the heap file \"%s\" using %lu bytes of space\n",
520 index->descriptor_file, (
unsigned long)NODE_LIMIT *
sizeof(heap_node_t));
522 index->opaque_data = heap =
memb_alloc(&heaps);
524 PRINTF(
"DB: Failed to allocate a heap\n");
525 result = DB_ALLOCATION_ERROR;
528 heap->heap_storage = -1;
529 heap->bucket_storage = -1;
532 filename = storage_generate_file(
"bucket",
533 (
unsigned long)NODE_LIMIT *
sizeof(bucket_t));
534 if(filename ==
NULL) {
535 PRINTF(
"DB: Failed to generate a bucket file\n");
536 result = DB_INDEX_ERROR;
539 memcpy(bucket_filename, filename,
sizeof(bucket_filename));
541 PRINTF(
"DB: Generated the bucket file \"%s\" using %lu bytes of space\n",
542 bucket_filename, (
unsigned long)NODE_LIMIT *
sizeof(bucket_t));
545 memset(&heap->next_free_slot, 0,
sizeof(heap->next_free_slot));
547 heap->heap_storage = storage_open(index->descriptor_file);
548 heap->bucket_storage = storage_open(bucket_filename);
549 if(heap->heap_storage < 0 || heap->bucket_storage < 0) {
550 result = DB_STORAGE_ERROR;
554 if(DB_ERROR(storage_write(heap->heap_storage, &bucket_filename, 0,
555 sizeof(bucket_filename)))) {
556 result = DB_STORAGE_ERROR;
560 if(heap_insert(heap, KEY_MIN, KEY_MAX) < 0) {
561 PRINTF(
"DB: Heap insertion error\n");
562 result = DB_INDEX_ERROR;
566 PRINTF(
"DB: Created a heap index\n");
570 if(result != DB_OK) {
572 storage_close(heap->bucket_storage);
573 storage_close(heap->heap_storage);
576 if(index->descriptor_file[0] !=
'\0') {
578 index->descriptor_file[0] =
'\0';
580 if(bucket_filename[0] !=
'\0') {
588 destroy(index_t *index)
591 return DB_INDEX_ERROR;
599 char bucket_file[DB_MAX_FILENAME_LENGTH];
601 index->opaque_data = heap =
memb_alloc(&heaps);
603 PRINTF(
"DB: Failed to allocate a heap\n");
604 return DB_ALLOCATION_ERROR;
607 fd = storage_open(index->descriptor_file);
609 return DB_STORAGE_ERROR;
612 if(storage_read(fd, bucket_file, 0,
sizeof(bucket_file)) !=
613 sizeof(bucket_file)) {
615 return DB_STORAGE_ERROR;
620 heap->heap_storage = storage_open(index->descriptor_file);
621 heap->bucket_storage = storage_open(bucket_file);
623 memset(&heap->next_free_slot, 0,
sizeof(heap->next_free_slot));
625 PRINTF(
"DB: Loaded max-heap index from file %s and bucket file %s\n",
626 index->descriptor_file, bucket_file);
632 release(index_t *index)
636 heap = index->opaque_data;
638 storage_close(heap->bucket_storage);
639 storage_close(heap->heap_storage);
641 return DB_INDEX_ERROR;
645 insert(index_t *index, attribute_value_t *key, tuple_id_t value)
650 heap = (heap_t *)index->opaque_data;
652 long_key = db_value_to_long(key);
654 if(insert_item(heap, (maxheap_key_t)long_key,
655 (maxheap_value_t)value) == 0) {
656 PRINTF(
"DB: Failed to insert key %ld into a max-heap index\n", long_key);
657 return DB_INDEX_ERROR;
663 delete(index_t *index, attribute_value_t *value)
665 return DB_INDEX_ERROR;
669 get_next(index_iterator_t *iterator)
671 struct iteration_cache {
672 index_iterator_t *index_iterator;
674 tuple_id_t found_items;
676 int visited_buckets[NODE_DEPTH];
679 static struct iteration_cache cache;
683 int tmp_heap_iterator;
685 struct bucket_cache *bcache;
686 uint8_t next_free_slot;
688 heap = (heap_t *)iterator->index->opaque_data;
689 key = *(maxheap_key_t *)&iterator->min_value;
691 if(cache.index_iterator != iterator || iterator->next_item_no == 0) {
693 cache.end = NODE_DEPTH - 1;
694 cache.found_items = cache.start = 0;
695 cache.index_iterator = iterator;
699 for(i = tmp_heap_iterator = 0; i < NODE_DEPTH; i++) {
700 cache.visited_buckets[i] = heap_find(heap, key, &tmp_heap_iterator);
701 if(cache.visited_buckets[i] < 0) {
706 cache.heap_iterator = cache.end;
715 for(; cache.heap_iterator >= 0; cache.heap_iterator--) {
716 bucket_id = cache.visited_buckets[cache.heap_iterator];
718 PRINTF(
"DB: Find key %lu in bucket %d\n", (
unsigned long)key, bucket_id);
720 if((bcache = bucket_load(heap, bucket_id)) ==
NULL) {
721 PRINTF(
"DB: Failed to load bucket %d\n", bucket_id);
722 return INVALID_TUPLE;
727 next_free_slot = heap->next_free_slot[bucket_id];
728 for(i = cache.start; i < next_free_slot; i++) {
729 if(bcache->bucket.pairs[i].key == key) {
730 if(cache.found_items++ == iterator->next_item_no) {
731 iterator->next_item_no++;
733 PRINTF(
"DB: Found key %ld with value %lu\n", (
long)key,
734 (
unsigned long)bcache->bucket.pairs[i].value);
735 return (tuple_id_t)bcache->bucket.pairs[i].value;
741 if(VALUE_INT(&iterator->min_value) == VALUE_INT(&iterator->max_value)) {
742 PRINTF(
"DB: Could not find key %ld in the index\n", (
long)key);
743 return INVALID_TUPLE;
746 iterator->next_item_no = 0;
747 VALUE_INT(&iterator->min_value)++;
749 return get_next(iterator);
The storage interface used by the database.
Declarations for the result acquisition API.
char memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().
void * memb_alloc(struct memb *m)
Allocate a memory block from a block of memory declared with MEMB().
#define NULL
The null pointer.
void random_init(unsigned short seed)
Seed the cc2430 random number generator.
Database configuration options.
int cfs_remove(const char *name)
Remove a file.
#define MEMB(name, structure, num)
Declare a memory block.
A set of debugging macros.
Header for the Coffee file system.
Memory block allocation routines.
unsigned short random_rand(void)
Generate the next state and return the upper part of it.