1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
|
#include "fuse_node.h"
#include "khash.h"
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdio.h> // for debugging
#define UNKNOWN_INO UINT64_MAX
#define ROOT_NODE_ID 0
#define ROOT_NODE_NAME "/"
typedef struct node_idname_t node_idname_t;
struct node_idname_t
{
uint64_t id;
const char *name;
};
static khint_t idname_hash_func(const node_idname_t idname);
static int idname_hash_equal(const node_idname_t idname0, const node_idname_t idname1);
KHASH_INIT(node,node_idname_t,fuse_node_t*,1,idname_hash_func,idname_hash_equal);
typedef struct fuse_node_hashtable_t fuse_node_hashtable_t;
struct fuse_node_hashtable_t
{
kh_node_t *ht;
uint64_t id;
uint64_t generation;
};
static
inline
khint_t
idname_hash_func(const node_idname_t idname_)
{
if(idname_.name == NULL)
return idname_.id;
return (idname_.id ^ kh_str_hash_func(idname_.name));
}
static
inline
int
idname_hash_equal(const node_idname_t idname0_,
const node_idname_t idname1_)
{
return ((idname0_.id == idname1_.id) &&
((idname0_.name == idname1_.name) ||
(strcmp(idname0_.name,idname1_.name) == 0)));
}
static
inline
fuse_node_t*
fuse_node_alloc(const uint64_t id_,
const char *name_)
{
fuse_node_t *node;
node = (fuse_node_t*)calloc(1,sizeof(fuse_node_t));
node->id = id_;
node->name = strdup(name_);
node->ref_count = 1;
node->lookup_count = 1;
return node;
}
static
inline
void
fuse_node_free(fuse_node_t *node_)
{
free(node_->name);
free(node_);
}
static
inline
uint64_t
rand64()
{
uint64_t rv;
rv = rand();
rv <<= 32;
rv |= rand();
return rv;
}
static
inline
void
node_hashtable_gen_unique_id(fuse_node_hashtable_t *ht_)
{
do
{
ht_->id++;
if(ht_->id == 0)
ht_->generation++;
}
while((ht_->id == 0) || (ht_->id == UNKNOWN_INO));
}
static
inline
void
node_hashtable_put_root(fuse_node_hashtable_t *ht_)
{
int rv;
khint_t k;
fuse_node_t *root_node;
const node_idname_t idname0 = {ROOT_NODE_ID,""};
const node_idname_t idname1 = {ROOT_NODE_ID,ROOT_NODE_NAME};
root_node = fuse_node_alloc(ROOT_NODE_ID,ROOT_NODE_NAME);
k = kh_put_node(ht_->ht,idname0,&rv);
kh_value(ht_->ht,k) = root_node;
k = kh_put_node(ht_->ht,idname1,&rv);
kh_value(ht_->ht,k) = root_node;
}
static
inline
void
node_hashtable_set_id_gen(fuse_node_hashtable_t *ht_,
fuse_node_t *node_)
{
node_hashtable_gen_unique_id(ht_);
node_->id = ht_->id;
node_->generation = ht_->generation;
}
fuse_node_hashtable_t*
fuse_node_hashtable_init()
{
fuse_node_hashtable_t *ht;
ht = (fuse_node_hashtable_t*)calloc(sizeof(fuse_node_hashtable_t),1);
if(ht == NULL)
return NULL;
ht->ht = kh_init_node();
if(ht->ht == NULL)
{
free(ht);
return NULL;
}
srand(time(NULL));
ht->id = 0;
ht->generation = rand64();
node_hashtable_put_root(ht);
return ht;
}
fuse_node_t*
fuse_node_hashtable_put(fuse_node_hashtable_t *ht_,
const uint64_t parent_id_,
const uint64_t child_id_,
const char *child_name_)
{
int rv;
khint_t k;
fuse_node_t *child_node;
const node_idname_t p_idname = {parent_id_,""};
const node_idname_t c0_idname = {child_id_,child_name_};
const node_idname_t c1_idname = {parent_id_,child_name_};
child_node = fuse_node_alloc(child_id_,child_name_);
k = kh_get_node(ht_->ht,p_idname);
child_node->parent = kh_value(ht_->ht,k);
child_node->parent->ref_count++;
k = kh_put_node(ht_->ht,c0_idname,&rv);
kh_value(ht_->ht,k) = child_node;
k = kh_put_node(ht_->ht,c1_idname,&rv);
kh_value(ht_->ht,k) = child_node;
return child_node;
}
fuse_node_t*
fuse_node_hashtable_get(fuse_node_hashtable_t *ht_,
const uint64_t id_)
{
return fuse_node_hashtable_get_child(ht_,id_,"");
}
fuse_node_t*
fuse_node_hashtable_get_child(fuse_node_hashtable_t *ht_,
const uint64_t parent_id_,
const char *child_name_)
{
khint_t k;
fuse_node_t *node;
const node_idname_t idname = {parent_id_,child_name_};
k = kh_get_node(ht_->ht,idname);
node = ((k != kh_end(ht_->ht)) ?
kh_value(ht_->ht,k) :
NULL);
return node;
}
void
fuse_node_hashtable_del(fuse_node_hashtable_t *ht_,
fuse_node_t *node_)
{
}
|