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 / server / unstuff.sm < prev   
Text File  |  2010-09-20  |  13KB  |  501 lines

  1. /* 
  2.  * (C) 2001 Clemson University and The University of Chicago 
  3.  *
  4.  * See COPYING in top-level directory.
  5.  *
  6.  * Changes by Acxiom Corporation to add dirent_count field to attributes
  7.  * Copyright ┬⌐ Acxiom Corporation, 2005.
  8.  */
  9.  
  10. #include <string.h>
  11. #include <assert.h>
  12.  
  13. #include "server-config.h"
  14. #include "pvfs2-server.h"
  15. #include "pvfs2-attr.h"
  16. #include "pvfs2-types.h"
  17. #include "pvfs2-types-debug.h"
  18. #include "pvfs2-util.h"
  19. #include "pint-util.h"
  20. #include "pvfs2-internal.h"
  21. #include "pint-cached-config.h"
  22.  
  23. #define STATE_UNSTUFF 33
  24.  
  25. %%
  26.  
  27. machine pvfs2_unstuff_sm
  28. {
  29.     state prelude
  30.     {
  31.         jump pvfs2_prelude_sm;
  32.         success => getattr_setup;
  33.         default => final_response;
  34.     }
  35.  
  36.     state getattr_setup
  37.     {
  38.         run getattr_setup;
  39.         success => getattr_do_work;
  40.         default => final_response;
  41.     }
  42.  
  43.     state getattr_do_work
  44.     {
  45.         jump pvfs2_get_attr_work_sm;
  46.         default => getattr_interpret;
  47.     }
  48.  
  49.     state getattr_interpret
  50.     {
  51.         run getattr_interpret;
  52.         STATE_UNSTUFF => get_keyvals;
  53.         default => final_response;
  54.     }
  55.  
  56.     state get_keyvals
  57.     {
  58.         run get_keyvals;
  59.         success => inspect_keyvals;
  60.         default => final_response;
  61.     }
  62.  
  63.     state inspect_keyvals
  64.     {
  65.         run inspect_keyvals;
  66.         success => get_handles;
  67.         default => final_response;
  68.     }
  69.  
  70.     state get_handles
  71.     {
  72.         run get_handles;
  73.         default => set_handles_on_object;
  74.     }
  75.  
  76.     state set_handles_on_object
  77.     {
  78.         run set_handles_on_object;
  79.         success => update_dfile_count;
  80.         default => final_response;
  81.     }
  82.  
  83.     state update_dfile_count
  84.     {
  85.         run update_dfile_count;
  86.         success => remove_layout;
  87.         default => final_response;
  88.     }
  89.  
  90.     state remove_layout
  91.     {
  92.         run remove_layout;
  93.         default => final_response;
  94.     }
  95.  
  96.     state final_response
  97.     {
  98.         jump pvfs2_final_response_sm;
  99.         default => cleanup;
  100.     }
  101.  
  102.     state cleanup
  103.     {
  104.         run cleanup;
  105.         default => terminate;
  106.     }
  107. }
  108.  
  109. %%
  110.  
  111. static PINT_sm_action get_keyvals(
  112.         struct PINT_smcb *smcb, job_status_s *js_p)
  113. {
  114.     struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  115.     int kind = 0;
  116.     int ret;
  117.     job_id_t job_id;
  118.  
  119.     s_op->keyval_count = 2;
  120.     s_op->key_a = malloc(sizeof(*s_op->key_a) * s_op->keyval_count);
  121.     if(!s_op->key_a)
  122.     {
  123.         js_p->error_code = -PVFS_ENOMEM;
  124.         goto error_exit;
  125.     }
  126.  
  127.     s_op->val_a = malloc(sizeof(*s_op->val_a) * s_op->keyval_count);
  128.     if(!s_op->val_a)
  129.     {
  130.         js_p->error_code = -PVFS_ENOMEM;
  131.         goto free_key_array;
  132.     }
  133.  
  134.     s_op->error_a = malloc(sizeof(*s_op->error_a) * s_op->keyval_count);
  135.     if(!s_op->error_a)
  136.     {
  137.         js_p->error_code = -PVFS_ENOMEM;
  138.         goto free_val_array;
  139.     }
  140.     memset(s_op->error_a, 0, sizeof(*s_op->error_a) * s_op->keyval_count);
  141.  
  142.     s_op->u.unstuff.encoded_layout = malloc(PVFS_REQ_LIMIT_LAYOUT);
  143.     if(!s_op->u.unstuff.encoded_layout)
  144.     {
  145.         js_p->error_code = -PVFS_ENOMEM;
  146.         goto free_encoded_layout;
  147.     }
  148.     memset(s_op->u.unstuff.encoded_layout, 0, PVFS_REQ_LIMIT_LAYOUT);
  149.  
  150.     /* kind = 0 */
  151.     s_op->key_a[kind].buffer = Trove_Common_Keys[METAFILE_LAYOUT_KEY].key;
  152.     s_op->key_a[kind].buffer_sz = Trove_Common_Keys[METAFILE_LAYOUT_KEY].size;
  153.  
  154.     s_op->val_a[kind].buffer = s_op->u.unstuff.encoded_layout;
  155.     s_op->val_a[kind].buffer_sz = PVFS_REQ_LIMIT_LAYOUT;
  156.  
  157.     ++kind;
  158.     /* kind = 1 */
  159.     s_op->key_a[kind].buffer = Trove_Common_Keys[NUM_DFILES_REQ_KEY].key;
  160.     s_op->key_a[kind].buffer_sz = Trove_Common_Keys[NUM_DFILES_REQ_KEY].size;
  161.  
  162.     s_op->val_a[kind].buffer = &s_op->u.unstuff.num_dfiles_req;
  163.     s_op->val_a[kind].buffer_sz = sizeof(s_op->u.unstuff.num_dfiles_req);
  164.  
  165.     ret = job_trove_keyval_read_list(
  166.         s_op->req->u.unstuff.fs_id,
  167.         s_op->req->u.unstuff.handle,
  168.         s_op->key_a, s_op->val_a, s_op->error_a, s_op->keyval_count,
  169.         0, NULL, smcb, 0, js_p, &job_id, server_job_context,
  170.         s_op->req->hints);
  171.     return ret;
  172.  
  173. free_encoded_layout:
  174.     free(s_op->u.unstuff.encoded_layout);
  175.     s_op->u.unstuff.encoded_layout = NULL;
  176. free_val_array:
  177.     free(s_op->val_a);
  178.     s_op->val_a = NULL;
  179. free_key_array:
  180.     free(s_op->key_a);
  181.     s_op->key_a = NULL;
  182. error_exit:
  183.     return SM_ACTION_COMPLETE;
  184. }
  185.  
  186. static PINT_sm_action inspect_keyvals(
  187.         struct PINT_smcb *smcb, job_status_s *js_p)
  188. {
  189.     struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  190.     char* tmpbuf;
  191.  
  192.     if(js_p->error_code == 0)
  193.     {
  194.         /* check keys; we have a big problem if one of them is missing */
  195.         if(s_op->error_a[0])
  196.         {
  197.             js_p->error_code = s_op->error_a[0];
  198.         }
  199.         else if(s_op->error_a[1])
  200.         {
  201.             js_p->error_code = s_op->error_a[1];
  202.         }
  203.  
  204.         if(js_p->error_code == 0)
  205.         {
  206.         
  207.             /* sanity check num dfiles */
  208.             if(s_op->u.unstuff.num_dfiles_req < 1)
  209.             {
  210.                 js_p->error_code = -PVFS_EINVAL;
  211.             }
  212.  
  213.             /* decode layout information */
  214.             tmpbuf = s_op->u.unstuff.encoded_layout;
  215.             decode_PVFS_sys_layout(&tmpbuf, &s_op->u.unstuff.layout);
  216.         }
  217.     }
  218.  
  219.     /* pass along error code for next state to handle */
  220.     return SM_ACTION_COMPLETE;
  221. }
  222.  
  223. static PINT_sm_action get_handles(
  224.         struct PINT_smcb *smcb, job_status_s *js_p)
  225. {
  226.     int ret;
  227.     job_id_t j_id;
  228.     struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  229.  
  230.     if(s_op->u.unstuff.layout.algorithm != PVFS_SYS_LAYOUT_ROUND_ROBIN)
  231.     {
  232.         /* see create.sm; for now the only layout that we use stuffing on is
  233.          * ROUND_ROBIN.  The storage format supports other layouts if we
  234.          * want to add support for others later
  235.          */
  236.         gossip_err("Error: unstuff doesn't support layout algorithm: %d\n", 
  237.             s_op->u.unstuff.layout.algorithm);
  238.         js_p->error_code = -PVFS_ENOSYS;
  239.         return SM_ACTION_COMPLETE;
  240.     }
  241.  
  242.     /* allocate room for final number of handles we want */
  243.     s_op->u.unstuff.dfile_array = 
  244.         malloc(s_op->u.unstuff.num_dfiles_req * sizeof(PVFS_handle));
  245.     if(!s_op->u.unstuff.dfile_array)
  246.     {
  247.         js_p->error_code = -PVFS_ENOMEM;
  248.         return SM_ACTION_COMPLETE;
  249.     }
  250.  
  251.     /* the very first handle should be our current stuffed handle */
  252.     s_op->u.unstuff.dfile_array[0] 
  253.         = s_op->resp.u.unstuff.attr.u.meta.dfile_array[0];
  254.  
  255.     if(s_op->u.unstuff.num_dfiles_req == 1)
  256.     {
  257.         /* special case; we are unstuffing to 1 datafile.  There is no need
  258.          * to retrieve any additional handles
  259.          */
  260.         js_p->error_code = 0;
  261.         return SM_ACTION_COMPLETE;
  262.     }
  263.  
  264.     /* NOTE: we are leaving the existing resp attr structure alone until we
  265.      * get a successful answer from get_handles() and commit to disk
  266.      */
  267.     ret = job_precreate_pool_get_handles(
  268.         s_op->req->u.unstuff.fs_id,
  269.         (s_op->u.unstuff.num_dfiles_req-1),
  270.         PVFS_TYPE_DATAFILE,
  271.         NULL,
  272.         &s_op->u.unstuff.dfile_array[1],
  273.         0,
  274.         smcb,
  275.         0,
  276.         js_p,
  277.         &j_id,
  278.         server_job_context,
  279.         s_op->req->hints);
  280.     return ret;
  281. }
  282.  
  283. static PINT_sm_action set_handles_on_object(
  284.         struct PINT_smcb *smcb, job_status_s *js_p)
  285. {
  286.     struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  287.     job_id_t j_id;
  288.  
  289.     gossip_debug(GOSSIP_SERVER_DEBUG, "job_precreate_pool_get_handles() returned %d\n", js_p->error_code);
  290.  
  291.     if(js_p->error_code < 0)
  292.     {
  293.         /* we failed to retrieve any handles */
  294.         if(s_op->u.unstuff.dfile_array)
  295.         {
  296.             free(s_op->u.unstuff.dfile_array);
  297.             /* preserve error code */
  298.             return SM_ACTION_COMPLETE;
  299.         }
  300.     }
  301.  
  302.     /* replace dfile information in attr structure */
  303.     free(s_op->resp.u.unstuff.attr.u.meta.dfile_array);
  304.     s_op->resp.u.unstuff.attr.u.meta.dfile_array 
  305.         = s_op->u.unstuff.dfile_array;
  306.     s_op->resp.u.unstuff.attr.u.meta.dfile_count 
  307.         = s_op->u.unstuff.num_dfiles_req;
  308.  
  309.     /* write new datafile handles to disk */
  310.     s_op->key.buffer = Trove_Common_Keys[METAFILE_HANDLES_KEY].key;
  311.     s_op->key.buffer_sz = Trove_Common_Keys[METAFILE_HANDLES_KEY].size;
  312.  
  313.     s_op->val.buffer = 
  314.         s_op->resp.u.unstuff.attr.u.meta.dfile_array; 
  315.     s_op->val.buffer_sz =
  316.         s_op->resp.u.unstuff.attr.u.meta.dfile_count * sizeof(PVFS_handle);
  317.  
  318.     return job_trove_keyval_write(
  319.         s_op->req->u.unstuff.fs_id,
  320.         s_op->req->u.unstuff.handle,
  321.         &s_op->key,
  322.         &s_op->val,
  323.         0, NULL, smcb, 0, js_p, &j_id, server_job_context,
  324.         s_op->req->hints);
  325. }
  326.  
  327. static PINT_sm_action update_dfile_count(
  328.         struct PINT_smcb *smcb, job_status_s *js_p)
  329. {
  330.     struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  331.     job_id_t j_id;
  332.  
  333.     /* take the current on-disk attribute in object_attr form
  334.      * (acquired from prelude) with the modified datafile array,
  335.      * and convert it to the dspace form for writing.
  336.      */
  337.     PVFS_object_attr_to_ds_attr(&s_op->resp.u.unstuff.attr, &s_op->ds_attr);
  338.  
  339.     return job_trove_dspace_setattr(
  340.         s_op->req->u.unstuff.fs_id, s_op->req->u.unstuff.handle,
  341.         &s_op->ds_attr,
  342.         TROVE_SYNC,
  343.         smcb, 0, js_p, &j_id, server_job_context,
  344.         s_op->req->hints);
  345. }
  346.  
  347. static PINT_sm_action remove_layout(
  348.         struct PINT_smcb *smcb, job_status_s *js_p)
  349. {
  350.     struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  351.     job_id_t j_id;
  352.  
  353.     /* remove the layout and num_dfiles_req keyvals as the layout has
  354.      * now been chosen.
  355.      */
  356.     return job_trove_keyval_remove_list(
  357.         s_op->req->u.unstuff.fs_id, s_op->req->u.unstuff.handle,
  358.         s_op->key_a,
  359.         s_op->val_a,
  360.         s_op->error_a,
  361.         2,
  362.         TROVE_SYNC, NULL,
  363.         smcb, 0, js_p, &j_id, server_job_context,
  364.         s_op->req->hints);
  365. }
  366.  
  367. static PINT_sm_action cleanup(
  368.         struct PINT_smcb *smcb, job_status_s *js_p)
  369. {
  370.     struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  371.  
  372.     if(s_op->u.unstuff.layout.server_list.servers)
  373.     {
  374.         free(s_op->u.unstuff.layout.server_list.servers);
  375.     }
  376.     if(s_op->u.unstuff.encoded_layout)
  377.     {
  378.         free(s_op->u.unstuff.encoded_layout);
  379.     }
  380.     if(s_op->val_a)
  381.     {
  382.         free(s_op->val_a);
  383.     }
  384.     if(s_op->key_a)
  385.     {
  386.         free(s_op->key_a);
  387.     }
  388.     if(s_op->error_a)
  389.     {
  390.         free(s_op->error_a);
  391.     }
  392.  
  393.     PINT_free_object_attr(&s_op->resp.u.getattr.attr);
  394.     return (server_state_machine_complete(smcb));
  395. }
  396.  
  397. static PINT_sm_action getattr_setup(
  398.     struct PINT_smcb *smcb, job_status_s *js_p)
  399. {
  400.     struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  401.     struct PINT_server_op *getattr_op;
  402.     int ret;
  403.  
  404.     js_p->error_code = 0;
  405.  
  406.     getattr_op = malloc(sizeof(*getattr_op));
  407.     if(!getattr_op)
  408.     {
  409.         js_p->error_code = -PVFS_ENOMEM;
  410.         return SM_ACTION_COMPLETE;
  411.     }
  412.     memset(getattr_op, 0, sizeof(*getattr_op));
  413.  
  414.     /* TODO: can we come up with a way to clean up and nail down what has 
  415.      * to be set in order to run this nested machine?  This seems fragile.
  416.      */
  417.  
  418.     /* need attrs that the prelude read already */
  419.     getattr_op->attr = s_op->attr;
  420.     /* need a valid request structure for some generic features like access
  421.      * logging 
  422.      */
  423.     getattr_op->req = s_op->req;
  424.     /* need to fill in the input parameters to the getattr nested machine */
  425.     getattr_op->u.getattr.fs_id = s_op->req->u.unstuff.fs_id;
  426.     getattr_op->u.getattr.handle = s_op->req->u.unstuff.handle;
  427.     getattr_op->u.getattr.attrmask = s_op->req->u.unstuff.attrmask;
  428.  
  429.     ret = PINT_sm_push_frame(smcb, 0, getattr_op);
  430.     if(ret < 0)
  431.     {
  432.         js_p->error_code = ret;
  433.     }
  434.  
  435.     return SM_ACTION_COMPLETE;
  436. }
  437.  
  438. static PINT_sm_action getattr_interpret(
  439.     struct PINT_smcb *smcb, job_status_s *js_p)
  440. {
  441.     struct PINT_server_op *getattr_op;
  442.     struct PINT_server_op *s_op;
  443.     int task_id;
  444.     int remaining;
  445.  
  446.     getattr_op = PINT_sm_pop_frame(smcb, &task_id, &js_p->error_code, 
  447.         &remaining);
  448.     s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  449.  
  450.     s_op->resp.u.unstuff.attr = getattr_op->resp.u.getattr.attr;
  451.  
  452.     free(getattr_op);
  453.  
  454.     if(js_p->error_code)
  455.     {
  456.         gossip_debug(GOSSIP_SERVER_DEBUG,
  457.             "unstuff failed to retrieve existing attrs.\n");
  458.         return(SM_ACTION_COMPLETE);
  459.     }
  460.  
  461.     if(s_op->resp.u.unstuff.attr.mask & PVFS_ATTR_META_UNSTUFFED)
  462.     {
  463.         gossip_debug(GOSSIP_SERVER_DEBUG,
  464.             "unstuff found file already unstuffed; return existing attrs.\n");
  465.         js_p->error_code = 0;
  466.         return(SM_ACTION_COMPLETE);
  467.     }
  468.  
  469. /*
  470.   gossip_err("Attributes show file as stuffed.\n");
  471. */
  472.     gossip_debug(GOSSIP_SERVER_DEBUG,
  473.         "unstuff found stuffed file.\n");
  474.     js_p->error_code = STATE_UNSTUFF;
  475.     return SM_ACTION_COMPLETE;
  476. }
  477.  
  478.  
  479. PINT_GET_OBJECT_REF_DEFINE(unstuff);
  480.  
  481. struct PINT_server_req_params pvfs2_unstuff_params =
  482. {
  483.     .string_name = "unstuff",
  484.     .perm = PINT_SERVER_CHECK_ATTR,
  485.     .access_type = PINT_server_req_modify,
  486.     .sched_policy = PINT_SERVER_REQ_SCHEDULE,
  487.     .get_object_ref = PINT_get_object_ref_unstuff,
  488.     .state_machine = &pvfs2_unstuff_sm
  489. };
  490.  
  491. /*
  492.  * Local variables:
  493.  *  mode: c
  494.  *  c-indent-level: 4
  495.  *  c-basic-offset: 4
  496.  * End:
  497.  *
  498.  * vim: ft=c ts=8 sts=4 sw=4 expandtab
  499.  */
  500.  
  501.