root/branches/orange-next/src/io/trove/trove-migrate.c @ 8959

Revision 8959, 21.6 KB (checked in by mtmoore, 22 months ago)

remove extents, handle ranges, precreate pools and various other things that aren't needed in their current forms with UUIDs

Line 
1/*
2 * (C) 2009 Clemson University and The University of Chicago
3 * (C) 2011 Omnibond Systems
4 *
5 * See COPYING in top-level directory.
6 */       
7
8#include <stdlib.h>
9#include <stdio.h>
10#include <string.h>
11#include <assert.h>
12#include "pvfs2-internal.h"
13#include "trove.h"
14#include "gossip.h"
15#include "trove-dbpf/dbpf.h"
16#include "pint-cached-config.h"
17#include "server-config-mgr.h"
18
19#undef DEBUG_MIGRATE_PERF
20
21/*
22 * Macros
23 */
24#define TROVE_DSPACE_WAIT(ret, coll_id, op_id,                  \
25                          context_id, op_count, state, label)   \
26    while (ret == 0)                                            \
27    {                                                           \
28        ret = trove_dspace_test(coll_id,                        \
29                                op_id,                          \
30                                context_id,                     \
31                                &op_count,                      \
32                                NULL,                           \
33                                NULL,                           \
34                                &state,                         \
35                                TROVE_DEFAULT_TEST_TIMEOUT);    \
36    }                                                           \
37    if (ret < 0)                                                \
38    {                                                           \
39        gossip_err("trove_dspace_test failed: err=%d coll=%d    \
40op=%lld context=%lld count=%d state=%d\n",                      \
41                    ret, coll_id, llu(op_id),                   \
42                    llu(context_id), op_count, state);          \
43        goto label;                                             \
44    }
45
46/*
47 * Prototypes
48 */
49static int migrate_collection_0_1_3 (TROVE_coll_id coll_id,
50                                     const char* data_path,
51                                     const char* meta_path);
52/*
53 * Migration Table
54 *
55 *  Migration routines should be listed in ascending order.
56 */
57struct migration_s
58{
59    int major;
60    int minor;
61    int incremental;
62    int (*migrate)(TROVE_coll_id coll_id,
63                 const char* data_path,
64                 const char* meta_path);
65};
66
67/* format: major, minor, incremental, function to migrate.
68 * NOTE: this defines the version to migratem *FROM*. In other words,
69 * if currently running the version defined in the table, run the
70 * associated function. */
71struct migration_s migration_table[] =
72{
73    { 0, 1, 3, migrate_collection_0_1_3 },
74    { 0, 0, 0, NULL }
75};
76
77/*
78 * trove_get_version
79 *   coll_id     - collection id
80 *   major       - return major version
81 *   minor       - return minor version
82 *   incremental - return incremental version
83 *
84 * Return the major, minor and incremental digits of the dbpf storage version.
85 * \return 0 on success, non-zero otherwise
86 */
87int trove_get_version (TROVE_coll_id coll_id,
88                       int* major,
89                       int* minor,
90                       int* incremental)
91{
92    TROVE_context_id context_id = PVFS_CONTEXT_NULL;
93    TROVE_op_id      op_id;
94    TROVE_ds_state   state;
95    TROVE_keyval_s   key;
96    TROVE_keyval_s   data;
97    char             version[32] = {0};
98    int              ret;
99    int              count;
100
101    memset (&key,  0, sizeof(key));
102    memset (&data, 0, sizeof(data));
103
104    key.buffer     = TROVE_DBPF_VERSION_KEY;
105    key.buffer_sz  = strlen(TROVE_DBPF_VERSION_KEY);
106    data.buffer    = version;
107    data.buffer_sz = sizeof(version);
108
109    ret = trove_open_context(coll_id, &context_id);
110    if (ret < 0)
111    {
112        gossip_err("trove_open_context failed: ret=%d coll=%d\n",
113                   ret, coll_id);
114        goto complete;
115    }
116
117    ret = trove_collection_geteattr(coll_id, &key, &data, 0, NULL,
118                                    context_id, &op_id);
119    if (ret < 0)
120    {
121        gossip_err("trove_collection_geteattr failed: ret=%d coll=%d \
122context=%lld op=%lld\n",
123                   ret, coll_id, llu(context_id), llu(op_id));
124        goto complete;
125    }
126
127    TROVE_DSPACE_WAIT(ret, coll_id, op_id, context_id, count, state, complete);
128
129    ret = sscanf(version, "%d.%d.%d", major, minor, incremental);
130    if (ret != 3)
131    {
132        gossip_err("sscanf failed: ret=%d errno=%d version=%s\n",
133                   ret, errno, version);
134        ret = -1;
135        goto complete;
136    }
137
138    ret = 0;
139
140complete:
141    if (context_id != PVFS_CONTEXT_NULL)
142    {
143        int rc = trove_close_context(coll_id, context_id);
144        if (rc < 0)
145        {
146            ret = rc;
147            gossip_err("trove_context_close failed: ret=%d coll=%d \
148context=%lld\n",
149                       ret, coll_id, llu(context_id));
150        }
151    }
152
153    return ret;
154}
155
156/*
157 * trove_put_version
158 *   coll_id     - collection id
159 *   major       - major version
160 *   minor       - minor version
161 *   incremental - incremental version
162 *
163 * Set the major, minor and incremental digits of the dbpf storage version.
164 * \return 0 on success, non-zero otherwise
165 */
166int trove_put_version (TROVE_coll_id coll_id,
167                       int major, int minor, int incremental)
168{
169    TROVE_context_id context_id = PVFS_CONTEXT_NULL;
170    TROVE_op_id      op_id;
171    TROVE_ds_state   state;
172    TROVE_keyval_s   key;
173    TROVE_keyval_s   data;
174    char             version[32] = {0};
175    int              ret;
176    int              count;
177
178    memset (&key,  0, sizeof(key));
179    memset (&data, 0, sizeof(data));
180
181    key.buffer     = TROVE_DBPF_VERSION_KEY;
182    key.buffer_sz  = strlen(TROVE_DBPF_VERSION_KEY);
183    data.buffer    = version;
184    data.buffer_sz = sizeof(version);
185
186    ret = trove_open_context(coll_id, &context_id);
187    if (ret < 0)
188    {
189        gossip_err("trove_open_context failed: ret=%d coll=%d\n",
190                   ret, coll_id);
191        goto complete;
192    }
193
194    ret = trove_collection_geteattr(coll_id, &key, &data, 0, NULL,
195                                    context_id, &op_id);
196    if (ret < 0)
197    {
198        gossip_err("trove_collection_geteattr failed: ret=%d coll=%d \
199context=%lld op=%lld\n",
200                   ret, coll_id, llu(context_id), llu(op_id));
201        goto complete;
202    }
203
204    TROVE_DSPACE_WAIT(ret, coll_id, op_id, context_id, count, state, complete);
205
206    ret = snprintf (version, sizeof(version), "%d.%d.%d",
207                    major, minor, incremental);
208    if ((ret < 0) || (ret >= 32))
209    {
210        gossip_err("snprintf failed: ret=%d errno=%d version=%s\n",
211                   ret, errno, version);
212        ret = -1;
213        goto complete;
214    }
215
216    /* set the size to a correct value, not 32 */
217    data.buffer_sz = strlen(data.buffer);
218    ret = trove_collection_seteattr(coll_id, &key, &data, 0, NULL,
219                                    context_id, &op_id);
220    if (ret < 0)
221    {
222        gossip_err("trove_collection_seteattr failed: ret=%d coll=%d \
223context=%lld op=%lld\n",
224                   ret, coll_id, llu(context_id), llu(op_id));
225        goto complete;
226    }
227
228    TROVE_DSPACE_WAIT(ret, coll_id, op_id, context_id, count, state, complete);
229
230complete:
231    if (context_id != PVFS_CONTEXT_NULL)
232    {
233        int rc = trove_close_context(coll_id, context_id);
234        if (rc < 0)
235        {
236            ret = rc;
237            gossip_err("trove_context_close failed: ret=%d coll=%d \
238context=%lld\n",
239                       ret, coll_id, llu(context_id));
240        }
241    }
242
243    return ret;
244}
245
246#ifdef DEBUG_MIGRATE_PERF
247static double wtime(void)
248{
249    struct timeval t;
250
251    gettimeofday(&t, NULL);
252    return((double)t.tv_sec + (double)t.tv_usec / 1000000);
253}
254#endif
255
256/*
257 * trove_migrate
258 *   method_id - method used to for trove access
259 *   data_path - path to data storage
260 *   meta_path - path to metadata storage
261 *
262 * Iterate over all collections and migrate each one.
263 * \return 0 on success, non-zero on failure
264 */
265int trove_migrate (TROVE_method_id method_id, const char* data_path,
266                   const char* meta_path)
267{
268    TROVE_rec_position pos;
269    TROVE_coll_id     coll_id;
270    TROVE_op_id       op_id;
271    TROVE_keyval_s    name = {0};
272    struct migration_s *migrate_p;
273    int               count;
274    int               ret = 0;
275    int               major;
276    int               minor;
277    int               incremental;
278    int               i;
279    int               migrated;
280    unsigned int      pos_flag;
281#ifdef DEBUG_MIGRATE_PERF
282    double            s,e;
283    s = wtime();
284#endif
285
286    count          = 1;
287    pos_flag       = TROVE_ITERATE_START;
288    name.buffer    = malloc(PATH_MAX);
289    name.buffer_sz = PATH_MAX;
290
291    if (!name.buffer)
292    {
293        ret = errno;
294        gossip_err("malloc failed: errno=%d\n", errno);
295        goto complete;
296    }
297    memset(name.buffer,0,PATH_MAX);
298
299    while (count > 0)
300    {
301        ret = trove_collection_iterate(method_id,
302                                       &pos,
303                                       &pos_flag,
304                                       &name,
305                                       &coll_id,
306                                       &count,
307                                       0,
308                                       NULL,
309                                       NULL,
310                                       &op_id);
311        if (ret < 0)
312        {
313            gossip_err("trove_collection_iterate failed: \
314ret=%d method=%d pos=%lld name=%p coll=%d count=%d op=%lld\n",
315                       ret, method_id, llu(pos), &name,
316                       coll_id, count, llu(op_id));
317            goto complete;
318        }
319
320        for (i=0; i<count; i++)
321        {
322            ret = trove_get_version(coll_id, &major, &minor, &incremental);
323            if (ret < 0)
324            {
325                gossip_err("trove_get_version failed: ret=%d coll=%d\n",
326                           ret, coll_id);
327                goto complete;
328            }
329
330            migrated = 0;
331            for (migrate_p = &(migration_table[0]);
332                 migrate_p->migrate != NULL;
333                 migrate_p++)
334            {
335                if ((major <= migrate_p->major) &&
336                    (minor <= migrate_p->minor) &&
337                    (incremental <= migrate_p->incremental))
338                {
339                    gossip_err("Trove Migration Started: Ver=%d.%d.%d\n",
340                               migrate_p->major,
341                               migrate_p->minor,
342                               migrate_p->incremental);
343                    ret = migrate_p->migrate(coll_id, data_path, meta_path);
344                    if (ret < 0)
345                    {
346                        gossip_err("migrate failed: \
347ret=%d coll=%d metadir=%s datadir=%s major=%d minor=%d incremental=%d\n",
348                                   ret, coll_id, meta_path, data_path,
349                                   migrate_p->major, migrate_p->minor,
350                                   migrate_p->incremental);
351                        goto complete;
352                    }
353                    gossip_err("Trove Migration Complete: Ver=%d.%d.%d\n",
354                               migrate_p->major,
355                               migrate_p->minor,
356                               migrate_p->incremental);
357                    migrated = 1;
358                }
359            }
360
361            if (migrated)
362            {
363                ret = sscanf(TROVE_DBPF_VERSION_VALUE, "%d.%d.%d",
364                             &major, &minor, &incremental);
365                if (ret !=3)
366                {
367                    gossip_err("sscanf failed: ret=%d\n", ret);
368                    goto complete;
369                }
370
371                ret = trove_put_version (coll_id, major, minor, incremental);
372                if (ret < 0)
373                {
374                    gossip_err("trove_put_version failed: ret=%d coll=%d \
375ver=%d.%d.%d\n",
376                               ret, coll_id, major, minor, incremental);
377                    goto complete;
378                }
379
380                gossip_err("Trove Version Set: %d.%d.%d\n",
381                           major, minor, incremental);
382            }
383        }
384    }
385
386complete:
387    if (name.buffer)
388    {
389        free(name.buffer);
390    }
391#ifdef DEBUG_MIGRATE_PERF
392    e = wtime();
393    gossip_err("migrate time: %lf seconds\n", (e-s));
394#endif
395    return ret;
396}
397
398/*
399 * migrate_collection_0_1_3
400 *   coll_id   - collection id
401 *   data_path - path to data storage
402 *   meta_path - path to metadata storage
403 *
404 * For each datafile handle, check the file length and update the
405 * b_size attribute.
406 * \return 0 on success, non-zero on failure
407 */
408static int migrate_collection_0_1_3 (TROVE_coll_id coll_id,
409                                     const char* data_path,
410                                     const char* meta_path)
411{
412    TROVE_context_id  context_id = PVFS_CONTEXT_NULL;
413    TROVE_ds_position pos;
414    TROVE_ds_state    state;
415    TROVE_op_id       iterate_op_id;
416    TROVE_op_id       setattr_op_id;
417    TROVE_op_id       getattr_op_id;
418    TROVE_handle*     handles;
419    TROVE_ds_attributes_s *attrs;
420    TROVE_ds_state    *states;
421    TROVE_ds_state    *completed_states;
422    TROVE_op_id       *completed_ids;
423    void              **user;
424    int               base_count;
425    int               handle_count;
426    int               completed_count;
427    int               op_count;
428    int               ret;
429    int               i, j, k;
430    int               outstanding_op_count;
431    int               immediate_completion;
432    unsigned int      pos_flag;
433
434    base_count = 10000;
435   
436    TROVE_handle_clear(pos);
437
438    handles = malloc(sizeof(TROVE_handle)*base_count);
439    if (!handles)
440    {
441        gossip_err("malloc failed: errno=%d size=%d\n",
442                   errno, (int)(sizeof(TROVE_handle)*base_count));
443        return -1;
444    }
445
446    attrs = malloc(sizeof(TROVE_ds_attributes_s)*base_count);
447    if (!attrs)
448    {
449        gossip_err("malloc failed: errno=%d size=%d\n",
450                   errno, (int)(sizeof(TROVE_ds_attributes)*base_count));
451        return -1;
452    }
453
454    states = malloc(sizeof(TROVE_ds_state)*base_count);
455    if (!states)
456    {
457        gossip_err("malloc failed: errno=%d size=%d\n",
458                   errno, (int)(sizeof(TROVE_ds_state)*base_count));
459        return -1;
460    }
461
462    completed_states = malloc(sizeof(TROVE_ds_state)*base_count);
463    if (!completed_states)
464    {
465        gossip_err("malloc failed: errno=%d size=%d\n",
466                   errno, (int)(sizeof(TROVE_ds_state)*base_count));
467        return -1;
468    }
469
470    completed_ids = malloc(sizeof(TROVE_op_id)*base_count);
471    if (!completed_ids)
472    {
473        gossip_err("malloc failed: errno=%d size=%d\n",
474                   errno, (int)(sizeof(TROVE_op_id)*base_count));
475        return -1;
476    }
477
478    user = (void**) malloc(sizeof(void*)*base_count);
479    if (!user)
480    {
481        gossip_err("malloc failed: errno=%d size=%d\n",
482                   errno, (int)(sizeof(void*)*base_count));
483        return -1;
484    }
485    for (i = 0; i < base_count; i++)
486    {
487        user[i] = NULL;
488    }
489
490    ret = trove_open_context(coll_id, &context_id);
491    if (ret < 0)
492    {
493        gossip_err("trove_open_context failed: ret=%d coll=%d\n",
494                   ret, coll_id);
495        goto complete;
496    }
497
498    immediate_completion = 1;
499    ret = trove_collection_setinfo(coll_id, context_id,
500                                   TROVE_COLLECTION_IMMEDIATE_COMPLETION,
501                                    &immediate_completion);
502    if (ret < 0)
503    {
504        gossip_err("trove_collection_setinfo failed: ret=%d coll=%d context=%lld\n",
505                   ret, coll_id, lld(context_id));
506        goto complete;
507    }
508
509    pos_flag = TROVE_ITERATE_START;
510
511    do
512    {
513        outstanding_op_count = 0;
514        handle_count         = base_count;
515
516        ret = trove_dspace_iterate_handles(coll_id,
517                                           &pos,
518                                           &pos_flag,
519                                           handles,
520                                           &handle_count,
521                                           0,
522                                           NULL,
523                                           NULL,
524                                           context_id,
525                                           &iterate_op_id);
526        if (ret < 0)
527        {
528            gossip_err("trove_dspace_iterate_handles failed: \
529ret=%d coll=%d pos_flag=%lld handles=%p count=%d context=%lld op=%lld\n",
530                       ret, coll_id, llu(pos_flag), handles, handle_count,
531                       llu(context_id), llu(iterate_op_id));
532            goto complete;
533        }
534        TROVE_DSPACE_WAIT(ret, coll_id, iterate_op_id, context_id, \
535                          op_count, state, complete);
536
537        ret = trove_dspace_getattr_list(coll_id,
538                                        handle_count,
539                                        handles,
540                                        attrs,
541                                        states,
542                                        0,
543                                        NULL,
544                                        context_id,
545                                        &getattr_op_id,
546                                        PVFS_HINT_NULL);
547        if (ret < 0)
548        {
549            gossip_err("trove_dspace_getattr_list failed: \
550ret=%d coll=%d handles=%p attrs=%p states=%p count=%d context=%lld op=%lld\n",
551                       ret, coll_id, handles, attrs, states, handle_count,
552                       llu(context_id), llu(getattr_op_id));
553            goto complete;
554        }
555
556        TROVE_DSPACE_WAIT(ret, coll_id, getattr_op_id, context_id, \
557                          op_count, state, complete);
558        for (i = 0; i < handle_count; i++)
559        {
560            if (states[i] != 0)
561            {
562                ret = -1;
563                gossip_err("trove_dspace_getattr_list failure: \
564coll=%d context=%lld handle=%llu state=%d\n",
565                           coll_id, lld(context_id),
566                           llu(handles[i]), states[i]);
567                goto complete;
568            }
569
570            if (attrs[i].type == PVFS_TYPE_DATAFILE)
571            {
572                struct stat  stat_data;
573                char         filename[PATH_MAX];
574                TROVE_size   b_size;
575
576                DBPF_GET_BSTREAM_FILENAME(filename,
577                                          PATH_MAX,
578                                          data_path,
579                                          coll_id,
580                                          llu(handles[i]));
581                ret = stat(filename, &stat_data);
582                if ((ret != 0) && (errno == ENOENT))
583                {
584                    /* The bstream does not exist, assume this is due
585                     *  to lazy creation.
586                     */
587                    b_size = 0;
588                }
589                else if (ret != 0)
590                {
591                    gossip_err("stat failed: ret=%d errno=%d fname=%s\n",
592                               ret, errno, filename);
593                    goto complete;
594                }
595                else
596                {
597                    b_size = (TROVE_size) stat_data.st_size;
598                }
599
600                /*
601                 * Set bstream size
602                 */
603                attrs[i].u.datafile.b_size = b_size;
604
605                ret = trove_dspace_setattr(coll_id,
606                                           handles[i],
607                                           &(attrs[i]),
608                                           0,
609                                           NULL,
610                                           context_id,
611                                           &setattr_op_id,
612                                           PVFS_HINT_NULL);
613                if (ret < 0)
614                {
615                    gossip_err("trove_dspace_setattr failed: \
616ret=%d handle=%lld context=%lld op=%lld\n",
617                               ret, llu(handles[i]),
618                               lld(context_id), lld(setattr_op_id));
619                    goto complete;
620                }
621
622                if (ret == 0)
623                {
624                    outstanding_op_count++;
625                }
626            }
627        }
628
629        for (j = outstanding_op_count; j > 0; )
630        {
631            completed_count = base_count;
632
633            ret = trove_dspace_testcontext(coll_id,
634                                           completed_ids,
635                                           &completed_count,
636                                           completed_states,
637                                           user,
638                                           10,
639                                           context_id);
640            if (ret < 0)
641            {
642                gossip_err("trove_dspace_testcontext failed: ret=%d \
643coll=%d ids=%p count=%d states=%p context=%lld\n",
644                           ret, coll_id, completed_ids,
645                           completed_count, completed_states,
646                           lld(context_id));
647                goto complete;
648            }
649
650            j -= completed_count;
651
652            for (k = 0; k < completed_count; k++)
653            {
654                if (completed_states[k] != 0)
655                {
656                    gossip_err("trove_dspace_testcontext failure: \
657coll=%d id=%lld state=%d\n",
658                               coll_id, lld(completed_ids[k]),
659                               completed_states[k]);
660                    goto complete;
661                }
662            }
663        }
664    } while (handle_count > 0);
665
666complete:
667
668    if (context_id != PVFS_CONTEXT_NULL)
669    {
670        int rc = trove_close_context(coll_id, context_id);
671        if (rc < 0)
672        {
673            ret = rc;
674            gossip_err("trove_close_context failed: ret=%d coll=%d \
675context=%lld\n",
676                       ret, coll_id, llu(context_id));
677        }
678    }
679
680    if (handles)
681    {
682        free(handles);
683    }
684
685    if (attrs)
686    {
687        free(attrs);
688    }
689
690    if (states)
691    {
692        free(states);
693    }
694
695    if (completed_states)
696    {
697        free(completed_states);
698    }
699
700    if (completed_ids)
701    {
702        free(completed_ids);
703    }
704
705    if (user)
706    {
707        free(user);
708    }
709
710    return ret;
711}
Note: See TracBrowser for help on using the browser.