root/branches/orange-next/src/common/misc/mkspace.c @ 8961

Revision 8961, 15.8 KB (checked in by mtmoore, 22 months ago)

trove/bmi version change, start working through handle changes from server-side file system creation

Line 
1/*
2 * (C) 2002 Clemson University and The University of Chicago
3 * (C) 2011 Omnibond Systems
4 *
5 * See COPYING in top-level directory.
6 */
7
8#include <unistd.h>
9#include <string.h>
10#include <stdio.h>
11#include <limits.h>
12#include <string.h>
13#include <stdlib.h>
14#include <time.h>
15#include <assert.h>
16
17#include "pvfs2-attr.h"
18#include "trove.h"
19#include "mkspace.h"
20#include "pvfs2-debug.h"
21#include "gossip.h"
22#include "server-config.h"
23#include "str-utils.h"
24#include "pvfs2-internal.h"
25#include "pint-util.h"
26#include "pint-event.h"
27
28static char *lost_and_found_string = "lost+found";
29static char handle_s[37] = { 0 };
30static TROVE_handle s_used_handles[4];
31
32#define mkspace_print(v, format, f...)              \
33do {                                                \
34 if (v == PVFS2_MKSPACE_GOSSIP_VERBOSE)             \
35   gossip_debug(GOSSIP_SERVER_DEBUG, format, ##f);  \
36 else if (v == PVFS2_MKSPACE_STDERR_VERBOSE)        \
37   fprintf(stderr,format, ##f);                     \
38} while(0)
39
40int pvfs2_mkspace(
41    char *data_path,
42    char *meta_path,
43    char *collection,
44    TROVE_coll_id coll_id,
45    TROVE_handle root_handle,
46    int create_collection_only,
47    int verbose)
48{
49    int ret = - 1, count = 0, i = 0;
50    TROVE_op_id op_id;
51    TROVE_ds_state state;
52    TROVE_keyval_s key, val;
53    TROVE_ds_attributes_s attr;
54    TROVE_context_id trove_context = -1;
55    TROVE_handle new_root_handle;
56    TROVE_handle root_dirdata_handle;
57    TROVE_handle lost_and_found_handle;
58    TROVE_handle lost_and_found_dirdata_handle;
59
60    uuid_unparse(root_handle, handle_s);
61
62    mkspace_print(verbose,"Data storage space     : %s\n",data_path);
63    mkspace_print(verbose,"Metadata storage space : %s\n", meta_path);
64    mkspace_print(verbose,"Collection   : %s\n",collection);
65    mkspace_print(verbose,"ID           : %d\n",coll_id);
66    mkspace_print(verbose,"Root Handle  : %s\n",handle_s);
67
68    PVFS_handle_clear(new_root_handle);
69    PVFS_handle_clear(root_dirdata_handle);
70    PVFS_handle_clear(lost_and_found_handle);
71    PVFS_handle_clear(lost_and_found_dirdata_handle);
72
73
74    PVFS_handle_copy(new_root_handle,root_handle);
75
76    /* clear out the 4 s_used_handles defined globally. should re-visit if
77     * they really need to be global */
78    for( i=0; i < 4; i++ )
79    {
80        PVFS_handle_clear( s_used_handles[i] );
81    }
82
83    /*
84      if we're only creating a collection inside an existing
85      storage space, we need to assume that it exists already
86    */
87    if (!create_collection_only)
88    {
89        /*
90          try to initialize; fails if storage space isn't there, which
91          is exactly what we're expecting in this case.
92        */
93        ret = trove_initialize(TROVE_METHOD_DBPF,
94                               NULL,
95                               data_path,
96                               meta_path,
97                               0);
98        if (ret > -1)
99        {
100            gossip_err("error: storage space %s or %s already "
101                       "exists; aborting!\n",data_path,meta_path);
102            return -1;
103        }
104
105        ret = trove_storage_create(TROVE_METHOD_DBPF, data_path, meta_path, NULL, &op_id);
106        if (ret != 1)
107        {
108            gossip_err("error: storage create failed; aborting!\n");
109            return -1;
110        }
111    }
112
113    /* now that the storage space exists, initialize trove properly */
114    ret = trove_initialize(
115        TROVE_METHOD_DBPF, NULL,
116        data_path, meta_path, 0);
117    if (ret < 0)
118    {
119        gossip_err("error: trove initialize failed; aborting!\n");
120        return -1;
121    }
122
123    mkspace_print(verbose,"info: created data storage space '%s'.\n",
124                  data_path);
125    mkspace_print(verbose,"info: created metadata storage space '%s'.\n",
126                  meta_path);
127
128    /* try to look up collection used to store file system */
129    ret = trove_collection_lookup(
130        TROVE_METHOD_DBPF, collection, &coll_id, NULL, &op_id);
131    if (ret == 1)
132    {
133        mkspace_print(verbose, "warning: collection lookup succeeded "
134                      "before it should; aborting!\n");
135        trove_finalize(TROVE_METHOD_DBPF);
136        return -1;
137    }
138
139    /* create the collection for the fs */
140    ret = trove_collection_create(collection, coll_id, NULL, &op_id);
141    if (ret != 1)
142    {
143        mkspace_print(verbose,"error: collection create failed for "
144                      "collection '%s'.\n",collection);
145        return -1;
146    }
147
148    /* make sure a collection lookup succeeds */
149    ret = trove_collection_lookup(
150        TROVE_METHOD_DBPF, collection, &coll_id, NULL, &op_id);
151    if (ret != 1)
152    {
153        mkspace_print(verbose,"error: collection lookup failed for "
154                      "collection '%s' after create.\n",collection);
155        return -1;
156    }
157
158    mkspace_print(verbose, "info: created collection '%s'.\n",collection);
159
160    ret = trove_open_context(coll_id, &trove_context);
161    if (ret < 0)
162    {
163        mkspace_print(verbose,"trove_open_context() failure.\n");
164        return -1;
165    }
166
167    /*
168      if a root_handle is specified, 1) create a dataspace to hold the
169      root directory 2) create the dspace for dir entries, 3) set
170      attributes on the dspace
171    */
172    if (! PVFS_handle_is_null(new_root_handle) )
173    {
174        ret = trove_dspace_create(
175            coll_id, &new_root_handle,
176            PVFS_TYPE_DIRECTORY, NULL,
177            (TROVE_SYNC | TROVE_FORCE_REQUESTED_HANDLE),
178            NULL, trove_context, &op_id, NULL);
179
180        while (ret == 0)
181        {
182            ret = trove_dspace_test(coll_id, op_id, trove_context,
183                                    &count, NULL, NULL, &state,
184                                    TROVE_DEFAULT_TEST_TIMEOUT);
185        }
186
187        if ((ret != 1) && (state != 0))
188        {
189            mkspace_print(verbose,
190                          "dspace create (for root dir) failed.\n");
191            return -1;
192        }
193
194        mkspace_print(verbose,"info: created root directory "
195                      "with handle %llu.\n", llu(new_root_handle));
196        PVFS_handle_copy(s_used_handles[0], new_root_handle);
197
198        /* set collection attribute for root handle */
199        key.buffer = ROOT_HANDLE_KEYSTR;
200        key.buffer_sz = ROOT_HANDLE_KEYLEN;
201        PVFS_handle_copy(*(PVFS_handle *)val.buffer, new_root_handle);
202        val.buffer_sz = sizeof(new_root_handle);
203        ret = trove_collection_seteattr(coll_id, &key, &val, 0,
204                                        NULL, trove_context, &op_id);
205        while (ret == 0)
206        {
207            ret = trove_dspace_test(
208                coll_id, op_id, trove_context, &count, NULL, NULL,
209                &state, TROVE_DEFAULT_TEST_TIMEOUT);
210        }
211
212        if (ret < 0)
213        {
214            gossip_err("error: collection seteattr (for root handle) "
215                       "failed; aborting!\n");
216            return -1;
217        }
218
219        /* set root directory dspace attributes */
220        memset(&attr, 0, sizeof(TROVE_ds_attributes_s));
221        attr.uid = getuid();
222        attr.gid = getgid();
223        attr.mode = 0777;
224        attr.type = PVFS_TYPE_DIRECTORY;
225        attr.atime = attr.ctime = PINT_util_get_current_time();
226        attr.mtime = PINT_util_mktime_version(attr.ctime);
227
228        ret = trove_dspace_setattr(
229            coll_id, new_root_handle, &attr, TROVE_SYNC, NULL,
230            trove_context, &op_id, NULL);
231
232        while (ret == 0)
233        {
234            ret = trove_dspace_test(
235                coll_id, op_id, trove_context, &count, NULL, NULL,
236                &state, TROVE_DEFAULT_TEST_TIMEOUT);
237        }
238
239        if (ret < 0)
240        {
241            gossip_err("error: dspace setattr for root handle "
242                       "attributes failed; aborting!\n");
243            return -1;
244        }
245
246        ret = trove_dspace_create(
247            coll_id, &root_dirdata_handle, PVFS_TYPE_DIRDATA, NULL, TROVE_SYNC,
248            NULL, trove_context, &op_id, NULL);
249
250        while (ret == 0)
251        {
252            ret = trove_dspace_test(
253                coll_id, op_id, trove_context, &count, NULL, NULL,
254                &state, TROVE_DEFAULT_TEST_TIMEOUT);
255        }
256
257        if ((ret != 1) && (state != 0))
258        {
259            gossip_err("dspace create (for dirent storage) failed.\n");
260            return -1;
261        }
262
263        mkspace_print(verbose, "info: created dspace for dirents "
264                      "with handle %llu\n", llu(root_dirdata_handle));
265        PVFS_handle_copy(s_used_handles[1], root_dirdata_handle);
266
267        key.buffer = DIRECTORY_ENTRY_KEYSTR;
268        key.buffer_sz = DIRECTORY_ENTRY_KEYLEN;
269        PVFS_handle_copy(*(PVFS_handle*)val.buffer, root_dirdata_handle);
270        val.buffer_sz = sizeof(TROVE_handle);
271
272        ret = trove_keyval_write(
273            coll_id, new_root_handle, &key, &val,
274            TROVE_SYNC, 0, NULL,
275            trove_context, &op_id, NULL);
276
277        while (ret == 0)
278        {
279            ret = trove_dspace_test(
280                coll_id, op_id, trove_context, &count, NULL, NULL,
281                &state, TROVE_DEFAULT_TEST_TIMEOUT);
282        }
283
284        if (ret < 0)
285        {
286            gossip_err("error: keyval write for handle used to store "
287                       "dirents failed; aborting!\n");
288            return -1;
289        }
290
291        mkspace_print(
292            verbose, "info: wrote attributes for root directory.\n");
293
294        /****************************************************
295          at this point we need to create and initialize the
296          lost+found directory as well
297        *****************************************************/
298        ret = trove_dspace_create(
299            coll_id, &lost_and_found_handle, PVFS_TYPE_DIRECTORY, NULL,
300            TROVE_SYNC, NULL, trove_context, &op_id, NULL);
301
302        while (ret == 0)
303        {
304            ret = trove_dspace_test(
305                coll_id, op_id, trove_context, &count, NULL, NULL,
306                &state, TROVE_DEFAULT_TEST_TIMEOUT);
307        }
308
309        if ((ret != 1) && (state != 0))
310        {
311            mkspace_print(verbose,
312                          "dspace create (for lost+found dir) failed.\n");
313            return -1;
314        }
315
316        mkspace_print(verbose,"info: created lost+found directory "
317                      "with handle %llu.\n", llu(lost_and_found_handle));
318        PVFS_handle_copy(s_used_handles[2], lost_and_found_handle);
319
320        /* set lost+found directory dspace attributes */
321        memset(&attr, 0, sizeof(TROVE_ds_attributes_s));
322        attr.uid = getuid();
323        attr.gid = getgid();
324        attr.mode = 0777;
325        attr.type = PVFS_TYPE_DIRECTORY;
326        attr.atime = attr.ctime = PINT_util_get_current_time();
327        attr.mtime = PINT_util_mktime_version(attr.ctime);
328
329        ret = trove_dspace_setattr(
330            coll_id, lost_and_found_handle, &attr, TROVE_SYNC, NULL,
331            trove_context, &op_id, NULL);
332
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: dspace setattr for lost+found handle "
343                       "attributes failed; aborting!\n");
344            return -1;
345        }
346
347        /* create a dataspace to hold directory entries */
348        ret = trove_dspace_create(
349            coll_id, &lost_and_found_dirdata_handle, PVFS_TYPE_DIRDATA, NULL,
350            TROVE_SYNC, NULL, trove_context, &op_id, NULL);
351
352        while (ret == 0)
353        {
354            ret = trove_dspace_test(
355                coll_id, op_id, trove_context, &count, NULL, NULL,
356                &state, TROVE_DEFAULT_TEST_TIMEOUT);
357        }
358
359        if ((ret != 1) && (state != 0))
360        {
361            gossip_err("dspace create (for dirent storage) failed.\n");
362            return -1;
363        }
364
365        mkspace_print(
366            verbose, "info: created dspace for dirents "
367            "with handle %llu\n", llu(lost_and_found_dirdata_handle));
368        PVFS_handle_copy(s_used_handles[3], lost_and_found_dirdata_handle);
369
370        key.buffer = DIRECTORY_ENTRY_KEYSTR;
371        key.buffer_sz = DIRECTORY_ENTRY_KEYLEN;
372        PVFS_handle_copy(*(PVFS_handle *)val.buffer,
373                         lost_and_found_dirdata_handle);
374        val.buffer_sz = sizeof(TROVE_handle);
375
376        ret = trove_keyval_write(
377            coll_id, lost_and_found_handle, &key, &val,
378            TROVE_SYNC,
379            0, NULL, trove_context, &op_id, NULL);
380
381        while (ret == 0)
382        {
383            ret = trove_dspace_test(
384                coll_id, op_id, trove_context, &count, NULL, NULL,
385                &state, TROVE_DEFAULT_TEST_TIMEOUT);
386        }
387
388        if (ret < 0)
389        {
390            gossip_err("error: keyval write for handle used to store "
391                       "dirents failed; aborting!\n");
392            return -1;
393        }
394
395        mkspace_print(verbose, "info: wrote attributes for "
396                      "lost+found directory.\n");
397
398        /*
399          finally, crdirent the lost+found directory into the root
400          directory by writing the appropriate keyval info into the
401          root dirdata handle space
402        */
403        key.buffer = lost_and_found_string;
404        key.buffer_sz = strlen(lost_and_found_string) + 1;
405        PVFS_handle_copy(*(PVFS_handle *)val.buffer, lost_and_found_handle);
406        val.buffer_sz = sizeof(TROVE_handle);
407
408        ret = trove_keyval_write(
409            coll_id, root_dirdata_handle, &key, &val,
410            TROVE_SYNC | TROVE_NOOVERWRITE | TROVE_KEYVAL_HANDLE_COUNT,
411            0,
412            NULL, trove_context, &op_id, NULL);
413
414        while (ret == 0)
415        {
416            ret = trove_dspace_test(
417                coll_id, op_id, trove_context, &count, NULL, NULL,
418                &state, TROVE_DEFAULT_TEST_TIMEOUT);
419        }
420
421        if (ret < 0)
422        {
423            gossip_err("error: keyval write for handle used to store "
424                       "dirents failed; aborting!\n");
425            return -1;
426        }
427
428        mkspace_print(verbose, "info: adding lost+found directory to "
429                      "the root directory.\n");
430    }
431       
432    if (trove_context != -1)
433    {
434        trove_close_context(coll_id, trove_context);
435    }
436    trove_finalize(TROVE_METHOD_DBPF);
437
438    mkspace_print(verbose, "collection created:\n"
439                  "\troot handle = %llu, coll id = %d, "
440                  "root string = \"%s\"\n",
441                  llu(root_handle), coll_id, ROOT_HANDLE_KEYSTR);
442    return 0;
443}
444
445int pvfs2_rmspace(
446    char *data_path,
447    char *meta_path,
448    char *collection,
449    TROVE_coll_id coll_id,
450    int remove_collection_only,
451    int verbose)
452{
453    int ret = -1;
454    TROVE_op_id op_id;
455    static int trove_is_initialized = 0;
456
457    /* try to initialize; fails if storage space isn't there */
458    if (!trove_is_initialized)
459    {
460        ret = trove_initialize(
461            TROVE_METHOD_DBPF, NULL,
462            data_path, meta_path, 0);
463        if (ret == -1)
464        {
465            gossip_err("error: storage space %s or %s does not "
466                       "exist; aborting!\n", data_path, meta_path);
467            return -1;
468        }
469        trove_is_initialized = 1;
470    }
471
472    mkspace_print(verbose, "Attempting to remove collection %s\n",
473                  collection);
474
475    ret = trove_collection_remove(
476        TROVE_METHOD_DBPF, collection, NULL, &op_id);
477    mkspace_print(
478        verbose, "PVFS2 Collection %s removed %s\n", collection,
479        (((ret == 1) || (ret == -TROVE_ENOENT)) ? "successfully" :
480         "with errors"));
481
482    if (!remove_collection_only)
483    {
484        ret = trove_storage_remove(TROVE_METHOD_DBPF, data_path, meta_path,
485                                   NULL, &op_id);
486        /*
487         * it is a bit weird to do a trove_finaliz() prior to blowing away
488         * the storage space, but this allows the __db files of the DB env
489         * to be blown away for the rmdir() to work correctly!
490         */
491        trove_finalize(TROVE_METHOD_DBPF);
492        mkspace_print(
493            verbose, "PVFS2 Storage Space %s and %s removed %s\n",
494            data_path, meta_path, (((ret == 1) || (ret == -TROVE_ENOENT)) ?
495                            "successfully" : "with errors"));
496
497        trove_is_initialized = 0;
498    }
499    return ret;
500}
501
502/*
503 * Local variables:
504 *  c-indent-level: 4
505 *  c-basic-offset: 4
506 * End:
507 *
508 * vim: ts=8 sts=4 sw=4 expandtab
509 */
Note: See TracBrowser for help on using the browser.