root/branches/Orange-Elaine-Distr-Dir-Branch/src/common/misc/mkspace.c @ 8768

Revision 8768, 32.9 KB (checked in by shuangy, 2 years ago)

store distdir struct in dirdata handle keyval space.

Line 
1/*
2 * (C) 2002 Clemson University and The University of Chicago
3 *
4 * See COPYING in top-level directory.
5 */
6
7#include <unistd.h>
8#include <string.h>
9#include <stdio.h>
10#include <limits.h>
11#include <string.h>
12#include <stdlib.h>
13#include <time.h>
14#include <assert.h>
15
16#include "pvfs2-attr.h"
17#include "trove.h"
18#include "mkspace.h"
19#include "pvfs2-debug.h"
20#include "gossip.h"
21#include "server-config.h"
22#include "str-utils.h"
23#include "extent-utils.h"
24#include "pvfs2-util.h"
25#include "pvfs2-internal.h"
26#include "pint-util.h"
27#include "pint-event.h"
28#include "dist-dir-utils.h"
29
30static char *lost_and_found_string = "lost+found";
31
32static TROVE_handle s_used_handles[4] =
33{
34    TROVE_HANDLE_NULL, TROVE_HANDLE_NULL,
35    TROVE_HANDLE_NULL, TROVE_HANDLE_NULL
36};
37
38#define mkspace_print(v, format, f...)              \
39do {                                                \
40 if (v == PVFS2_MKSPACE_GOSSIP_VERBOSE)             \
41   gossip_debug(GOSSIP_SERVER_DEBUG, format, ##f);  \
42 else if (v == PVFS2_MKSPACE_STDERR_VERBOSE)        \
43   fprintf(stderr,format, ##f);                     \
44} while(0)
45
46static int handle_is_excluded(
47    TROVE_handle handle, TROVE_handle *handles_to_exclude,
48    int num_handles_to_exclude)
49{
50    int excluded = 0;
51
52    while((num_handles_to_exclude - 1) > -1)
53    {
54        if (handle == handles_to_exclude[num_handles_to_exclude-1])
55        {
56            excluded = 1;
57            break;
58        }
59        num_handles_to_exclude--;
60    }
61    return excluded;
62}
63
64static void get_handle_extent_from_ranges(
65    char *handle_ranges, TROVE_handle_extent *out_extent,
66    TROVE_handle *handles_to_exclude, int num_handles_to_exclude)
67{
68    PINT_llist *cur = NULL;
69    TROVE_handle_extent *tmp_extent = NULL;
70    PINT_llist *extent_list = NULL;
71
72    if (handle_ranges && out_extent)
73    {
74        out_extent->first = TROVE_HANDLE_NULL;
75        out_extent->last = TROVE_HANDLE_NULL;
76
77        extent_list = PINT_create_extent_list(handle_ranges);
78        if (extent_list)
79        {
80            cur = extent_list;
81            while(cur)
82            {
83                tmp_extent = PINT_llist_head(cur);
84                if (!tmp_extent)
85                {
86                    break;
87                }
88
89                /*
90                  allow any handle range in this list that can allow
91                  at least the single handle allocation to pass.  a
92                  range of 1 is ok, so long as it's not a handle that
93                  was previously allocated (i.e. in the specified
94                  excluded list)
95                */
96                if (((tmp_extent->last - tmp_extent->first) > 0) ||
97                    ((tmp_extent->last > 0) &&
98                     (tmp_extent->last == tmp_extent->first) &&
99                     !handle_is_excluded(
100                         tmp_extent->last, handles_to_exclude,
101                         num_handles_to_exclude)))
102                {
103                    out_extent->first = tmp_extent->first;
104                    out_extent->last = tmp_extent->last;
105                    break;
106                }
107                cur = PINT_llist_next(cur);
108            }
109            PINT_release_extent_list(extent_list);
110        }
111    }
112}
113
114int pvfs2_mkspace(
115    char *data_path,
116    char *meta_path,
117    char *collection,
118    TROVE_coll_id coll_id,
119    TROVE_handle root_handle,
120    char *meta_handle_ranges,
121    char *data_handle_ranges,
122    int create_collection_only,
123    int verbose)
124{
125    int ret = - 1, count = 0, keyval_count, i;
126    TROVE_op_id op_id;
127    TROVE_ds_state state;
128    TROVE_keyval_s key, val;
129    TROVE_keyval_s *key_a = NULL, *val_a = NULL;
130    TROVE_ds_attributes_s attr;
131    TROVE_handle_extent cur_extent;
132    TROVE_handle_extent_array extent_array;
133    TROVE_context_id trove_context = -1;
134    char *merged_handle_ranges = NULL;
135    unsigned char *c = NULL;
136    TROVE_handle new_root_handle = TROVE_HANDLE_NULL;
137    TROVE_handle root_dirdata_handle = TROVE_HANDLE_NULL;
138    TROVE_handle lost_and_found_handle = TROVE_HANDLE_NULL;
139    TROVE_handle lost_and_found_dirdata_handle = TROVE_HANDLE_NULL;
140
141    /* distributed directory parameters */
142    PVFS_dist_dir_attr meta_dist_dir_attr;
143    PVFS_dist_dir_attr dirdata_dist_dir_attr;
144    PVFS_dist_dir_bitmap dist_dir_bitmap = NULL;
145    /* only one dirdata_handle for root and lost_and_found, not using arrays
146    PVFS_handle *dirdata_handles;
147    */
148
149    mkspace_print(verbose,"Data storage space     : %s\n",data_path);
150    mkspace_print(verbose,"Metadata storage space : %s\n", meta_path);
151    mkspace_print(verbose,"Collection   : %s\n",collection);
152    mkspace_print(verbose,"ID           : %d\n",coll_id);
153    mkspace_print(verbose,"Root Handle  : %llu\n",llu(root_handle));
154    mkspace_print(verbose,"Meta Handles : %s\n",
155                  (meta_handle_ranges && strlen(meta_handle_ranges) ?
156                   meta_handle_ranges : "NONE"));
157    mkspace_print(verbose,"Data Handles : %s\n",
158                  (data_handle_ranges && strlen(data_handle_ranges) ?
159                   data_handle_ranges : "NONE"));
160
161    new_root_handle = root_handle;
162
163    /*
164      if we're only creating a collection inside an existing
165      storage space, we need to assume that it exists already
166    */
167    if (!create_collection_only)
168    {
169        /*
170          try to initialize; fails if storage space isn't there, which
171          is exactly what we're expecting in this case.
172        */
173        ret = trove_initialize(TROVE_METHOD_DBPF,
174                               NULL,
175                               data_path,
176                               meta_path,
177                               0);
178        if (ret > -1)
179        {
180            gossip_err("error: storage space %s or %s already "
181                       "exists; aborting!\n",data_path,meta_path);
182            return -1;
183        }
184
185        ret = trove_storage_create(TROVE_METHOD_DBPF, data_path, meta_path, NULL, &op_id);
186        if (ret != 1)
187        {
188            gossip_err("error: storage create failed; aborting!\n");
189            return -1;
190        }
191    }
192
193    /* now that the storage space exists, initialize trove properly */
194    ret = trove_initialize(
195        TROVE_METHOD_DBPF, NULL,
196        data_path, meta_path, 0);
197    if (ret < 0)
198    {
199        gossip_err("error: trove initialize failed; aborting!\n");
200        return -1;
201    }
202
203    mkspace_print(verbose,"info: created data storage space '%s'.\n",
204                  data_path);
205    mkspace_print(verbose,"info: created metadata storage space '%s'.\n",
206                  meta_path);
207
208    /* try to look up collection used to store file system */
209    ret = trove_collection_lookup(
210        TROVE_METHOD_DBPF, collection, &coll_id, NULL, &op_id);
211    if (ret == 1)
212    {
213        mkspace_print(verbose, "warning: collection lookup succeeded "
214                      "before it should; aborting!\n");
215        trove_finalize(TROVE_METHOD_DBPF);
216        return -1;
217    }
218
219    /* create the collection for the fs */
220    ret = trove_collection_create(collection, coll_id, NULL, &op_id);
221    if (ret != 1)
222    {
223        mkspace_print(verbose,"error: collection create failed for "
224                      "collection '%s'.\n",collection);
225        return -1;
226    }
227
228    /* make sure a collection lookup succeeds */
229    ret = trove_collection_lookup(
230        TROVE_METHOD_DBPF, collection, &coll_id, NULL, &op_id);
231    if (ret != 1)
232    {
233        mkspace_print(verbose,"error: collection lookup failed for "
234                      "collection '%s' after create.\n",collection);
235        return -1;
236    }
237
238    mkspace_print(verbose, "info: created collection '%s'.\n",collection);
239
240    ret = trove_open_context(coll_id, &trove_context);
241    if (ret < 0)
242    {
243        mkspace_print(verbose,"trove_open_context() failure.\n");
244        return -1;
245    }
246
247    /* merge the specified ranges to pass to the handle allocator */
248    if ((meta_handle_ranges && strlen(meta_handle_ranges)) &&
249        (data_handle_ranges && strlen(data_handle_ranges)))
250    {
251        merged_handle_ranges = PINT_merge_handle_range_strs(
252            meta_handle_ranges, data_handle_ranges);
253    }
254    else if (meta_handle_ranges && strlen(meta_handle_ranges))
255    {
256        merged_handle_ranges = strdup(meta_handle_ranges);
257    }
258    else if (data_handle_ranges && strlen(data_handle_ranges))
259    {
260        merged_handle_ranges = strdup(data_handle_ranges);
261    }
262
263    if (!merged_handle_ranges)
264    {
265        gossip_err("Failed to merge the handle range!  Format invalid\n");
266        return -1;
267    }
268
269    /*
270      set the trove handle ranges; this initializes the handle
271      allocator with the ranges we were told to use
272    */
273    ret = trove_collection_setinfo(
274        coll_id, trove_context, TROVE_COLLECTION_HANDLE_RANGES,
275        merged_handle_ranges);
276
277    if (ret < 0)
278    {
279        mkspace_print(verbose, "Error adding handle ranges: %s\n",
280                      merged_handle_ranges);
281        free(merged_handle_ranges);
282        return -1;
283    }
284
285    mkspace_print(verbose,"info: set handle ranges to %s\n",
286                  merged_handle_ranges);
287
288    free(merged_handle_ranges);
289 
290
291    /*
292      if a root_handle is specified, 1) create a dataspace to hold the
293      root directory 2) create the dspace for dir entries, 3) set
294      attributes on the dspace
295    */
296    if (new_root_handle != TROVE_HANDLE_NULL)
297    {
298        cur_extent.first = cur_extent.last = new_root_handle;
299        extent_array.extent_count = 1;
300        extent_array.extent_array = &cur_extent;
301
302        ret = trove_dspace_create(
303            coll_id, &extent_array, &new_root_handle,
304            PVFS_TYPE_DIRECTORY, NULL,
305            (TROVE_SYNC | TROVE_FORCE_REQUESTED_HANDLE),
306            NULL, trove_context, &op_id, NULL);
307
308        while (ret == 0)
309        {
310            ret = trove_dspace_test(coll_id, op_id, trove_context,
311                                    &count, NULL, NULL, &state,
312                                    TROVE_DEFAULT_TEST_TIMEOUT);
313        }
314
315        if ((ret != 1) && (state != 0))
316        {
317            mkspace_print(verbose,
318                          "dspace create (for root dir) failed.\n");
319            return -1;
320        }
321
322        mkspace_print(verbose,"info: created root directory "
323                      "with handle %llu.\n", llu(new_root_handle));
324        s_used_handles[0] = new_root_handle;
325
326        /* set collection attribute for root handle */
327        key.buffer = ROOT_HANDLE_KEYSTR;
328        key.buffer_sz = ROOT_HANDLE_KEYLEN;
329        val.buffer = &new_root_handle;
330        val.buffer_sz = sizeof(new_root_handle);
331        ret = trove_collection_seteattr(coll_id, &key, &val, 0,
332                                        NULL, trove_context, &op_id);
333        while (ret == 0)
334        {
335            ret = trove_dspace_test(
336                coll_id, op_id, trove_context, &count, NULL, NULL,
337                &state, TROVE_DEFAULT_TEST_TIMEOUT);
338        }
339
340        if (ret < 0)
341        {
342            gossip_err("error: collection seteattr (for root handle) "
343                       "failed; aborting!\n");
344            return -1;
345        }
346
347        /* set root directory dspace attributes */
348        memset(&attr, 0, sizeof(TROVE_ds_attributes_s));
349        attr.uid = getuid();
350        attr.gid = getgid();
351        attr.mode = 0777;
352        attr.type = PVFS_TYPE_DIRECTORY;
353        attr.atime = attr.ctime = PINT_util_get_current_time();
354        attr.mtime = PINT_util_mktime_version(attr.ctime);
355
356        ret = trove_dspace_setattr(
357            coll_id, new_root_handle, &attr, TROVE_SYNC, NULL,
358            trove_context, &op_id, NULL);
359
360        while (ret == 0)
361        {
362            ret = trove_dspace_test(
363                coll_id, op_id, trove_context, &count, NULL, NULL,
364                &state, TROVE_DEFAULT_TEST_TIMEOUT);
365        }
366
367        if (ret < 0)
368        {
369            gossip_err("error: dspace setattr for root handle "
370                       "attributes failed; aborting!\n");
371            return -1;
372        }
373
374        /*
375          create a dataspace to hold directory entries; if we have a
376          meta handle range, use that one of those ranges (being
377          careful to make sure the range has enough space for an
378          allocation) to allocate a dataspace to hold directory
379          entries.  if we don't have a meta handle range, use
380          TROVE_HANDLE_NULL which tells the allocator to use any
381          handle available
382        */
383        cur_extent.first = cur_extent.last = TROVE_HANDLE_NULL;
384        if (meta_handle_ranges)
385        {
386            get_handle_extent_from_ranges(
387                meta_handle_ranges, &cur_extent, s_used_handles, 1);
388
389            if ((cur_extent.first == TROVE_HANDLE_NULL) &&
390                (cur_extent.last == TROVE_HANDLE_NULL))
391            {
392                gossip_err("No valid meta handle ranges available! "
393                           "Using a default\n");
394            }
395            else
396            {
397                mkspace_print(
398                    verbose, "info: using meta handle range %llu-%llu for "
399                    "root dirent dspace\n", llu(cur_extent.first),
400                    llu(cur_extent.last));
401            }
402        }
403
404        extent_array.extent_count = 1;
405        extent_array.extent_array = &cur_extent;
406
407        ret = trove_dspace_create(
408            coll_id, &extent_array, &root_dirdata_handle,
409            PVFS_TYPE_DIRDATA, NULL, TROVE_SYNC, NULL,
410            trove_context, &op_id, NULL);
411
412        while (ret == 0)
413        {
414            ret = trove_dspace_test(
415                coll_id, op_id, trove_context, &count, NULL, NULL,
416                &state, TROVE_DEFAULT_TEST_TIMEOUT);
417        }
418
419        if ((ret != 1) && (state != 0))
420        {
421            gossip_err("dspace create (for dirent storage) failed.\n");
422            return -1;
423        }
424
425        mkspace_print(verbose, "info: created dspace for dirents "
426                      "with handle %llu\n", llu(root_dirdata_handle));
427        s_used_handles[1] = root_dirdata_handle;
428
429        /* set root dirdata dspace attributes */
430        memset(&attr, 0, sizeof(TROVE_ds_attributes_s));
431        attr.uid = getuid();
432        attr.gid = getgid();
433        attr.mode = 0777;
434        attr.type = PVFS_TYPE_DIRDATA;
435        attr.atime = attr.ctime = PINT_util_get_current_time();
436        attr.mtime = PINT_util_mktime_version(attr.ctime);
437
438        ret = trove_dspace_setattr(
439            coll_id, root_dirdata_handle, &attr, TROVE_SYNC, NULL,
440            trove_context, &op_id, NULL);
441
442        while (ret == 0)
443        {
444            ret = trove_dspace_test(
445                coll_id, op_id, trove_context, &count, NULL, NULL,
446                &state, TROVE_DEFAULT_TEST_TIMEOUT);
447        }
448
449        if (ret < 0)
450        {
451            gossip_err("error: dspace setattr for root dirdata handle "
452                       "attributes failed; aborting!\n");
453            return -1;
454        }
455
456
457        key.buffer = DIRECTORY_ENTRY_KEYSTR;
458        key.buffer_sz = DIRECTORY_ENTRY_KEYLEN;
459        val.buffer = &root_dirdata_handle;
460        val.buffer_sz = sizeof(TROVE_handle);
461           
462        ret = trove_keyval_write(
463            coll_id, new_root_handle, &key, &val,
464            TROVE_SYNC, 0, NULL,
465            trove_context, &op_id, NULL);
466           
467        while (ret == 0)
468        {           
469            ret = trove_dspace_test(
470                coll_id, op_id, trove_context, &count, NULL, NULL,
471                &state, TROVE_DEFAULT_TEST_TIMEOUT);
472        }
473       
474        if (ret < 0)
475        {
476            gossip_err("error: keyval write for handle used to store "
477                       "dirents failed; aborting!\n");
478            return -1;
479        }   
480
481        mkspace_print(
482            verbose, "info: wrote attributes for root directory.\n");
483           
484
485        /* !!! set dist-dir-struct keyvals for root handle and its dirdata handle */
486        /* init meta handle dist_dir_struct, num_servers=1, server_no = -1, pre_dsg_num_server=1 */
487        /* should be reusable when init lost+found */
488        ret = PINT_init_dist_dir_state(&meta_dist_dir_attr,
489                &dist_dir_bitmap, 1, 0, 1);
490        assert(ret == 0);
491
492        /* gossip dist_dir_attr and dist_dir_bitmap */
493        mkspace_print(verbose, "info: init dist_dir_attr for root handle %llu: \n"
494                "with tree_height=%d, num_servers=%d, bitmap_size=%d, "
495                "split_size=%d, server_no=%d and branch_level=%d\n",
496                llu(new_root_handle),
497                meta_dist_dir_attr.tree_height,
498                meta_dist_dir_attr.num_servers,
499                meta_dist_dir_attr.bitmap_size,
500                meta_dist_dir_attr.split_size,
501                meta_dist_dir_attr.server_no,
502                meta_dist_dir_attr.branch_level);
503        mkspace_print(verbose, "info: init dist_dir_bitmap as:\n");
504        for(i = meta_dist_dir_attr.bitmap_size - 1;
505                i >= 0 ; i--)
506        {
507            c = (unsigned char *)(dist_dir_bitmap + i);
508            mkspace_print(verbose,
509                    " i=%d : %02x %02x %02x %02x\n",
510                    i, c[3], c[2], c[1], c[0]);
511        }
512        mkspace_print(verbose, "\n");
513
514        /* init dirdata_dist_dir_attr */
515        PINT_dist_dir_attr_copyto(dirdata_dist_dir_attr, meta_dist_dir_attr);
516        PINT_dist_dir_set_serverno(0, &dirdata_dist_dir_attr, dist_dir_bitmap);
517
518        mkspace_print(verbose, "info: init dist_dir_attr for root dirdata handle %llu: \n"
519                "with tree_height=%d, num_servers=%d, bitmap_size=%d, "
520                "split_size=%d, server_no=%d and branch_level=%d\n",
521                llu(root_dirdata_handle),
522                dirdata_dist_dir_attr.tree_height,
523                dirdata_dist_dir_attr.num_servers,
524                dirdata_dist_dir_attr.bitmap_size,
525                dirdata_dist_dir_attr.split_size,
526                dirdata_dist_dir_attr.server_no,
527                dirdata_dist_dir_attr.branch_level);
528
529        keyval_count = 3;
530
531        key_a = malloc(sizeof(TROVE_keyval_s) * keyval_count);
532        if(!key_a)
533        {
534            gossip_err("keyval space create (for root and lost+found storage) failed.\n");
535            return -1;
536        }
537        memset(key_a, 0, sizeof(TROVE_keyval_s) * keyval_count);
538
539        val_a = malloc(sizeof(TROVE_keyval_s) * keyval_count);
540        if(!val_a)
541        {
542            free(key_a);
543            gossip_err("keyval space create (for root and lost+found storage) failed.\n");
544            return -1;
545        }
546        memset(val_a, 0, sizeof(TROVE_keyval_s) * keyval_count);
547
548        /* set keyval for root meta handle */
549        key_a[0].buffer = DIST_DIR_ATTR_KEYSTR;
550        key_a[0].buffer_sz = DIST_DIR_ATTR_KEYLEN;
551
552        val_a[0].buffer = &meta_dist_dir_attr;
553        val_a[0].buffer_sz =
554            sizeof(meta_dist_dir_attr);
555
556        key_a[1].buffer = DIST_DIRDATA_BITMAP_KEYSTR;
557        key_a[1].buffer_sz = DIST_DIRDATA_BITMAP_KEYLEN;
558
559        val_a[1].buffer_sz =
560            meta_dist_dir_attr.bitmap_size *  /* bitmap_size = 1 */
561            sizeof(PVFS_dist_dir_bitmap_basetype);
562        val_a[1].buffer = dist_dir_bitmap;
563
564        key_a[2].buffer = DIST_DIRDATA_HANDLES_KEYSTR;
565        key_a[2].buffer_sz = DIST_DIRDATA_HANDLES_KEYLEN;
566
567        val_a[2].buffer = &root_dirdata_handle; /* only one dirdata server */
568        val_a[2].buffer_sz = meta_dist_dir_attr.num_servers *
569            sizeof(root_dirdata_handle);
570
571        mkspace_print(verbose,
572                " info: writing dist-dir-struct keyvals for root handle: %llu "
573                " with server_no=%d and branch_level=%d \n",
574                llu(new_root_handle),
575                meta_dist_dir_attr.server_no,
576                meta_dist_dir_attr.branch_level);
577
578        /* write to root meta handle keyval space */
579        ret = trove_keyval_write_list(
580            coll_id, new_root_handle, key_a, val_a, keyval_count,
581            TROVE_SYNC, 0, NULL,
582            trove_context, &op_id, NULL);
583
584        while (ret == 0)
585        {
586            ret = trove_dspace_test(
587                coll_id, op_id, trove_context, &count, NULL, NULL,
588                &state, TROVE_DEFAULT_TEST_TIMEOUT);
589        }
590
591        if (ret < 0)
592        {
593            gossip_err("error: keyval write for handle used to store "
594                       "dirents failed; aborting!\n");
595            return -1;
596        }
597
598        /* adjust dist_dir_attr val_a */
599        val_a[0].buffer = &dirdata_dist_dir_attr;
600       
601        mkspace_print(verbose,
602                " info: writing dist-dir-struct keyvals for root dirdata handle: %llu "
603                " with server_no=%d and branch_level=%d \n",
604                llu(root_dirdata_handle),
605                dirdata_dist_dir_attr.server_no,
606                dirdata_dist_dir_attr.branch_level);
607
608        /* write to root dirdata handle keyval space */
609        ret = trove_keyval_write_list(
610            coll_id, root_dirdata_handle, key_a, val_a, keyval_count,
611            TROVE_SYNC, 0, NULL,
612            trove_context, &op_id, NULL);
613
614        while (ret == 0)
615        {
616            ret = trove_dspace_test(
617                coll_id, op_id, trove_context, &count, NULL, NULL,
618                &state, TROVE_DEFAULT_TEST_TIMEOUT);
619        }
620
621        if (ret < 0)
622        {
623            gossip_err("error: dist-dir-struct keyval write for root dirdata handle "
624                       "failed; aborting!\n");
625            return -1;
626        }
627
628        mkspace_print(
629            verbose, "info: wrote attributes for root directory.\n");
630
631
632        /****************************************************
633          at this point we need to create and initialize the
634          lost+found directory as well
635        *****************************************************/
636        cur_extent.first = cur_extent.last = TROVE_HANDLE_NULL;
637        if (meta_handle_ranges)
638        {
639            get_handle_extent_from_ranges(
640                meta_handle_ranges, &cur_extent, s_used_handles, 2);
641
642            if ((cur_extent.first == TROVE_HANDLE_NULL) &&
643                (cur_extent.last == TROVE_HANDLE_NULL))
644            {
645                gossip_err("No valid meta handle ranges available! "
646                           "Using a default\n");
647            }
648            else
649            {
650                mkspace_print(
651                    verbose, "info: using meta handle range %llu-%llu for "
652                    "lost+found directory dspace\n", llu(cur_extent.first),
653                    llu(cur_extent.last));
654            }
655        }
656        extent_array.extent_count = 1;
657        extent_array.extent_array = &cur_extent;
658
659        ret = trove_dspace_create(
660            coll_id, &extent_array, &lost_and_found_handle,
661            PVFS_TYPE_DIRECTORY, NULL, TROVE_SYNC, NULL,
662            trove_context, &op_id, NULL);
663
664        while (ret == 0)
665        {
666            ret = trove_dspace_test(
667                coll_id, op_id, trove_context, &count, NULL, NULL,
668                &state, TROVE_DEFAULT_TEST_TIMEOUT);
669        }
670
671        if ((ret != 1) && (state != 0))
672        {
673            mkspace_print(verbose,
674                          "dspace create (for lost+found dir) failed.\n");
675            return -1;
676        }
677
678        mkspace_print(verbose,"info: created lost+found directory "
679                      "with handle %llu.\n", llu(lost_and_found_handle));
680        s_used_handles[2] = lost_and_found_handle;
681
682        /* set lost+found directory dspace attributes */
683        memset(&attr, 0, sizeof(TROVE_ds_attributes_s));
684        attr.uid = getuid();
685        attr.gid = getgid();
686        attr.mode = 0777;
687        attr.type = PVFS_TYPE_DIRECTORY;
688        attr.atime = attr.ctime = PINT_util_get_current_time();
689        attr.mtime = PINT_util_mktime_version(attr.ctime);
690
691        ret = trove_dspace_setattr(
692            coll_id, lost_and_found_handle, &attr, TROVE_SYNC, NULL,
693            trove_context, &op_id, NULL);
694
695        while (ret == 0)
696        {
697            ret = trove_dspace_test(
698                coll_id, op_id, trove_context, &count, NULL, NULL,
699                &state, TROVE_DEFAULT_TEST_TIMEOUT);
700        }
701
702        if (ret < 0)
703        {
704            gossip_err("error: dspace setattr for lost+found handle "
705                       "attributes failed; aborting!\n");
706            return -1;
707        }
708
709        /* create a dataspace to hold directory entries */
710        cur_extent.first = cur_extent.last = TROVE_HANDLE_NULL;
711        if (meta_handle_ranges)
712        {
713            get_handle_extent_from_ranges(
714                meta_handle_ranges, &cur_extent, s_used_handles, 3);
715
716            if ((cur_extent.first == TROVE_HANDLE_NULL) &&
717                (cur_extent.last == TROVE_HANDLE_NULL))
718            {
719                gossip_err("No valid meta handle ranges available! "
720                           "Using a default\n");
721            }
722            else
723            {
724                mkspace_print(
725                    verbose, "info: using meta handle range %llu-%llu for "
726                    "lost+found dirent dspace\n", llu(cur_extent.first),
727                    llu(cur_extent.last));
728            }
729        }
730        extent_array.extent_count = 1;
731        extent_array.extent_array = &cur_extent;
732
733        ret = trove_dspace_create(
734            coll_id, &extent_array, &lost_and_found_dirdata_handle,
735            PVFS_TYPE_DIRDATA, NULL, TROVE_SYNC, NULL,
736            trove_context, &op_id, NULL);
737
738        while (ret == 0)
739        {
740            ret = trove_dspace_test(
741                coll_id, op_id, trove_context, &count, NULL, NULL,
742                &state, TROVE_DEFAULT_TEST_TIMEOUT);
743        }
744
745        if ((ret != 1) && (state != 0))
746        {
747            gossip_err("dspace create (for dirent storage) failed.\n");
748            return -1;
749        }
750
751        mkspace_print(
752            verbose, "info: created dspace for dirents "
753            "with handle %llu\n", llu(lost_and_found_dirdata_handle));
754        s_used_handles[3] = lost_and_found_dirdata_handle;
755
756        /* set lost+found dirdata dspace attributes */
757        memset(&attr, 0, sizeof(TROVE_ds_attributes_s));
758        attr.uid = getuid();
759        attr.gid = getgid();
760        attr.mode = 0777;
761        attr.type = PVFS_TYPE_DIRDATA;
762        attr.atime = attr.ctime = PINT_util_get_current_time();
763        attr.mtime = PINT_util_mktime_version(attr.ctime);
764
765        ret = trove_dspace_setattr(
766            coll_id, lost_and_found_dirdata_handle, &attr, TROVE_SYNC, NULL,
767            trove_context, &op_id, NULL);
768
769        while (ret == 0)
770        {
771            ret = trove_dspace_test(
772                coll_id, op_id, trove_context, &count, NULL, NULL,
773                &state, TROVE_DEFAULT_TEST_TIMEOUT);
774        }
775
776        if (ret < 0)
777        {
778            gossip_err("error: dspace setattr for lost+found handle "
779                       "attributes failed; aborting!\n");
780            return -1;
781        }
782
783        key.buffer = DIRECTORY_ENTRY_KEYSTR;
784        key.buffer_sz = DIRECTORY_ENTRY_KEYLEN;
785        val.buffer = &lost_and_found_dirdata_handle;
786        val.buffer_sz = sizeof(TROVE_handle);
787
788        ret = trove_keyval_write(
789            coll_id, lost_and_found_handle, &key, &val,
790            TROVE_SYNC,
791            0, NULL, trove_context, &op_id, NULL);
792
793        while (ret == 0)
794        {
795            ret = trove_dspace_test(
796                coll_id, op_id, trove_context, &count, NULL, NULL,
797                &state, TROVE_DEFAULT_TEST_TIMEOUT);
798        }
799
800        if (ret < 0)
801        {
802            gossip_err("error: keyval write for handle used to store "
803                       "dirents failed; aborting!\n");
804            return -1;
805        }
806
807        mkspace_print(verbose, "info: wrote attributes for "
808                      "lost+found directory.\n");
809
810
811        /* set dist-dir-struct keyvals for lost+find handle and its dirdata handle
812         * use 1 dirdata server now, just as root handle
813         * */
814
815        /* adjust keyval values, others should be the same as the root handle */
816        val_a[0].buffer = &meta_dist_dir_attr;
817        val_a[2].buffer = &lost_and_found_dirdata_handle;
818        /* bitmap should be the same as the root handle for now */
819
820        mkspace_print(verbose,
821                " info: writing dist-dir-struct keyvals for lost+found handle: %llu "
822                " with server_no=%d and branch_level=%d \n",
823                llu(lost_and_found_handle),
824                meta_dist_dir_attr.server_no,
825                meta_dist_dir_attr.branch_level);
826
827        /* write to lost+found meta handle keyval space */
828        ret = trove_keyval_write_list(
829            coll_id, lost_and_found_handle, key_a, val_a, keyval_count,
830            TROVE_SYNC, 0, NULL,
831            trove_context, &op_id, NULL);
832
833        while (ret == 0)
834        {
835            ret = trove_dspace_test(
836                coll_id, op_id, trove_context, &count, NULL, NULL,
837                &state, TROVE_DEFAULT_TEST_TIMEOUT);
838        }
839
840        if (ret < 0)
841        {
842            gossip_err("error: keyval write for handle used to store "
843                       "dirents failed; aborting!\n");
844            return -1;
845        }
846
847
848        /* adjust dist_dir_attr val */
849        val_a[0].buffer = &dirdata_dist_dir_attr;
850
851        mkspace_print(verbose,
852                " info: writing dist-dir-struct keyvals for lost+found dirdata handle: %llu "
853                " with server_no=%d and branch_level=%d \n",
854                llu(lost_and_found_dirdata_handle),
855                dirdata_dist_dir_attr.server_no,
856                dirdata_dist_dir_attr.branch_level);
857
858        /* write to lost+found dirdata handle keyval space */
859        ret = trove_keyval_write_list(
860                coll_id, lost_and_found_dirdata_handle, key_a, val_a, keyval_count,
861                TROVE_SYNC, 0, NULL,
862                trove_context, &op_id, NULL);
863
864        while (ret == 0)
865        {
866            ret = trove_dspace_test(
867                    coll_id, op_id, trove_context, &count, NULL, NULL,
868                    &state, TROVE_DEFAULT_TEST_TIMEOUT);
869        }
870
871        if (ret < 0)
872        {
873            gossip_err("error: dist-dir-struct keyval write for lost+found dirdata handle "
874                    "failed; aborting!\n");
875            return -1;
876        }
877
878        mkspace_print(verbose, "info: wrote attributes for "
879                      "lost+found directory.\n");
880
881
882        /*
883          finally, crdirent the lost+found directory into the root
884          directory by writing the appropriate keyval info into the
885          root dirdata handle space
886        */
887        key.buffer = lost_and_found_string;
888        key.buffer_sz = strlen(lost_and_found_string) + 1;
889        val.buffer = &lost_and_found_handle;
890        val.buffer_sz = sizeof(TROVE_handle);
891
892        ret = trove_keyval_write(
893            coll_id, root_dirdata_handle, &key, &val,
894            TROVE_SYNC | TROVE_NOOVERWRITE | TROVE_KEYVAL_HANDLE_COUNT | TROVE_KEYVAL_DIRECTORY_ENTRY,
895            0,
896            NULL, trove_context, &op_id, NULL);
897
898        while (ret == 0)
899        {
900            ret = trove_dspace_test(
901                coll_id, op_id, trove_context, &count, NULL, NULL,
902                &state, TROVE_DEFAULT_TEST_TIMEOUT);
903        }
904
905        if (ret < 0)
906        {
907            gossip_err("error: keyval write for handle used to store "
908                       "dirents failed; aborting!\n");
909            return -1;
910        }
911
912        mkspace_print(verbose, "info: adding lost+found directory to "
913                      "the root directory.\n");
914    }
915       
916    if (trove_context != -1)
917    {
918        trove_close_context(coll_id, trove_context);
919    }
920    trove_finalize(TROVE_METHOD_DBPF);
921
922    mkspace_print(verbose, "collection created:\n"
923                  "\troot handle = %llu, coll id = %d, "
924                  "root string = \"%s\"\n",
925                  llu(root_handle), coll_id, ROOT_HANDLE_KEYSTR);
926
927    /* free space */
928    if (dist_dir_bitmap)
929    {
930        free(dist_dir_bitmap);
931    }
932    if (key_a)
933    {
934        free(key_a);
935    }
936    if (val_a)
937    {
938        free(val_a);
939    }
940
941    return 0;
942}
943
944int pvfs2_rmspace(
945    char *data_path,
946    char *meta_path,
947    char *collection,
948    TROVE_coll_id coll_id,
949    int remove_collection_only,
950    int verbose)
951{
952    int ret = -1;
953    TROVE_op_id op_id;
954    static int trove_is_initialized = 0;
955
956    /* try to initialize; fails if storage space isn't there */
957    if (!trove_is_initialized)
958    {
959        ret = trove_initialize(
960            TROVE_METHOD_DBPF, NULL,
961            data_path, meta_path, 0);
962        if (ret == -1)
963        {
964            gossip_err("error: storage space %s or %s does not "
965                       "exist; aborting!\n", data_path, meta_path);
966            return -1;
967        }
968        trove_is_initialized = 1;
969    }
970
971    mkspace_print(verbose, "Attempting to remove collection %s\n",
972                  collection);
973
974    ret = trove_collection_remove(
975        TROVE_METHOD_DBPF, collection, NULL, &op_id);
976    mkspace_print(
977        verbose, "PVFS2 Collection %s removed %s\n", collection,
978        (((ret == 1) || (ret == -TROVE_ENOENT)) ? "successfully" :
979         "with errors"));
980
981    if (!remove_collection_only)
982    {
983        ret = trove_storage_remove(TROVE_METHOD_DBPF, data_path, meta_path,
984                                   NULL, &op_id);
985        /*
986         * it is a bit weird to do a trove_finaliz() prior to blowing away
987         * the storage space, but this allows the __db files of the DB env
988         * to be blown away for the rmdir() to work correctly!
989         */
990        trove_finalize(TROVE_METHOD_DBPF);
991        mkspace_print(
992            verbose, "PVFS2 Storage Space %s and %s removed %s\n",
993            data_path, meta_path, (((ret == 1) || (ret == -TROVE_ENOENT)) ?
994                            "successfully" : "with errors"));
995
996        trove_is_initialized = 0;
997    }
998    return ret;
999}
1000
1001/*
1002 * Local variables:
1003 *  c-indent-level: 4
1004 *  c-basic-offset: 4
1005 * End:
1006 *
1007 * vim: ts=8 sts=4 sw=4 expandtab
1008 */
Note: See TracBrowser for help on using the browser.