Added shadow entity lookup, registry and pool.
This commit is contained in:
parent
726c231561
commit
3d73718aee
|
@ -1 +1,2 @@
|
|||
tests/internal/shadow-tag
|
||||
tests/internal/shadow-tag
|
||||
tests/internal/shadow-lookup
|
|
@ -4,10 +4,12 @@
|
|||
|
||||
#include <librr/types.h>
|
||||
#include <shadow-tag.h>
|
||||
#include <shadow.h>
|
||||
|
||||
typedef struct MtContext
|
||||
{
|
||||
MtShadowTagSystem shadow_tag_system;
|
||||
MtShadowRegistry *shadow_registry;
|
||||
} MtContext;
|
||||
|
||||
#endif // MT_CONTEXT_H
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
|
||||
#ifndef MT_SHADOW_H
|
||||
#define MT_SHADOW_H
|
||||
|
||||
#include <librr/types.h>
|
||||
#include <shadow-tag.h>
|
||||
|
||||
typedef struct MtShadowRegistry MtShadowRegistry;
|
||||
typedef struct MtShadow MtShadow;
|
||||
typedef struct MtShadowPool MtShadowPool;
|
||||
typedef struct MtShadowLookupTree MtShadowLookupTree;
|
||||
|
||||
/// @brief: An MtShadow contains the actual information which is used
|
||||
/// each time when an entity is modified. It contains the tags and
|
||||
/// other meta-information as well as data required for optimization.
|
||||
struct MtShadow
|
||||
{
|
||||
void *context;
|
||||
MtShadowTag *tag_chain_start;
|
||||
u32_t identifier;
|
||||
|
||||
MtShadowPool *pool;
|
||||
MtShadow *pool_next;
|
||||
};
|
||||
|
||||
struct MtShadowPool
|
||||
{
|
||||
usz_t capacity;
|
||||
MtShadow *shadows;
|
||||
MtShadow *first_free;
|
||||
MtShadowPool *continuation;
|
||||
};
|
||||
|
||||
typedef struct MtShadowLookupLevel3
|
||||
{
|
||||
MtShadow *next[256];
|
||||
} MtShadowLookupLevel3;
|
||||
|
||||
typedef struct MtShadowLookupLevel2
|
||||
{
|
||||
MtShadowLookupLevel3 *next[256];
|
||||
} MtShadowLookupLevel2;
|
||||
|
||||
typedef struct MtShadowLookup1
|
||||
{
|
||||
MtShadowLookupLevel2 *next[256];
|
||||
} MtShadowLookupLevel1;
|
||||
|
||||
struct MtShadowLookupTree
|
||||
{
|
||||
MtShadowLookupLevel1 *next[256];
|
||||
};
|
||||
|
||||
struct MtShadowRegistry
|
||||
{
|
||||
// TODO: The IDs must be assigned using a singly linked list of indices
|
||||
// to the next free entry, the index representing the ID's value and having
|
||||
// stored the next free entry's index. Conceptually similar to the internals
|
||||
// of the old File Allocation Table filesystems (FAT12, FAT16, FAT32).
|
||||
u32_t id_counter;
|
||||
MtShadowPool root_pool;
|
||||
MtShadowLookupTree lookup_tree;
|
||||
void *context_ptr;
|
||||
};
|
||||
|
||||
MtShadowRegistry mt_create_shadow_registry(void *context_ptr);
|
||||
void mt_cleanup_shadow_registry(MtShadowRegistry *registry);
|
||||
|
||||
MtShadow * mt_create_shadow(MtShadowRegistry *registry);
|
||||
MtShadow * mt_lookup_shadow(MtShadowRegistry *registry, u32_t identifier);
|
||||
void mt_delete_shadow(MtShadowRegistry *registry, MtShadow *shadow);
|
||||
|
||||
void mt_cleanup_shadow_pool(MtShadowPool *pool);
|
||||
void mt_free_shadow_pool(MtShadowPool *pool);
|
||||
MtShadowLookupTree mt_create_shadow_lookup_tree();
|
||||
|
||||
void mt_init_shadow_pool(MtShadowPool *pool, usz_t capacity);
|
||||
MtShadowPool * mt_new_shadow_pool(usz_t capacity);
|
||||
MtShadow * mt_pool_shadow(MtShadowPool *pool);
|
||||
void mt_unpool_shadow(MtShadow *shadow);
|
||||
|
||||
#endif // MT_SHADOW_H
|
|
@ -0,0 +1,90 @@
|
|||
#include <shadow.h>
|
||||
#include <context.h>
|
||||
#include <stdlib.h>
|
||||
#include <librr/memory.h>
|
||||
|
||||
MtShadowLookupTree mt_create_shadow_lookup_tree()
|
||||
{
|
||||
MtShadowLookupTree lookup_tree;
|
||||
rr_memset(&lookup_tree.next[0], sizeof(MtShadow *) * 256, 0);
|
||||
return lookup_tree;
|
||||
}
|
||||
|
||||
MtShadow * mt_lookup_shadow(MtShadowRegistry *registry, u32_t identifier)
|
||||
{
|
||||
u8_t index_1 = identifier >> 24;
|
||||
u8_t index_2 = (identifier >> 16) & 0xff;
|
||||
u8_t index_3 = (identifier >> 8) & 0xff;
|
||||
u8_t index_4 = identifier & 0xff;
|
||||
MtShadowLookupLevel1 *level_1 = registry->lookup_tree.next[index_1];
|
||||
if(level_1 == NULL)
|
||||
return NULL;
|
||||
MtShadowLookupLevel2 *level_2 = level_1->next[index_2];
|
||||
if(level_2 == NULL)
|
||||
return NULL;
|
||||
MtShadowLookupLevel3 *level_3 = level_2->next[index_3];
|
||||
if(level_3 == NULL)
|
||||
return NULL;
|
||||
MtShadow *shadow = level_3->next[index_4];
|
||||
return shadow;
|
||||
}
|
||||
|
||||
void mt_delete_shadow(MtShadowRegistry *registry, MtShadow *shadow)
|
||||
{
|
||||
u32_t identifier = shadow->identifier;
|
||||
mt_unpool_shadow(shadow);
|
||||
|
||||
u8_t index_1 = identifier >> 24;
|
||||
u8_t index_2 = (identifier >> 16) & 0xff;
|
||||
u8_t index_3 = (identifier >> 8) & 0xff;
|
||||
u8_t index_4 = identifier & 0xff;
|
||||
MtShadowLookupLevel1 *level_1 = registry->lookup_tree.next[index_1];
|
||||
if(level_1 == NULL)
|
||||
return;
|
||||
MtShadowLookupLevel2 *level_2 = level_1->next[index_2];
|
||||
if(level_2 == NULL)
|
||||
return;
|
||||
MtShadowLookupLevel3 *level_3 = level_2->next[index_3];
|
||||
if(level_3 == NULL)
|
||||
return;
|
||||
level_3->next[index_4] = NULL;
|
||||
}
|
||||
|
||||
void mt_write_shadow_lookup_entry(MtShadowLookupTree *tree, MtShadow *shadow)
|
||||
{
|
||||
u32_t identifier = shadow->identifier;
|
||||
|
||||
u8_t index_1 = identifier >> 24;
|
||||
u8_t index_2 = (identifier >> 16) & 0xff;
|
||||
u8_t index_3 = (identifier >> 8) & 0xff;
|
||||
u8_t index_4 = identifier & 0xff;
|
||||
MtShadowLookupLevel1 *level_1 = tree->next[index_1];
|
||||
if(level_1 == NULL)
|
||||
{
|
||||
tree->next[index_1] = calloc(sizeof(MtShadowLookupLevel1), 256);
|
||||
level_1 = tree->next[index_1];
|
||||
}
|
||||
MtShadowLookupLevel2 *level_2 = level_1->next[index_2];
|
||||
if(level_2 == NULL)
|
||||
{
|
||||
level_1->next[index_1] = calloc(sizeof(MtShadowLookupLevel2), 256);
|
||||
level_2 = level_1->next[index_2];
|
||||
}
|
||||
MtShadowLookupLevel3 *level_3 = level_2->next[index_3];
|
||||
if(level_3 == NULL)
|
||||
{
|
||||
level_2->next[index_1] = calloc(sizeof(MtShadowLookupLevel3), 256);
|
||||
level_3 = level_2->next[index_3];
|
||||
}
|
||||
level_3->next[index_4] = shadow;
|
||||
}
|
||||
|
||||
MtShadow * mt_create_shadow(MtShadowRegistry *registry)
|
||||
{
|
||||
MtShadow *shadow = mt_pool_shadow(®istry->root_pool);
|
||||
shadow->identifier = registry->id_counter;
|
||||
shadow->context = registry->context_ptr;
|
||||
shadow->tag_chain_start = NULL;
|
||||
mt_write_shadow_lookup_entry(®istry->lookup_tree, shadow);
|
||||
return shadow;
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
#include <shadow.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void mt_init_shadow_pool_allocation(MtShadowPool *pool)
|
||||
{
|
||||
usz_t capacity = pool->capacity;
|
||||
usz_t shadow_index = 0;
|
||||
while(shadow_index < capacity)
|
||||
{
|
||||
pool->shadows[shadow_index].pool = pool;
|
||||
pool->shadows[shadow_index].pool_next = &pool->shadows[shadow_index+1];
|
||||
++shadow_index;
|
||||
}
|
||||
pool->shadows[capacity-1].pool_next = NULL;
|
||||
}
|
||||
|
||||
void mt_init_shadow_pool(MtShadowPool *pool, usz_t capacity)
|
||||
{
|
||||
pool->capacity = capacity;
|
||||
pool->continuation = NULL;
|
||||
pool->shadows = calloc(sizeof(MtShadow), capacity);
|
||||
pool->first_free = pool->shadows;
|
||||
mt_init_shadow_pool_allocation(pool);
|
||||
}
|
||||
|
||||
void mt_cleanup_shadow_pool(MtShadowPool *pool)
|
||||
{
|
||||
if(pool->continuation != NULL)
|
||||
{
|
||||
mt_cleanup_shadow_pool(pool->continuation);
|
||||
free(pool->continuation);
|
||||
}
|
||||
free(pool->shadows);
|
||||
}
|
||||
|
||||
void mt_free_shadow_pool(MtShadowPool *pool)
|
||||
{
|
||||
mt_cleanup_shadow_pool(pool);
|
||||
free(pool);
|
||||
}
|
||||
|
||||
MtShadowPool * mt_new_shadow_pool(usz_t capacity)
|
||||
{
|
||||
MtShadowPool *pool = malloc(sizeof(MtShadowPool));
|
||||
mt_init_shadow_pool(pool, capacity);
|
||||
return pool;
|
||||
}
|
||||
|
||||
MtShadow * mt_pool_shadow(MtShadowPool *pool)
|
||||
{
|
||||
if(pool->first_free == NULL)
|
||||
{
|
||||
if(pool->continuation == NULL)
|
||||
pool->continuation = mt_new_shadow_pool(pool->capacity * 2);
|
||||
return mt_pool_shadow(pool->continuation);
|
||||
}
|
||||
MtShadow *result = pool->first_free;
|
||||
pool->first_free = result->pool_next;
|
||||
return result;
|
||||
}
|
||||
|
||||
void mt_unpool_shadow(MtShadow *shadow)
|
||||
{
|
||||
shadow->pool_next = shadow->pool->first_free;
|
||||
shadow->pool->first_free = shadow;
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
#include <shadow.h>
|
||||
#include <librr/memory.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void mt_delete_shadow_lookup_tree_of_registry(MtShadowRegistry *registry);
|
||||
|
||||
MtShadowRegistry mt_create_shadow_registry(void *context_ptr)
|
||||
{
|
||||
MtShadowRegistry registry;
|
||||
registry.id_counter = 1;
|
||||
registry.context_ptr = context_ptr;
|
||||
registry.lookup_tree = mt_create_shadow_lookup_tree();
|
||||
mt_init_shadow_pool(®istry.root_pool, 16384);
|
||||
return registry;
|
||||
}
|
||||
|
||||
void mt_cleanup_shadow_registry(MtShadowRegistry *registry)
|
||||
{
|
||||
mt_delete_shadow_lookup_tree_of_registry(registry);
|
||||
mt_cleanup_shadow_pool(®istry->root_pool);
|
||||
}
|
||||
|
||||
void mt_cleanup_shadow_data(MtShadow *shadow)
|
||||
{
|
||||
if(shadow->tag_chain_start != NULL)
|
||||
mt_free_shadow_tag_chain(shadow->tag_chain_start);
|
||||
}
|
||||
|
||||
void mt_delete_shadow_lookup_tree_of_registry(MtShadowRegistry *registry)
|
||||
{
|
||||
MtShadowLookupTree *lookup_tree = ®istry->lookup_tree;
|
||||
u32_t index_1 = 0;
|
||||
while(index_1 < 256)
|
||||
{
|
||||
MtShadowLookupLevel1 *level_1 = lookup_tree->next[index_1];
|
||||
if(level_1 == NULL)
|
||||
{
|
||||
++index_1;
|
||||
continue;
|
||||
}
|
||||
u32_t index_2 = 0;
|
||||
while(index_2 < 256)
|
||||
{
|
||||
MtShadowLookupLevel2 *level_2 = level_1->next[index_2];
|
||||
if(level_2 == NULL)
|
||||
{
|
||||
++index_2;
|
||||
continue;
|
||||
}
|
||||
u32_t index_3 = 0;
|
||||
while(index_3 < 256)
|
||||
{
|
||||
MtShadowLookupLevel3 *level_3 = level_2->next[index_3];
|
||||
if(level_3 == NULL)
|
||||
{
|
||||
++index_3;
|
||||
continue;
|
||||
}
|
||||
u32_t index_4 = 0;
|
||||
while(index_4 < 256)
|
||||
{
|
||||
MtShadow *shadow = level_3->next[index_4];
|
||||
if(shadow == NULL)
|
||||
{
|
||||
++index_4;
|
||||
continue;
|
||||
}
|
||||
mt_cleanup_shadow_data(shadow);
|
||||
++index_4;
|
||||
}
|
||||
free(level_3);
|
||||
++index_3;
|
||||
}
|
||||
free(level_2);
|
||||
++index_2;
|
||||
}
|
||||
free(level_1);
|
||||
++index_1;
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
core/inc-c
|
|
@ -0,0 +1,55 @@
|
|||
#include <shadow.h>
|
||||
#include <context.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
|
||||
MtShadowRegistry registry;
|
||||
|
||||
void cleanup_and_exit(int status_code)
|
||||
{
|
||||
mt_cleanup_shadow_registry(®istry);
|
||||
}
|
||||
|
||||
void signal_handler(int number)
|
||||
{
|
||||
printf("FAIL: The program crashed because of a memory access error!\n");
|
||||
exit(-8);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
signal(SIGSEGV, &signal_handler);
|
||||
registry = mt_create_shadow_registry(NULL);
|
||||
MtShadow *original_1 = mt_create_shadow(®istry);
|
||||
MtShadow *lookedup_1 = mt_lookup_shadow(®istry, original_1->identifier);
|
||||
|
||||
MtShadow *original_2 = mt_create_shadow(®istry);
|
||||
MtShadow *lookedup_2 = mt_lookup_shadow(®istry, original_2->identifier);
|
||||
|
||||
if(original_1 != lookedup_1)
|
||||
{
|
||||
puts("FAIL: In test case 1, the original shadow doesn't match the looked-up one.");
|
||||
printf("O %p : L %p\n", original_1, lookedup_1);
|
||||
cleanup_and_exit(-1);
|
||||
}
|
||||
if(original_2 != lookedup_2)
|
||||
{
|
||||
puts("FAIL: In test case 2, the original shadow doesn't match the looked-up one.");
|
||||
printf("O %p : L %p\n", original_2, lookedup_2);
|
||||
cleanup_and_exit(-2);
|
||||
}
|
||||
if(original_1 == original_2)
|
||||
{
|
||||
puts("FAIL: In test case 3, the first original shadow matches the second!");
|
||||
cleanup_and_exit(-3);
|
||||
}
|
||||
if(lookedup_1 == lookedup_2)
|
||||
{
|
||||
puts("FAIL: In test case 3, the first looked-up shadow matches the second!");
|
||||
cleanup_and_exit(-4);
|
||||
}
|
||||
puts("Success.");
|
||||
cleanup_and_exit(0);
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue