root/branches/Orange-Elaine-Distr-Dir-Branch/src/common/misc/dist-dir-utils.c @ 8660

Revision 8660, 7.4 KB (checked in by shuangy, 2 years ago)

1. sys-getattr only contact active dirdata servers. 2. cleanup mkdir. 3. fix a memory leak in PINT_free_object_attr.

Line 
1/*
2 * (C) 2001 Clemson University and The University of Chicago
3 *
4 * See COPYING in top-level directory.
5 */
6
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10#include <math.h>
11#include <assert.h>
12
13#include "dist-dir-utils.h"
14#include "md5.h"
15
16
17/****************************
18 * helper functions
19 * **************************/
20
21/* calculate log2 of number */
22static double my_log2(const double n)
23{
24        return log(n) / log(2.0);
25}
26
27/* calculate branch_level for a server from a bitmap */
28static int dist_dir_calc_branch_level(
29                const PVFS_dist_dir_attr *dist_dir_attr,
30                const PVFS_dist_dir_bitmap bitmap)
31{
32        int level = 0;
33        int server_no, num_servers;
34
35        server_no = dist_dir_attr->server_no;
36        num_servers = dist_dir_attr->num_servers;
37
38        /* meta handle copy (server_no = -1) shall not reach here */
39        assert(server_no >= 0 && server_no < num_servers);
40        assert(bitmap != NULL);
41
42        if(!(TST_BIT(bitmap, server_no)))
43        {
44                return -1; /* not an active server */
45        }
46
47        /* get the number of bits above which all bits are zero */
48        while( server_no >> level )
49        {
50                level++;
51        }
52
53        /* until no splitting node is set */
54        while( TST_BIT(bitmap, server_no + (1l << level)) )
55        {
56                level++;
57        }
58
59        return level;
60}
61
62/*****************************
63 * main operation functions
64 * ***************************/
65
66/* init dir state function, set all parameters
67 * server_no <- -1..(num_servers-1)
68 * pre_dsg_num_server: pre-set a number of servers, used for known large directory. default value can be 1.
69 */
70
71int PINT_init_dist_dir_state(
72                PVFS_dist_dir_attr *dist_dir_attr,
73                PVFS_dist_dir_bitmap *bitmap_ptr,
74                const int num_servers,
75                const int server_no,
76                int pre_dsg_num_server)
77{
78        int i;
79
80        assert(dist_dir_attr != NULL);
81
82        /* -1 <= server_no < num_servers && 0 < pre_dsg_num_server <= num_servers */
83        assert( (num_servers > 0) &&
84                        (server_no >= -1) && /* metadata handle has server_no = -1 */
85                        (server_no < num_servers));
86
87        if ((pre_dsg_num_server <= 0) ||
88                (pre_dsg_num_server > num_servers))
89        {
90                pre_dsg_num_server = num_servers;       
91        }
92
93        dist_dir_attr->num_servers = num_servers;
94        dist_dir_attr->server_no = server_no;
95        /* tree_height start from 0 */
96        dist_dir_attr->tree_height = (int)ceil(my_log2((double)num_servers));
97
98        /* increase bitmap_size if 2^tree_height > 32
99         * bitmap has at least 2^tree_height bits, that is, the number of leaves of a full tree. */
100        if( (1l << dist_dir_attr->tree_height) >
101                (sizeof(PVFS_dist_dir_bitmap_basetype) * 8))
102        {
103                dist_dir_attr->bitmap_size = ((1l << dist_dir_attr->tree_height) >> 5);
104        }
105        else
106        {
107                dist_dir_attr->bitmap_size = 1;
108        }
109
110        *bitmap_ptr = (PVFS_dist_dir_bitmap) malloc(
111                        dist_dir_attr->bitmap_size * sizeof(PVFS_dist_dir_bitmap_basetype));
112        if ((*bitmap_ptr) == NULL)
113        {
114                return -1;
115        }
116
117        memset((*bitmap_ptr), 0,
118                        dist_dir_attr->bitmap_size * sizeof(PVFS_dist_dir_bitmap_basetype));
119
120        for(i = pre_dsg_num_server-1; i >= 0; i--)
121        {
122                SET_BIT((*bitmap_ptr), i);
123        }
124
125        if(server_no > -1) /* an dirdata server */
126        {
127                dist_dir_attr->branch_level = dist_dir_calc_branch_level(dist_dir_attr, *bitmap_ptr);
128        }
129        else /* a meta server */
130        {
131                dist_dir_attr->branch_level = -1;
132        }
133
134        /* set split size */
135        dist_dir_attr->split_size = PVFS_DIST_DIR_MAX_ENTRIES;
136        return 0;
137}
138
139/* functions to test whether a dirdata server is active or not.
140 * will return 0 if server_no is out of bound or server is inactive.
141 */
142int PINT_is_dist_dir_bucket_active(
143                const PVFS_dist_dir_attr *dist_dir_attr_p,
144                const PVFS_dist_dir_bitmap bitmap,
145                const int server_no)
146{
147    if((server_no < 0) ||
148            (server_no >= dist_dir_attr_p->num_servers))
149    {
150        return 0;
151    }
152
153    if(TST_BIT(bitmap, server_no))
154    {
155        return 1;
156    }
157    else
158    {
159        return 0;
160    }
161
162}
163
164/*
165 * client uses this function to find the server that should hold
166 * a new dir entry, based on the current tree
167 * hash can be any value, whose rightmost several bits will be examined.
168 */
169int PINT_find_dist_dir_bucket(
170                const PVFS_dist_dir_hash_type hash,
171                const PVFS_dist_dir_attr *const dist_dir_attr,
172                const PVFS_dist_dir_bitmap bitmap)
173{
174        PVFS_dist_dir_hash_type node_val;
175        int level;
176
177        assert(dist_dir_attr != NULL);
178        assert(bitmap != NULL);
179
180        level = dist_dir_attr->tree_height;
181
182        if(level < 0)
183        {
184                return -1;
185        }
186
187        for( node_val = hash & ((1l << level) - 1); /* use the rightmost 'tree_height' bits */
188                 (level >= 0) && !(TST_BIT(bitmap, node_val)); /* test if node_val bit is set */
189                 node_val &= ((1l << (--level)) - 1) ); /* if it's not, use less bits of the hash value */
190
191        return (int)node_val; /* assume tree_height < 32 */
192}
193
194
195/*
196 * this code return the index of the new node when a bucket is to be split
197 */
198int PINT_find_dist_dir_split_node(
199                const PVFS_dist_dir_attr *const dist_dir_attr,
200                const PVFS_dist_dir_bitmap bitmap)
201{
202        int new_node_val;
203        int branch_level;
204
205        assert((dist_dir_attr != NULL) &&
206                   (dist_dir_attr->server_no > -1) &&
207                   (bitmap != NULL));
208
209        branch_level = dist_dir_attr->branch_level;
210
211        /* meta server or inactive dirdata server should not come here */
212        assert(branch_level > -1);
213
214        /* if it reaches the maximum tree height */
215        if (branch_level >= dist_dir_attr->tree_height)
216        {
217                return -1;
218        }
219
220        /* calculate new node value */
221        new_node_val = dist_dir_attr->server_no
222                                + (1l << branch_level);
223        if(new_node_val >= dist_dir_attr->num_servers)
224        {
225                return -1;
226        }
227
228        /* new node must be unset, otherwise branch_level is messed up */
229        assert(!TST_BIT(bitmap, new_node_val));
230
231        return new_node_val;
232}
233
234/*
235 * update current bitmap tree and re-calculate branch_level
236 */
237int PINT_update_dist_dir_bitmap_from_bitmap(
238                PVFS_dist_dir_attr *to_dir_attr,
239                PVFS_dist_dir_bitmap to_dir_bitmap,
240                const PVFS_dist_dir_attr *from_dir_attr,
241                const PVFS_dist_dir_bitmap from_dir_bitmap)
242{
243        int i;
244
245        assert((to_dir_attr != NULL) && (from_dir_attr != NULL));
246        assert((to_dir_bitmap != NULL) && (from_dir_bitmap != NULL));
247
248        if( (to_dir_attr->num_servers != from_dir_attr->num_servers) ||
249                (to_dir_attr->server_no == from_dir_attr->server_no))
250        {
251                return -1; /* not in the same tree or update itself */
252        }
253
254        /* bitmap is with a type of (uint32_t *)
255         */
256        for(i = to_dir_attr->bitmap_size - 1;
257                i >= 0; i--)
258        {
259                to_dir_bitmap[i] |= from_dir_bitmap[i];
260        }
261
262        /* update branch level */
263        if(to_dir_attr->server_no > -1) /* dirdata server */
264        {
265        to_dir_attr->branch_level = dist_dir_calc_branch_level(to_dir_attr, to_dir_bitmap);
266        }
267
268        /* anything else to update? */
269
270        return 0;
271}
272
273
274/** a md5 encrypt function
275 * MD5 encryption returns a 128bit value, the hash value takes the last 64bit
276 * and save as an uint64_t
277 *
278 * ?? later, may add an option to be able to use other hash algorithm?
279 */
280PVFS_dist_dir_hash_type PINT_encrypt_dirdata(const char *const name)
281{
282        PVFS_dist_dir_hash_type *hash_val;
283        md5_state_t state;
284        md5_byte_t digest[16];
285
286        md5_init(&state);
287        md5_append(&state, (const md5_byte_t *)name, strlen(name));
288        md5_finish(&state, digest);
289
290        hash_val = (PVFS_dist_dir_hash_type *)(digest + 8);
291        return *hash_val;
292}
293
294
295
296/* set server_no field and update branch_level if necessary */
297int PINT_dist_dir_set_serverno(const int server_no,
298        PVFS_dist_dir_attr *ddattr,
299        PVFS_dist_dir_bitmap ddbitmap)
300{
301        assert(ddattr != NULL &&
302                        ddbitmap != NULL &&
303                        server_no >= -1 &&
304                        server_no < ddattr->num_servers);
305
306        ddattr->server_no = server_no;
307       
308        ddattr->branch_level = dist_dir_calc_branch_level(ddattr, ddbitmap);
309
310        return 0;
311}
312
313/*
314 * Local variables:
315 *  c-indent-level: 4
316 *  c-basic-offset: 4
317 * End:
318 *
319 * vim: ts=8 sts=4 sw=4 expandtab
320 */
Note: See TracBrowser for help on using the browser.