home *** CD-ROM | disk | FTP | other *** search
/ ftp.parl.clemson.edu / 2015-02-07.ftp.parl.clemson.edu.tar / ftp.parl.clemson.edu / pub / pvfs2 / orangefs-2.8.3-20110323.tar.gz / orangefs-2.8.3-20110323.tar / orangefs / src / io / trove / trove-migrate.c < prev    next >
C/C++ Source or Header  |  2010-12-13  |  30KB  |  900 lines

  1. /*
  2.  * (C) 2009 Clemson University and The University of Chicago
  3.  *
  4.  * See COPYING in top-level directory.
  5.  */       
  6.  
  7. #include <stdlib.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <assert.h>
  11. #include "pvfs2-internal.h"
  12. #include "trove.h"
  13. #include "gossip.h"
  14. #include "trove-dbpf/dbpf.h"
  15. #include "pint-cached-config.h"
  16. #include "server-config-mgr.h"
  17.  
  18. #undef DEBUG_MIGRATE_PERF
  19.  
  20. /*
  21.  * Macros
  22.  */
  23. #define TROVE_DSPACE_WAIT(ret, coll_id, op_id,                  \
  24.                           context_id, op_count, state, label)   \
  25.     while (ret == 0)                                            \
  26.     {                                                           \
  27.         ret = trove_dspace_test(coll_id,                        \
  28.                                 op_id,                          \
  29.                                 context_id,                     \
  30.                                 &op_count,                      \
  31.                                 NULL,                           \
  32.                                 NULL,                           \
  33.                                 &state,                         \
  34.                                 TROVE_DEFAULT_TEST_TIMEOUT);    \
  35.     }                                                           \
  36.     if (ret < 0)                                                \
  37.     {                                                           \
  38.         gossip_err("trove_dspace_test failed: err=%d coll=%d    \
  39. op=%lld context=%lld count=%d state=%d\n",                      \
  40.                     ret, coll_id, llu(op_id),                   \
  41.                     llu(context_id), op_count, state);          \
  42.         goto label;                                             \
  43.     }
  44.  
  45. /*
  46.  * Prototypes
  47.  */
  48. static int migrate_collection_0_1_3 (TROVE_coll_id coll_id,
  49.                      const char* data_path,
  50.                      const char* meta_path);
  51. static int migrate_collection_0_1_4 (TROVE_coll_id coll_id,
  52.                      const char* data_path,
  53.                      const char* meta_path);
  54.  
  55. /*
  56.  * Migration Table
  57.  *
  58.  *  Migration routines should be listed in ascending order.
  59.  */
  60. struct migration_s
  61. {
  62.     int major;
  63.     int minor;
  64.     int incremental;
  65.     int (*migrate)(TROVE_coll_id coll_id,
  66.          const char* data_path,
  67.          const char* meta_path);
  68. };
  69.  
  70. /* format: major, minor, incremental, function to migrate.
  71.  * NOTE: this defines the version to migratem *FROM*. In other words,
  72.  * if currently running the version defined in the table, run the
  73.  * associated function. */
  74. struct migration_s migration_table[] =
  75. {
  76.     { 0, 1, 3, migrate_collection_0_1_3 },
  77.     { 0, 1, 4, migrate_collection_0_1_4 },
  78.     { 0, 0, 0, NULL }
  79. };
  80.  
  81. /*
  82.  * trove_get_version
  83.  *   coll_id     - collection id
  84.  *   major       - return major version
  85.  *   minor       - return minor version
  86.  *   incremental - return incremental version
  87.  *
  88.  * Return the major, minor and incremental digits of the dbpf storage version.
  89.  * \return 0 on success, non-zero otherwise
  90.  */
  91. int trove_get_version (TROVE_coll_id coll_id,
  92.                        int* major,
  93.                        int* minor,
  94.                        int* incremental)
  95. {
  96.     TROVE_context_id context_id = PVFS_CONTEXT_NULL;
  97.     TROVE_op_id      op_id;
  98.     TROVE_ds_state   state;
  99.     TROVE_keyval_s   key;
  100.     TROVE_keyval_s   data;
  101.     char             version[32] = {0};
  102.     int              ret;
  103.     int              count;
  104.  
  105.     memset (&key,  0, sizeof(key));
  106.     memset (&data, 0, sizeof(data));
  107.  
  108.     key.buffer     = TROVE_DBPF_VERSION_KEY;
  109.     key.buffer_sz  = strlen(TROVE_DBPF_VERSION_KEY);
  110.     data.buffer    = version;
  111.     data.buffer_sz = sizeof(version);
  112.  
  113.     ret = trove_open_context(coll_id, &context_id);
  114.     if (ret < 0)
  115.     {
  116.         gossip_err("trove_open_context failed: ret=%d coll=%d\n",
  117.                    ret, coll_id);
  118.         goto complete;
  119.     }
  120.  
  121.     ret = trove_collection_geteattr(coll_id, &key, &data, 0, NULL,
  122.                                     context_id, &op_id);
  123.     if (ret < 0)
  124.     {
  125.         gossip_err("trove_collection_geteattr failed: ret=%d coll=%d \
  126. context=%lld op=%lld\n",
  127.                    ret, coll_id, llu(context_id), llu(op_id));
  128.         goto complete;
  129.     }
  130.  
  131.     TROVE_DSPACE_WAIT(ret, coll_id, op_id, context_id, count, state, complete);
  132.  
  133.     ret = sscanf(version, "%d.%d.%d", major, minor, incremental);
  134.     if (ret != 3)
  135.     {
  136.         gossip_err("sscanf failed: ret=%d errno=%d version=%s\n",
  137.                    ret, errno, version);
  138.         ret = -1;
  139.         goto complete;
  140.     }
  141.  
  142.     ret = 0;
  143.  
  144. complete:
  145.     if (context_id != PVFS_CONTEXT_NULL)
  146.     {
  147.         int rc = trove_close_context(coll_id, context_id);
  148.         if (rc < 0)
  149.         {
  150.             ret = rc;
  151.             gossip_err("trove_context_close failed: ret=%d coll=%d \
  152. context=%lld\n",
  153.                        ret, coll_id, llu(context_id));
  154.         }
  155.     }
  156.  
  157.     return ret;
  158. }
  159.  
  160. /*
  161.  * trove_put_version
  162.  *   coll_id     - collection id
  163.  *   major       - major version
  164.  *   minor       - minor version
  165.  *   incremental - incremental version
  166.  *
  167.  * Set the major, minor and incremental digits of the dbpf storage version.
  168.  * \return 0 on success, non-zero otherwise
  169.  */
  170. int trove_put_version (TROVE_coll_id coll_id,
  171.                        int major, int minor, int incremental)
  172. {
  173.     TROVE_context_id context_id = PVFS_CONTEXT_NULL;
  174.     TROVE_op_id      op_id;
  175.     TROVE_ds_state   state;
  176.     TROVE_keyval_s   key;
  177.     TROVE_keyval_s   data;
  178.     char             version[32] = {0};
  179.     int              ret;
  180.     int              count;
  181.  
  182.     memset (&key,  0, sizeof(key));
  183.     memset (&data, 0, sizeof(data));
  184.  
  185.     key.buffer     = TROVE_DBPF_VERSION_KEY;
  186.     key.buffer_sz  = strlen(TROVE_DBPF_VERSION_KEY);
  187.     data.buffer    = version;
  188.     data.buffer_sz = sizeof(version);
  189.  
  190.     ret = trove_open_context(coll_id, &context_id);
  191.     if (ret < 0)
  192.     {
  193.         gossip_err("trove_open_context failed: ret=%d coll=%d\n",
  194.                    ret, coll_id);
  195.         goto complete;
  196.     }
  197.  
  198.     ret = trove_collection_geteattr(coll_id, &key, &data, 0, NULL,
  199.                                     context_id, &op_id);
  200.     if (ret < 0)
  201.     {
  202.         gossip_err("trove_collection_geteattr failed: ret=%d coll=%d \
  203. context=%lld op=%lld\n",
  204.                    ret, coll_id, llu(context_id), llu(op_id));
  205.         goto complete;
  206.     }
  207.  
  208.     TROVE_DSPACE_WAIT(ret, coll_id, op_id, context_id, count, state, complete);
  209.  
  210.     ret = snprintf (version, sizeof(version), "%d.%d.%d",
  211.                     major, minor, incremental);
  212.     if ((ret < 0) || (ret >= 32))
  213.     {
  214.         gossip_err("snprintf failed: ret=%d errno=%d version=%s\n",
  215.                    ret, errno, version);
  216.         ret = -1;
  217.         goto complete;
  218.     }
  219.  
  220.     /* set the size to a correct value, not 32 */
  221.     data.buffer_sz = strlen(data.buffer);
  222.     ret = trove_collection_seteattr(coll_id, &key, &data, 0, NULL,
  223.                                     context_id, &op_id);
  224.     if (ret < 0)
  225.     {
  226.         gossip_err("trove_collection_seteattr failed: ret=%d coll=%d \
  227. context=%lld op=%lld\n",
  228.                    ret, coll_id, llu(context_id), llu(op_id));
  229.         goto complete;
  230.     }
  231.  
  232.     TROVE_DSPACE_WAIT(ret, coll_id, op_id, context_id, count, state, complete);
  233.  
  234. complete:
  235.     if (context_id != PVFS_CONTEXT_NULL)
  236.     {
  237.         int rc = trove_close_context(coll_id, context_id);
  238.         if (rc < 0)
  239.         {
  240.             ret = rc;
  241.             gossip_err("trove_context_close failed: ret=%d coll=%d \
  242. context=%lld\n",
  243.                        ret, coll_id, llu(context_id));
  244.         }
  245.     }
  246.  
  247.     return ret;
  248. }
  249.  
  250. #ifdef DEBUG_MIGRATE_PERF
  251. static double wtime(void)
  252. {
  253.     struct timeval t;
  254.  
  255.     gettimeofday(&t, NULL);
  256.     return((double)t.tv_sec + (double)t.tv_usec / 1000000);
  257. }
  258. #endif
  259.  
  260. /*
  261.  * trove_migrate
  262.  *   method_id - method used to for trove access
  263.  *   data_path - path to data storage
  264.  *   meta_path - path to metadata storage
  265.  *
  266.  * Iterate over all collections and migrate each one.
  267.  * \return 0 on success, non-zero on failure
  268.  */
  269. int trove_migrate (TROVE_method_id method_id, const char* data_path,
  270.            const char* meta_path)
  271. {
  272.     TROVE_ds_position pos;
  273.     TROVE_coll_id     coll_id;
  274.     TROVE_op_id       op_id;
  275.     TROVE_keyval_s    name = {0};
  276.     struct migration_s *migrate_p;
  277.     int               count;
  278.     int               ret = 0;
  279.     int               major;
  280.     int               minor;
  281.     int               incremental;
  282.     int               i;
  283.     int               migrated;
  284. #ifdef DEBUG_MIGRATE_PERF
  285.     double            s,e;
  286.     s = wtime();
  287. #endif
  288.  
  289.     count          = 1;
  290.     pos            = TROVE_ITERATE_START;
  291.     name.buffer    = malloc(PATH_MAX);
  292.     name.buffer_sz = PATH_MAX;
  293.  
  294.     if (!name.buffer)
  295.     {
  296.         ret = errno;
  297.         gossip_err("malloc failed: errno=%d\n", errno);
  298.         goto complete;
  299.     }
  300.     memset(name.buffer,0,PATH_MAX);
  301.  
  302.     while (count > 0)
  303.     {
  304.         ret = trove_collection_iterate(method_id,
  305.                                        &pos,
  306.                                        &name,
  307.                                        &coll_id,
  308.                                        &count,
  309.                                        0,
  310.                                        NULL,
  311.                                        NULL,
  312.                                        &op_id);
  313.         if (ret < 0)
  314.         {
  315.             gossip_err("trove_collection_iterate failed: \
  316. ret=%d method=%d pos=%lld name=%p coll=%d count=%d op=%lld\n",
  317.                        ret, method_id, llu(pos), &name,
  318.                        coll_id, count, llu(op_id));
  319.             goto complete;
  320.         }
  321.  
  322.         for (i=0; i<count; i++)
  323.         {
  324.             ret = trove_get_version(coll_id, &major, &minor, &incremental);
  325.             if (ret < 0)
  326.             {
  327.                 gossip_err("trove_get_version failed: ret=%d coll=%d\n",
  328.                            ret, coll_id);
  329.                 goto complete;
  330.             }
  331.  
  332.             migrated = 0;
  333.             for (migrate_p = &(migration_table[0]);
  334.                  migrate_p->migrate != NULL;
  335.                  migrate_p++)
  336.             {
  337.                 if ((major <= migrate_p->major) &&
  338.                     (minor <= migrate_p->minor) &&
  339.                     (incremental <= migrate_p->incremental))
  340.                 {
  341.                     gossip_err("Trove Migration Started: Ver=%d.%d.%d\n",
  342.                                migrate_p->major,
  343.                                migrate_p->minor,
  344.                                migrate_p->incremental);
  345.                     ret = migrate_p->migrate(coll_id, data_path, meta_path);
  346.                     if (ret < 0)
  347.                     {
  348.                         gossip_err("migrate failed: \
  349. ret=%d coll=%d metadir=%s datadir=%s major=%d minor=%d incremental=%d\n",
  350.                                    ret, coll_id, meta_path, data_path,
  351.                    migrate_p->major, migrate_p->minor, 
  352.                    migrate_p->incremental);
  353.                         goto complete;
  354.                     }
  355.                     gossip_err("Trove Migration Complete: Ver=%d.%d.%d\n",
  356.                                migrate_p->major,
  357.                                migrate_p->minor,
  358.                                migrate_p->incremental);
  359.                     migrated = 1;
  360.                 }
  361.             }
  362.  
  363.             if (migrated)
  364.             {
  365.                 ret = sscanf(TROVE_DBPF_VERSION_VALUE, "%d.%d.%d",
  366.                              &major, &minor, &incremental);
  367.                 if (ret !=3)
  368.                 {
  369.                     gossip_err("sscanf failed: ret=%d\n", ret);
  370.                     goto complete;
  371.                 }
  372.  
  373.                 ret = trove_put_version (coll_id, major, minor, incremental);
  374.                 if (ret < 0)
  375.                 {
  376.                     gossip_err("trove_put_version failed: ret=%d coll=%d \
  377. ver=%d.%d.%d\n",
  378.                                ret, coll_id, major, minor, incremental);
  379.                     goto complete;
  380.                 }
  381.  
  382.                 gossip_err("Trove Version Set: %d.%d.%d\n",
  383.                            major, minor, incremental);
  384.             }
  385.         }
  386.     }
  387.  
  388. complete:
  389.     if (name.buffer)
  390.     {
  391.         free(name.buffer);
  392.     }
  393. #ifdef DEBUG_MIGRATE_PERF
  394.     e = wtime();
  395.     gossip_err("migrate time: %lf seconds\n", (e-s));
  396. #endif
  397.     return ret;
  398. }
  399.  
  400. /*
  401.  * migrate_collection_0_1_3
  402.  *   coll_id   - collection id
  403.  *   data_path - path to data storage
  404.  *   meta_path - path to metadata storage
  405.  *
  406.  * For each datafile handle, check the file length and update the
  407.  * b_size attribute.
  408.  * \return 0 on success, non-zero on failure
  409.  */
  410. static int migrate_collection_0_1_3 (TROVE_coll_id coll_id, 
  411.                      const char* data_path,
  412.                      const char* meta_path)
  413. {
  414.     TROVE_context_id  context_id = PVFS_CONTEXT_NULL;
  415.     TROVE_ds_position pos;
  416.     TROVE_ds_state    state;
  417.     TROVE_op_id       iterate_op_id;
  418.     TROVE_op_id       setattr_op_id;
  419.     TROVE_op_id       getattr_op_id;
  420.     TROVE_handle*     handles;
  421.     TROVE_ds_attributes_s *attrs;
  422.     TROVE_ds_state    *states;
  423.     TROVE_ds_state    *completed_states;
  424.     TROVE_op_id       *completed_ids;
  425.     void              **user;
  426.     int               base_count;
  427.     int               handle_count;
  428.     int               completed_count;
  429.     int               op_count;
  430.     int               ret;
  431.     int               i, j, k;
  432.     int               outstanding_op_count;
  433.     int               immediate_completion;
  434.  
  435.     base_count = 10000;
  436.     
  437.     handles = malloc(sizeof(TROVE_handle)*base_count);
  438.     if (!handles)
  439.     {
  440.         gossip_err("malloc failed: errno=%d size=%d\n",
  441.                    errno, (int)(sizeof(TROVE_handle)*base_count));
  442.         return -1;
  443.     }
  444.  
  445.     attrs = malloc(sizeof(TROVE_ds_attributes_s)*base_count);
  446.     if (!attrs)
  447.     {
  448.         gossip_err("malloc failed: errno=%d size=%d\n",
  449.                    errno, (int)(sizeof(TROVE_ds_attributes)*base_count));
  450.         return -1;
  451.     }
  452.  
  453.     states = malloc(sizeof(TROVE_ds_state)*base_count);
  454.     if (!states)
  455.     {
  456.         gossip_err("malloc failed: errno=%d size=%d\n",
  457.                    errno, (int)(sizeof(TROVE_ds_state)*base_count));
  458.         return -1;
  459.     }
  460.  
  461.     completed_states = malloc(sizeof(TROVE_ds_state)*base_count);
  462.     if (!completed_states)
  463.     {
  464.         gossip_err("malloc failed: errno=%d size=%d\n",
  465.                    errno, (int)(sizeof(TROVE_ds_state)*base_count));
  466.         return -1;
  467.     }
  468.  
  469.     completed_ids = malloc(sizeof(TROVE_op_id)*base_count);
  470.     if (!completed_ids)
  471.     {
  472.         gossip_err("malloc failed: errno=%d size=%d\n",
  473.                    errno, (int)(sizeof(TROVE_op_id)*base_count));
  474.         return -1;
  475.     }
  476.  
  477.     user = (void**) malloc(sizeof(void*)*base_count);
  478.     if (!user)
  479.     {
  480.         gossip_err("malloc failed: errno=%d size=%d\n",
  481.                    errno, (int)(sizeof(void*)*base_count));
  482.         return -1;
  483.     }
  484.     for (i = 0; i < base_count; i++)
  485.     {
  486.         user[i] = NULL;
  487.     }
  488.  
  489.     ret = trove_open_context(coll_id, &context_id);
  490.     if (ret < 0)
  491.     {
  492.         gossip_err("trove_open_context failed: ret=%d coll=%d\n",
  493.                    ret, coll_id);
  494.         goto complete;
  495.     }
  496.  
  497.     immediate_completion = 1;
  498.     ret = trove_collection_setinfo(coll_id, context_id,
  499.                                    TROVE_COLLECTION_IMMEDIATE_COMPLETION,
  500.                                     &immediate_completion);
  501.     if (ret < 0)
  502.     {
  503.         gossip_err("trove_collection_setinfo failed: ret=%d coll=%d context=%lld\n",
  504.                    ret, coll_id, lld(context_id));
  505.         goto complete;
  506.     }
  507.  
  508.     pos = TROVE_ITERATE_START;
  509.  
  510.     do
  511.     {
  512.         outstanding_op_count = 0;
  513.         handle_count         = base_count;
  514.  
  515.         ret = trove_dspace_iterate_handles(coll_id,
  516.                                            &pos,
  517.                                            handles,
  518.                                            &handle_count,
  519.                                            0,
  520.                                            NULL,
  521.                                            NULL,
  522.                                            context_id,
  523.                                            &iterate_op_id);
  524.         if (ret < 0)
  525.         {
  526.             gossip_err("trove_dspace_iterate_handles failed: \
  527. ret=%d coll=%d pos=%lld handles=%p count=%d context=%lld op=%lld\n",
  528.                        ret, coll_id, llu(pos), handles, handle_count,
  529.                        llu(context_id), llu(iterate_op_id));
  530.             goto complete;
  531.         }
  532.         TROVE_DSPACE_WAIT(ret, coll_id, iterate_op_id, context_id, \
  533.                           op_count, state, complete);
  534.  
  535.         ret = trove_dspace_getattr_list(coll_id,
  536.                                         handle_count,
  537.                                         handles,
  538.                                         attrs,
  539.                                         states,
  540.                                         0,
  541.                                         NULL,
  542.                                         context_id,
  543.                                         &getattr_op_id,
  544.                                         PVFS_HINT_NULL); 
  545.         if (ret < 0)
  546.         {
  547.             gossip_err("trove_dspace_getattr_list failed: \
  548. ret=%d coll=%d handles=%p attrs=%p states=%p count=%d context=%lld op=%lld\n",
  549.                        ret, coll_id, handles, attrs, states, handle_count,
  550.                        llu(context_id), llu(getattr_op_id));
  551.             goto complete;
  552.         }
  553.  
  554.         TROVE_DSPACE_WAIT(ret, coll_id, getattr_op_id, context_id, \
  555.                           op_count, state, complete);
  556.         for (i = 0; i < handle_count; i++)
  557.         {
  558.             if (states[i] != 0)
  559.             {
  560.                 ret = -1;
  561.                 gossip_err("trove_dspace_getattr_list failure: \
  562. coll=%d context=%lld handle=%llu state=%d\n",
  563.                            coll_id, lld(context_id),
  564.                            llu(handles[i]), states[i]);
  565.                 goto complete;
  566.             }
  567.  
  568.             if (attrs[i].type == PVFS_TYPE_DATAFILE)
  569.             {
  570.                 struct stat  stat_data;
  571.                 char         filename[PATH_MAX];
  572.                 TROVE_size   b_size;
  573.  
  574.                 DBPF_GET_BSTREAM_FILENAME(filename,
  575.                                           PATH_MAX,
  576.                                           data_path,
  577.                                           coll_id,
  578.                                           llu(handles[i]));
  579.                 ret = stat(filename, &stat_data);
  580.                 if ((ret != 0) && (errno == ENOENT))
  581.                 {
  582.                     /* The bstream does not exist, assume this is due
  583.                      *  to lazy creation.
  584.                      */
  585.                     b_size = 0;
  586.                 }
  587.                 else if (ret != 0)
  588.                 {
  589.                     gossip_err("stat failed: ret=%d errno=%d fname=%s\n",
  590.                                ret, errno, filename);
  591.                     goto complete;
  592.                 }
  593.                 else
  594.                 {
  595.                     b_size = (TROVE_size) stat_data.st_size;
  596.                 }
  597.  
  598.                 /*
  599.                  * Set bstream size
  600.                  */
  601.                 attrs[i].u.datafile.b_size = b_size;
  602.  
  603.                 ret = trove_dspace_setattr(coll_id,
  604.                                            handles[i],
  605.                                            &(attrs[i]),
  606.                                            0,
  607.                                            NULL,
  608.                                            context_id,
  609.                                            &setattr_op_id,
  610.                                            PVFS_HINT_NULL);
  611.                 if (ret < 0)
  612.                 {
  613.                     gossip_err("trove_dspace_setattr failed: \
  614. ret=%d handle=%lld context=%lld op=%lld\n",
  615.                                ret, llu(handles[i]),
  616.                                lld(context_id), lld(setattr_op_id));
  617.                     goto complete;
  618.                 }
  619.  
  620.                 if (ret == 0)
  621.                 {
  622.                     outstanding_op_count++;
  623.                 }
  624.             }
  625.         }
  626.  
  627.         for (j = outstanding_op_count; j > 0; )
  628.         {
  629.             completed_count = base_count;
  630.  
  631.             ret = trove_dspace_testcontext(coll_id,
  632.                                            completed_ids,
  633.                                            &completed_count,
  634.                                            completed_states,
  635.                                            user,
  636.                                            10,
  637.                                            context_id);
  638.             if (ret < 0)
  639.             {
  640.                 gossip_err("trove_dspace_testcontext failed: ret=%d \
  641. coll=%d ids=%p count=%d states=%p context=%lld\n",
  642.                            ret, coll_id, completed_ids,
  643.                            completed_count, completed_states,
  644.                            lld(context_id));
  645.                 goto complete;
  646.             }
  647.  
  648.             j -= completed_count;
  649.  
  650.             for (k = 0; k < completed_count; k++)
  651.             {
  652.                 if (completed_states[k] != 0)
  653.                 {
  654.                     gossip_err("trove_dspace_testcontext failure: \
  655. coll=%d id=%lld state=%d\n",
  656.                                coll_id, lld(completed_ids[k]),
  657.                                completed_states[k]);
  658.                     goto complete;
  659.                 }
  660.             }
  661.         }
  662.     } while (handle_count > 0);
  663.  
  664. complete:
  665.  
  666.     if (context_id != PVFS_CONTEXT_NULL)
  667.     {
  668.         int rc = trove_close_context(coll_id, context_id);
  669.         if (rc < 0)
  670.         {
  671.             ret = rc;
  672.             gossip_err("trove_close_context failed: ret=%d coll=%d \
  673. context=%lld\n",
  674.                        ret, coll_id, llu(context_id));
  675.         }
  676.     }
  677.  
  678.     if (handles)
  679.     {
  680.         free(handles);
  681.     }
  682.  
  683.     if (attrs)
  684.     {
  685.         free(attrs);
  686.     }
  687.  
  688.     if (states)
  689.     {
  690.         free(states);
  691.     }
  692.  
  693.     if (completed_states)
  694.     {
  695.         free(completed_states);
  696.     }
  697.  
  698.     if (completed_ids)
  699.     {
  700.         free(completed_ids);
  701.     }
  702.  
  703.     if (user)
  704.     {
  705.         free(user);
  706.     }
  707.  
  708.     return ret;
  709. }
  710.  
  711.  
  712. /*
  713.  * migrate_collection_0_1_4
  714.  *   coll_id   - collection id
  715.  *   data_path - path to data storage
  716.  *   meta_path - path to metadata storage
  717.  *
  718.  * Migrate existing precreate pool keys held in the collection attributes
  719.  * to include the handle type (PVFS_TYPE_DATAFILE) in the key. Since prior
  720.  * to this version only PVFS_TYPE_DATAFILE handles existed in a pool this
  721.  * is an easy conversion to make 
  722.  *
  723.  * \return 0 on success, non-zero on failure
  724.  */
  725. static int migrate_collection_0_1_4 (TROVE_coll_id coll_id, 
  726.                      const char* data_path,
  727.                      const char* meta_path)
  728. {
  729.     int ret=0, i=0, server_count=0, server_type=0, count=0, pool_key_len=0;
  730.     const char *host;
  731.     /* hostname + pool key string + handle type size */
  732.     char pool_key[PVFS_MAX_SERVER_ADDR_LEN + 28] = { 0 };
  733.     char type_string[11] = { 0 };
  734.     TROVE_context_id  context_id = PVFS_CONTEXT_NULL;
  735.     TROVE_keyval_s key, data;
  736.     TROVE_op_id delattr_op_id, getattr_op_id, setattr_op_id;
  737.     TROVE_ds_state state;
  738.     PVFS_BMI_addr_t* addr_array = NULL;
  739.     PVFS_handle handle = PVFS_HANDLE_NULL;
  740.  
  741.     struct server_configuration_s *user_opts = get_server_config_struct();
  742.     assert(user_opts);
  743.  
  744.     gossip_debug(GOSSIP_TROVE_DEBUG, "%s: %d, %s, %s\n", 
  745.                  __func__, coll_id, data_path, meta_path);
  746.  
  747.     ret = trove_open_context(coll_id, &context_id);
  748.     if (ret < 0)
  749.     {
  750.         gossip_err("%s: trove_open_context failed: ret=%d coll=%d\n", __func__, 
  751.                     ret, coll_id);
  752.         return ret;
  753.     }
  754.  
  755.     /* for completeness we will check even if this server claims it's not a 
  756.      * metadata server to make sure we get all precreate pool handles updated.
  757.      * If it doesn't have any defined then our geteattr calls will just return
  758.      * with no record, Also check all peer servers for a precreate pool for
  759.      * the same reason (and it's easier anyway). */
  760.     ret = PINT_cached_config_count_servers( coll_id, PINT_SERVER_TYPE_ALL, 
  761.                                             &server_count);
  762.     if(ret < 0)
  763.     {
  764.         gossip_err("%s: error: unable to count servers for fsid: %d\n",
  765.                    __func__, (int)coll_id);
  766.         return ret;
  767.     }
  768.  
  769.     addr_array = calloc(server_count, sizeof(PVFS_BMI_addr_t));
  770.     if(!addr_array)
  771.     {
  772.         gossip_err("%s: error: unable to allocate addr array for precreate "
  773.                    "pools.\n", __func__);
  774.         ret = -PVFS_ENOMEM;
  775.         goto complete;
  776.     }
  777.  
  778.     /* resolve addrs for each I/O server */
  779.     ret = PINT_cached_config_get_server_array(coll_id, PINT_SERVER_TYPE_ALL, 
  780.                                               addr_array, &server_count);
  781.     if(ret < 0)
  782.     {
  783.         gossip_err("%s: error: unable retrieve servers addrs\n", __func__);
  784.         goto complete;
  785.     }
  786.        
  787.     /* check each server for a precreate pool and check for only one pool since
  788.      * that's all there was prior to this version */
  789.     for(i=0; i<server_count; i++)
  790.     {
  791.         host = PINT_cached_config_map_addr(coll_id, addr_array[i], 
  792.                                            &server_type);
  793.         /* potential host with precreate pool entry */
  794.         memset(&key,  0, sizeof(key));
  795.         memset(&data, 0, sizeof(data));
  796.         memset(pool_key, 0, PVFS_MAX_SERVER_ADDR_LEN + 28);
  797.  
  798.         pool_key_len = strlen(host) + strlen("precreate-pool-") + 1;
  799.         key.buffer = pool_key;
  800.         key.buffer_sz = pool_key_len;
  801.         key.read_sz = 0;
  802.  
  803.         snprintf((char*)key.buffer, key.buffer_sz, "precreate-pool-%s", host);
  804.         data.buffer    = &handle;
  805.         data.buffer_sz = sizeof(handle);
  806.         data.read_sz = 0;
  807.  
  808.         gossip_debug(GOSSIP_TROVE_DEBUG, "%s: looking for pool key\n", 
  809.                      __func__);
  810.         gossip_debug(GOSSIP_TROVE_DEBUG, "%s: key(%s)(%d)(%d)\n", 
  811.                      __func__, (char *)key.buffer, key.buffer_sz, key.read_sz);
  812.         gossip_debug(GOSSIP_TROVE_DEBUG, "%s: data(%s)(%d)(%d)\n", 
  813.                    __func__, (char *)data.buffer, data.buffer_sz, data.read_sz);
  814.         ret = trove_collection_geteattr(coll_id, &key, &data, 0, NULL, 
  815.                                         context_id, &getattr_op_id);
  816.         if (ret < 0)
  817.         {
  818.             gossip_err("%s: trove_collection_getattr failed for pool key %s "
  819.                        "ret=%d coll=%d context=%lld op=%lld\n", __func__,
  820.                        pool_key, ret, coll_id, llu(context_id), 
  821.                        llu(getattr_op_id));
  822.             continue;
  823.         } 
  824.         TROVE_DSPACE_WAIT(ret, coll_id, getattr_op_id, context_id, count, state,
  825.                           complete);
  826.         gossip_debug(GOSSIP_TROVE_DEBUG, "%s: found pool key\n", __func__);
  827.         gossip_debug(GOSSIP_TROVE_DEBUG, "%s: key(%s)(%d)(%d)\n", 
  828.                      __func__, (char *)key.buffer, key.buffer_sz, key.read_sz);
  829.         gossip_debug(GOSSIP_TROVE_DEBUG, "%s: data(%llu)(%d)(%d)\n", 
  830.                      __func__, llu(*(PVFS_handle *)data.buffer), data.buffer_sz,
  831.                      data.read_sz);
  832.  
  833.         ret = trove_collection_deleattr(coll_id, &key, 0, NULL, context_id, 
  834.                                         &delattr_op_id);
  835.         if (ret < 0)
  836.         {
  837.             gossip_err("%s: trove_collection_delattr failed: \
  838.                        ret=%d coll=%d context=%lld op=%lld\n", __func__,
  839.                        ret, coll_id, llu(context_id), llu(delattr_op_id));
  840.             goto complete;
  841.         } 
  842.         TROVE_DSPACE_WAIT(ret, coll_id, delattr_op_id, context_id, count, state,
  843.                           complete);
  844.         gossip_debug(GOSSIP_TROVE_DEBUG, "%s: removed old pool key\n", 
  845.                      __func__);
  846.  
  847.         /* munge to new key */
  848.         snprintf(type_string, 11, "%u", PVFS_TYPE_DATAFILE);
  849.         memset(pool_key, 0, PVFS_MAX_SERVER_ADDR_LEN + 28);
  850.         snprintf(pool_key, PVFS_MAX_SERVER_ADDR_LEN + 28,
  851.                  "precreate-pool-%s-%s", host, type_string);
  852.  
  853.         /* reset the length to include room for the type */
  854.         pool_key_len = strlen(host) + strlen(type_string) +
  855.                        strlen("precreate-pool-") + 2;
  856.         key.buffer_sz  = pool_key_len;
  857.  
  858.         gossip_debug(GOSSIP_TROVE_DEBUG, "%s: adding new pool key (%s) -> "
  859.                      "(%llu)\n", __func__, (char *)key.buffer, 
  860.                      llu(*(PVFS_handle *)data.buffer));
  861.         ret = trove_collection_seteattr(coll_id, &key, &data, 0, NULL, 
  862.                                         context_id, &setattr_op_id);
  863.         if (ret < 0)
  864.         {
  865.             gossip_err("%s: trove_collection_setattr failed: \
  866.                        ret=%d coll=%d context=%lld op=%lld\n", __func__,
  867.                        ret, coll_id, llu(context_id), llu(setattr_op_id));
  868.             goto complete;
  869.         } 
  870.         TROVE_DSPACE_WAIT(ret, coll_id, setattr_op_id, context_id, count, state,
  871.                           complete);
  872.         gossip_debug(GOSSIP_TROVE_DEBUG, "%s: successfully migrated pool %s\n",
  873.                      __func__, (char *)key.buffer);
  874.     } // for each server
  875.  
  876.     /* if we just came out of the loop force ret to 0, we don't want a bad
  877.      * key lookup to spoil the whole migration (since it's expected) */
  878.     ret = 0; 
  879.  
  880. complete:
  881.     if (context_id != PVFS_CONTEXT_NULL)
  882.     {
  883.         int rc = trove_close_context(coll_id, context_id);
  884.         if (rc < 0)
  885.         {
  886.             ret = rc;
  887.             gossip_err("%s: trove_close_context failed: ret=%d coll=%d " \
  888.                        "context=%lld\n", __func__, ret, coll_id, 
  889.                        llu(context_id));
  890.         }
  891.     }
  892.  
  893.     if( addr_array )
  894.     {
  895.         free(addr_array);
  896.     }
  897.  
  898.     return ret;
  899. }
  900.