Skip to content

Commit

Permalink
Replaced 'Trie' component with 'GNode' in Stage
Browse files Browse the repository at this point in the history
- see #34
  • Loading branch information
mwatts15 committed Feb 21, 2015
1 parent 3de9e03 commit c0991eb
Show file tree
Hide file tree
Showing 7 changed files with 217 additions and 122 deletions.
7 changes: 7 additions & 0 deletions key.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ void key_push_end (tagdb_key_t k, key_elem_t e)
g_array_append_val(k, e);
}

key_elem_t key_pop_front (tagdb_key_t k)
{
key_elem_t res = g_array_index(k, key_elem_t, 0);
g_array_remove_index(k, 0);
return res;
}

tagdb_key_t key_copy (tagdb_key_t k)
{
tagdb_key_t res = key_new();
Expand Down
1 change: 1 addition & 0 deletions key.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ tagdb_key_t make_key (key_elem_t *args, int nkeys);
tagdb_key_t key_copy (tagdb_key_t k);
void key_destroy (tagdb_key_t k);
void key_push_end (tagdb_key_t k, key_elem_t e);
key_elem_t key_pop_front (tagdb_key_t k);
key_elem_t key_ref (tagdb_key_t k, int index);
int key_is_empty (tagdb_key_t k);
void key_sort (tagdb_key_t k, GCompareFunc c);
Expand Down
126 changes: 92 additions & 34 deletions stage.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,73 +4,131 @@

#define trie_index(__t) ((__t)->index)

/* Modifies the key given */
GNode *_node_lookup(GNode *n, tagdb_key_t position);

/* Staging tags created with mkdir */
Stage *new_stage ()
{
Stage *res = g_try_malloc0(sizeof(Stage));
trie_index(res) = g_hash_table_new(g_direct_hash, g_direct_equal);
if (!res)
return NULL;
res->data = new_trie();
res->tree = g_node_new(TO_SP(-1));
return res;
}

AbstractFile* stage_lookup (Stage *s, tagdb_key_t position, file_id_t id)
gboolean stage_lookup (Stage *s, tagdb_key_t position, file_id_t id)
{
return trie_retrieve(s->data, position, TO_SP(id));
tagdb_key_t lookup_key = key_copy(position);
key_push_end(lookup_key, id);
GNode *n = _node_lookup(s->tree, lookup_key);
key_destroy(lookup_key);
if (n)
{
return (id == TO_S(n->data));
}
return FALSE;
}

void stage_add (Stage *s, tagdb_key_t position, AbstractFile *item)
GNode *_node_lookup (GNode *n, tagdb_key_t position)
{

tagdb_key_t index_key = key_copy(position);
key_push_end(index_key, get_file_id(item));
KL(index_key, i)
if (key_is_empty(position))
{
gpointer k = TO_SP(key_ref(index_key, i));
GList *l = g_hash_table_lookup(trie_index(s), k);
l = g_list_prepend(l, key_copy(position));
g_hash_table_insert(trie_index(s), k, l);
return n;
}
key_destroy(index_key);

trie_insert(s->data, position, TO_SP(get_file_id(item)), item);
key_elem_t child_id = key_pop_front(position);
GNode *child = g_node_find_child(n, G_TRAVERSE_ALL, TO_SP(child_id));

if (child)
{
return _node_lookup(child, position);
}
else
{
return child;
}
}

void trie_remove_by_bucket_key (Stage *t, AbstractFile *s)
GNode *_node_lookup_create (GNode *n, tagdb_key_t position)
{
gpointer id = TO_SP(get_file_id(s));
GList *l = g_hash_table_lookup(trie_index(t), id);
LL(l, it)
if (key_is_empty(position))
{
return n;
}

key_elem_t child_id = key_pop_front(position);
GNode *child = g_node_find_child(n, G_TRAVERSE_ALL, TO_SP(child_id));

if (child)
{
return _node_lookup_create(child, position);
}
else
{
stage_remove(t, it->data, s);
}LL_END;
g_hash_table_remove(trie_index(t), id);
g_list_free_full(l, (GDestroyNotify)key_destroy);
GNode *new_child = g_node_new(TO_SP(child_id));
g_node_insert(n, 0, new_child);
return _node_lookup_create(new_child, position);
}
}

void stage_remove (Stage *s, tagdb_key_t position, AbstractFile *f)
gboolean stage_add (Stage *s, tagdb_key_t position, file_id_t item)
{
trie_remove(s->data, position, TO_SP(get_file_id(f)));
tagdb_key_t lookup_key = key_copy(position);
key_push_end(lookup_key, item);
_node_lookup_create(s->tree, lookup_key);
key_destroy(lookup_key);
return TRUE;
}

gboolean stage_remove (Stage *s, tagdb_key_t position, file_id_t id)
{
tagdb_key_t lookup_key = key_copy(position);
key_push_end(lookup_key, id);
GNode *n = _node_lookup(s->tree, lookup_key);
gboolean res = FALSE;
if (n)
{
g_node_destroy(n);
res = TRUE;
}
key_destroy(lookup_key);
return res;
}

void stage_remove_tag (Stage *s, AbstractFile *t)
void stage_remove_all (Stage *s, file_id_t id)
{
trie_remove_by_bucket_key(s, t);
GNode *n = s->tree;
while (n)
{
n = g_node_find(s->tree, G_IN_ORDER, G_TRAVERSE_ALL, TO_SP(id));
if (n)
{
g_node_destroy(n);
}
}
}

GList *stage_list_position (Stage *s, tagdb_key_t position)
{
return trie_retrieve_bucket_l(s->data, position);
tagdb_key_t lookup_key = key_copy(position);
GNode *n = _node_lookup(s->tree, lookup_key);
GList *res = NULL;
if (n)
{
GNode *it = n->children;
while (it)
{
res = g_list_prepend(res, it->data);
it = it->next;
} LL_END;
}
key_destroy(lookup_key);
return res;
}

void stage_destroy (Stage *s)
{
HL(trie_index(s), it, k, v)
{
g_list_free_full(v, (GDestroyNotify) key_destroy);
} HL_END
g_hash_table_destroy(trie_index(s));
trie_destroy(s->data);
g_node_destroy(s->tree);
g_free(s);
}
12 changes: 6 additions & 6 deletions stage.h
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
#ifndef STAGE_H
#define STAGE_H

#include "trie.h"
#include "tag.h"
#include "key.h"

typedef struct
{
Trie *data;
GNode *tree;
GHashTable *index;
} Stage;

Stage *new_stage ();

/* Adds the given name to the stage at the given
posiiton */
void stage_add (Stage *s, tagdb_key_t position, AbstractFile *item);
gboolean stage_add (Stage *s, tagdb_key_t position, file_id_t item);

/* Removes the given name from the given position */
void stage_remove (Stage *s, tagdb_key_t position, AbstractFile *f);
gboolean stage_remove (Stage *s, tagdb_key_t position, file_id_t f);

GList *stage_list_position (Stage *s, tagdb_key_t position);

AbstractFile* stage_lookup (Stage *s, tagdb_key_t position, file_id_t id);
void stage_remove_tag (Stage *s, AbstractFile *f);
gboolean stage_lookup (Stage *s, tagdb_key_t position, file_id_t id);
void stage_remove_all (Stage *s, file_id_t f);
void stage_destroy (Stage *s);

#endif /* STAGE_H */
19 changes: 11 additions & 8 deletions tagdb_fs.lc
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ int _move_directory(const char *path, const char *newpath)
{
set_tag_name(DB, t, newbase);
tagdb_key_t key = path_extract_key(newdir);
stage_add(STAGE, key, (AbstractFile*)t);
stage_add(STAGE, key, tag_id(t));
key_destroy(key);
}
}
Expand Down Expand Up @@ -542,7 +542,7 @@ int make_a_file_and_return_its_real_path(const char *path, char **result)
}
}
tagdb_key_t key = path_extract_key(dir);
stage_add(STAGE, key, (AbstractFile*)t);
stage_add(STAGE, key, tag_id(t));
key_destroy(key);
tagdb_end_transaction(DB);
}
Expand Down Expand Up @@ -575,9 +575,9 @@ int make_a_file_and_return_its_real_path(const char *path, char **result)
}

file_id_t tag_id = tag_id(t);
stage_remove(STAGE, key, (AbstractFile *)t);
stage_remove_tag(STAGE, (AbstractFile *)t);
assert(stage_lookup(STAGE, key, tag_id) == NULL);
/*stage_remove(STAGE, key, (AbstractFile *)t);*/
stage_remove_all(STAGE, tag_id);
assert(!stage_lookup(STAGE, key, tag_id));
if (t)
{
tagdb_begin_transaction(DB);
Expand Down Expand Up @@ -756,11 +756,14 @@ if (_readdir_list_file(filler, buffer, (const char*)(__name)))\
t = get_tags_list(DB, tags);
}



if (tags)
{
s = stage_list_position(STAGE, tags);
GList *tmp = stage_list_position(STAGE, tags);
LL(tmp, it)
{
s = g_list_prepend(s, retrieve_tag(DB, TO_S(it->data)));
} LL_END
g_list_free(tmp);
}

seen = g_hash_table_new(g_str_hash, g_str_equal);
Expand Down
14 changes: 14 additions & 0 deletions tests/acceptance_test.pl
Original file line number Diff line number Diff line change
Expand Up @@ -1104,6 +1104,20 @@ sub cleanupTestDir
ok(rename($g, $h), "file rename succeeded");
ok((-f $hh), "renamed file exists");
},
move_directories_beneath_each_other =>
sub {
# See issue #34
my $f = "$testDirName/a";
my $g = "$testDirName/b";
my $fg = "$testDirName/a/b";
my $gf = "$testDirName/b/a";
mkdir($f);
mkdir($g);
ok(rename($f, $gf), "Rename $f to $gf succeeds");
ok(rename($g, $fg), "Rename $g to $fg succeeds");
ok((-d $fg), "$fg exists");
ok((-d $gf), "$gf exists");
},
);
my %tests = @tests_list;

Expand Down
Loading

0 comments on commit c0991eb

Please sign in to comment.