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 <librr/types.h>
|
||||||
#include <shadow-tag.h>
|
#include <shadow-tag.h>
|
||||||
|
#include <shadow.h>
|
||||||
|
|
||||||
typedef struct MtContext
|
typedef struct MtContext
|
||||||
{
|
{
|
||||||
MtShadowTagSystem shadow_tag_system;
|
MtShadowTagSystem shadow_tag_system;
|
||||||
|
MtShadowRegistry *shadow_registry;
|
||||||
} MtContext;
|
} MtContext;
|
||||||
|
|
||||||
#endif // MT_CONTEXT_H
|
#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