root/branches/orange-next/src/io/trove/trove-dbpf/dbpf-keyval-pcache.c @ 8994

Revision 8994, 7.6 KB (checked in by dcypher, 23 months ago)

replaced %llu->%s for (PVFS|TROVE)_handle

Line 
1/*
2 * (C) 2002 Clemson University and The University of Chicago
3 *
4 * See COPYING in top-level directory.
5 */
6
7#include <stdlib.h>
8#include <string.h>
9#ifdef HAVE_MALLOC_H
10#include <malloc.h>
11#endif
12
13#include "dbpf-keyval-pcache.h"
14#include "quickhash.h"
15#include "gossip.h"
16#include "pvfs2-internal.h"
17
18/* table size must be a multiple of 2 */
19#define DBPF_KEYVAL_PCACHE_TABLE_SIZE (1<<10)
20#define DBPF_KEYVAL_PCACHE_HARD_LIMIT 51200
21
22struct dbpf_keyval_pcache_key
23{
24    TROVE_handle handle;
25    TROVE_kv_position pos;
26};
27
28struct dbpf_keyval_pcache_entry
29{
30    TROVE_handle handle;
31    TROVE_kv_position pos;
32    char keyname[PVFS_NAME_MAX];
33    int keylen;
34};
35
36static int dbpf_keyval_pcache_compare(
37    void * key, struct qhash_head * link);
38static int dbpf_keyval_pcache_hash(
39    void * key, int size);
40static int dbpf_keyval_pcache_entry_free(
41    void * entry);
42
43PINT_dbpf_keyval_pcache * PINT_dbpf_keyval_pcache_initialize(void)
44{
45    PINT_dbpf_keyval_pcache * cache;
46
47    cache = malloc(sizeof(PINT_dbpf_keyval_pcache));
48    if(!cache)
49    {
50        return NULL;
51    }
52
53    gen_mutex_init(&cache->mutex);
54
55    cache->tcache = PINT_tcache_initialize(
56        dbpf_keyval_pcache_compare,
57        dbpf_keyval_pcache_hash,
58        dbpf_keyval_pcache_entry_free,
59        DBPF_KEYVAL_PCACHE_TABLE_SIZE);
60    if(!cache->tcache)
61    {
62        return NULL;
63    }
64
65    PINT_tcache_set_info(cache->tcache,
66                         TCACHE_ENABLE_EXPIRATION,
67                         0);
68    PINT_tcache_set_info(cache->tcache,
69                         TCACHE_HARD_LIMIT,
70                         DBPF_KEYVAL_PCACHE_HARD_LIMIT);
71
72
73    return cache;
74}
75   
76void PINT_dbpf_keyval_pcache_finalize(
77    PINT_dbpf_keyval_pcache * cache)
78{
79    PINT_tcache_finalize(cache->tcache);
80    gen_mutex_destroy(&cache->mutex);
81    free(cache);
82}
83
84static int dbpf_keyval_pcache_compare(
85    void * key, struct qhash_head * link)
86{
87    struct dbpf_keyval_pcache_key * key_entry =
88        (struct dbpf_keyval_pcache_key *)key;
89    struct dbpf_keyval_pcache_entry * link_entry =
90        (struct dbpf_keyval_pcache_entry *)
91        (qhash_entry(link, struct PINT_tcache_entry, hash_link))->payload;
92
93    if(!(TROVE_handle_compare(key_entry->handle, link_entry->handle)) &&
94       key_entry->pos.session == link_entry->pos.session &&
95       key_entry->pos.count == link_entry->pos.count)
96        return 1;
97    return 0;
98}
99   
100/* hash from http://burtleburtle.net/bob/hash/evahash.html
101#define mix(a,b,c) \
102do { \
103  a=a-b;  a=a-c;  a=a^(c>>13); \
104      b=b-c;  b=b-a;  b=b^(a<<8);  \
105      c=c-a;  c=c-b;  c=c^(b>>13); \
106      a=a-b;  a=a-c;  a=a^(c>>12); \
107      b=b-c;  b=b-a;  b=b^(a<<16); \
108      c=c-a;  c=c-b;  c=c^(b>>5);  \
109      a=a-b;  a=a-c;  a=a^(c>>3);  \
110      b=b-c;  b=b-a;  b=b^(a<<10); \
111      c=c-a;  c=c-b;  c=c^(b>>15); \
112} while(0) */
113
114/* 64 bit version */
115 #define mix64(a,b,c) \
116 { \
117    a=a-b;  a=a-c;  a=a^(c>>43); \
118    b=b-c;  b=b-a;  b=b^(a<<9);  \
119    c=c-a;  c=c-b;  c=c^(b>>8);  \
120    a=a-b;  a=a-c;  a=a^(c>>38); \
121    b=b-c;  b=b-a;  b=b^(a<<23); \
122    c=c-a;  c=c-b;  c=c^(b>>5);  \
123    a=a-b;  a=a-c;  a=a^(c>>35); \
124    b=b-c;  b=b-a;  b=b^(a<<49); \
125    c=c-a;  c=c-b;  c=c^(b>>11); \
126    a=a-b;  a=a-c;  a=a^(c>>12); \
127    b=b-c;  b=b-a;  b=b^(a<<18); \
128    c=c-a;  c=c-b;  c=c^(b>>22); \
129 }
130
131
132static int dbpf_keyval_pcache_hash(
133    void * key, int size)
134{
135    struct dbpf_keyval_pcache_entry * key_entry =
136        (struct dbpf_keyval_pcache_entry *)key;
137    uint64_t a = 0, b = 0, c = 0;
138
139    /* FIX: needs refactored for both handle and pos.session/pos.count */
140    TROVE_handle_to_hash(key_entry->handle, &a);
141    b = key_entry->pos.session;
142    c = key_entry->pos.count;
143
144    mix64(a,b,c);
145    return (int)(c & (DBPF_KEYVAL_PCACHE_TABLE_SIZE-1));
146}
147
148static int dbpf_keyval_pcache_entry_free(
149    void * entry)
150{
151    free(entry);
152    return 0;
153}
154
155int PINT_dbpf_keyval_pcache_lookup(
156    PINT_dbpf_keyval_pcache *pcache,
157    TROVE_handle handle,
158    TROVE_kv_position pos,
159    const void ** keyname,
160    int * length)
161{
162    struct PINT_tcache_entry *entry;
163    struct dbpf_keyval_pcache_key key;
164    int ret, status;
165
166    TROVE_handle_copy(key.handle, handle);
167
168    /* this used to be a 64 bit number where the top 32 bits were a
169     * session id and the bottom 32 were a count. that's replaced with
170     * struct that is the same, should provide the same data to tcache */
171    memcpy(&key.pos, &pos, sizeof(TROVE_kv_position) );
172   
173    gen_mutex_lock(&pcache->mutex);
174    ret = PINT_tcache_lookup(pcache->tcache, (void *)&key, &entry, &status);
175    if(ret != 0)
176    {
177        if(ret == -PVFS_ENOENT)
178        {
179            gossip_debug(GOSSIP_DBPF_KEYVAL_DEBUG,
180                         "Trove KeyVal pcache NOTFOUND: "
181                         "handle: %s, pos: session(%lluu), count(%lluu)\n",
182                         PVFS_handle_to_str(handle), llu(pos.session), llu(pos.count));
183        }
184        else
185        {
186            gossip_debug(GOSSIP_DBPF_KEYVAL_DEBUG,
187                         "Trove KeyVal pcache failed: (error %d): "
188                         "handle: %s, pos: session(%llu), count(%llu)\n",
189                         ret, PVFS_handle_to_str(handle), llu(pos.session), llu(pos.count));
190        }
191
192        gen_mutex_unlock(&pcache->mutex);
193        return ret;
194    }
195    gen_mutex_unlock(&pcache->mutex);
196
197    *keyname = ((struct dbpf_keyval_pcache_entry *)entry->payload)->keyname;
198    *length = ((struct dbpf_keyval_pcache_entry *)entry->payload)->keylen;
199
200    gossip_debug(GOSSIP_DBPF_KEYVAL_DEBUG,
201                 "Trove KeyVal pcache lookup succeeded: "
202                 "handle: %s, pos: session(%llu), count(%llu)\n",
203                 PVFS_handle_to_str(handle), llu(pos.session), llu(pos.count));
204
205    return 0;
206}
207
208int PINT_dbpf_keyval_pcache_insert(
209    PINT_dbpf_keyval_pcache *pcache,
210    TROVE_handle handle,
211    TROVE_kv_position pos,
212    const char * keyname,
213    int length)
214{
215    struct dbpf_keyval_pcache_entry *entry;
216    struct dbpf_keyval_pcache_key key;
217    struct PINT_tcache_entry * tentry;
218    int lookup_status;
219    int ret;
220    int removed;
221   
222    entry = malloc(sizeof(struct dbpf_keyval_pcache_entry));
223    if(!entry)
224    {
225        return -PVFS_ENOMEM;
226    }
227
228    TROVE_handle_copy(key.handle, handle);
229    memcpy(&key.pos, &pos, sizeof(PVFS_kv_position));
230
231    gen_mutex_lock(&pcache->mutex);
232    if(PINT_tcache_lookup(
233            pcache->tcache, (void *)&key, &tentry, &lookup_status) == 0)
234    {
235        /* remove entry that already exists */
236        PINT_tcache_delete(pcache->tcache, tentry);
237    }
238
239    TROVE_handle_copy(entry->handle,  handle);
240    memcpy(&entry->pos, &pos, sizeof(PVFS_kv_position));
241    memcpy(entry->keyname, keyname, length);
242    entry->keylen = length;
243
244    ret = PINT_tcache_insert_entry(pcache->tcache,
245                                   &key,
246                                   entry,
247                                   &removed);
248    if(ret != 0)
249    {
250        gossip_debug(GOSSIP_DBPF_KEYVAL_DEBUG,
251                     "Trove KeyVal pcache insert failed: (error: %d) "
252                     "handle: %s, pos: session(%llu), count(%llu)\n",
253                     ret, PVFS_handle_to_str(handle), llu(pos.session), llu(pos.count));
254
255        gen_mutex_unlock(&pcache->mutex);
256        free(entry);
257        return ret;
258    }
259    gen_mutex_unlock(&pcache->mutex);
260
261    gossip_debug(GOSSIP_DBPF_KEYVAL_DEBUG,
262                 "Trove KeyVal pcache insert succeeded: "
263                 "handle: %s, pos: session(%llu), count(%llu)\n",
264                 PVFS_handle_to_str(handle), llu(pos.session), llu(pos.count));
265
266    return 0;
267}
268   
269/*
270 * Local variables:
271 *  c-indent-level: 4
272 *  c-basic-offset: 4
273 * End:
274 *
275 * vim: ts=8 sts=4 sw=4 expandtab
276 */
Note: See TracBrowser for help on using the browser.