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 / tree-communicate.sm < prev    next >
Text File  |  2010-12-15  |  28KB  |  759 lines

  1. /* 
  2.  * (C) 2008 Clemson University and The University of Chicago
  3.  *
  4.  * See COPYING in top-level directory.
  5.  */
  6.  
  7. /** \file
  8.  *  \ingroup sysint
  9.  *
  10.  *  PVFS2 system interface routines for creating files.
  11.  */
  12.  
  13. #include <string.h>
  14. #include <assert.h>
  15.  
  16. #include "server-config.h"
  17. #include "pvfs2-server.h"
  18. #include "pvfs2-attr.h"
  19.  
  20. #include "client-state-machine.h"
  21. #include "pvfs2-debug.h"
  22. #include "pvfs2-dist-simple-stripe.h"
  23. #include "job.h"
  24. #include "gossip.h"
  25. #include "str-utils.h"
  26. #include "pint-cached-config.h"
  27. #include "pint-distribution.h"
  28. #include "PINT-reqproto-encode.h"
  29. #include "pint-util.h"
  30. #include "pint-dist-utils.h"
  31. #include "ncache.h"
  32. #include "pvfs2-internal.h"
  33. #include "extent-utils.h"
  34.  
  35. #define    MAX_PARTITIONS    2
  36.  
  37. enum
  38. {
  39.     LOCAL_OPERATION = 2,
  40.     REMOTE_OPERATION = 3
  41. };
  42.  
  43. /* completion function prototypes */
  44. static int tree_get_file_size_comp_fn(
  45.     void *v_p, struct PVFS_server_resp *resp_p, int index);
  46.  
  47. %%
  48.  
  49. machine pvfs2_tree_remove_sm
  50. {
  51.     state tree_remove_do_work
  52.     {
  53.         jump pvfs2_tree_remove_work_sm;
  54.         default => tree_remove_final_response;
  55.     }
  56.  
  57.     state tree_remove_final_response
  58.     {
  59.         jump pvfs2_final_response_sm;
  60.         default => tree_remove_cleanup;
  61.     }
  62.  
  63.     state tree_remove_cleanup
  64.     {
  65.         run tree_remove_cleanup;
  66.         default => terminate;
  67.     }
  68. }
  69.  
  70. nested machine pvfs2_tree_remove_work_sm
  71. {
  72.     state tree_remove_work_do_work
  73.     {
  74.         pjmp tree_remove_setup
  75.         {
  76.             REMOTE_OPERATION => pvfs2_pjmp_call_msgpairarray_sm;
  77.             LOCAL_OPERATION => pvfs2_pjmp_remove_work_sm;
  78.         }
  79.         default => tree_remove_work_cleanup;
  80.     }
  81.  
  82.     state tree_remove_work_cleanup
  83.     {
  84.         run tree_remove_work_cleanup;
  85.         default => return;
  86.     }
  87. }
  88.  
  89. machine pvfs2_tree_get_file_size_sm
  90. {
  91.     state tree_get_file_size_do_work
  92.     {
  93.         jump pvfs2_tree_get_file_size_work_sm;
  94.         default => tree_get_file_size_final_response;
  95.     }
  96.  
  97.     state tree_get_file_size_final_response
  98.     {
  99.         jump pvfs2_final_response_sm;
  100.         default => tree_get_file_size_cleanup;
  101.     }
  102.  
  103.     state tree_get_file_size_cleanup
  104.     {
  105.         run tree_get_file_size_cleanup;
  106.         default => terminate;
  107.     }
  108. }
  109.  
  110. nested machine pvfs2_tree_get_file_size_work_sm
  111. {
  112.     state tree_get_file_size_work_do_work
  113.     {
  114.         pjmp tree_get_file_size_setup
  115.         {
  116.             REMOTE_OPERATION => pvfs2_pjmp_call_msgpairarray_sm;
  117.             LOCAL_OPERATION => pvfs2_pjmp_get_attr_with_prelude_sm;
  118.         }
  119.         default => tree_get_file_size_work_cleanup;
  120.     }
  121.  
  122.     state tree_get_file_size_work_cleanup
  123.     {
  124.         run tree_get_file_size_work_cleanup;
  125.         default => return;
  126.     }
  127. }
  128.  
  129. %%
  130.  
  131. static PINT_sm_action tree_communicate_partition_handles(struct PINT_smcb *smcb
  132.                                                         ,job_status_s *js_p
  133.                                                         ,int num_data_files
  134.                                                         ,PVFS_fs_id fs_id
  135.                                                         ,enum PVFS_server_op operation
  136.                                                         ,PVFS_handle *handle_array)
  137. {
  138.     struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  139.     struct PINT_server_op *tree_communicate_s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  140.     struct PVFS_server_req *this_req = s_op->req;
  141.     int num_partitions, num_files_per_server;
  142.     int i;
  143.     char server_name[1024];
  144.     struct server_configuration_s *server_config = get_server_config_struct();
  145.     int ret = -PVFS_EINVAL;
  146.     struct PVFS_server_req *req = NULL;
  147.  
  148.     s_op->u.tree_communicate.handle_array_local = calloc(
  149.         num_data_files, sizeof(*s_op->u.tree_communicate.handle_array_local));
  150.     s_op->u.tree_communicate.handle_array_remote = calloc(
  151.         num_data_files, sizeof(*s_op->u.tree_communicate.handle_array_remote));
  152.     s_op->u.tree_communicate.local_join_size = calloc(
  153.         num_data_files, sizeof(*s_op->u.tree_communicate.local_join_size));
  154.     s_op->u.tree_communicate.remote_join_size = calloc(
  155.         num_data_files, sizeof(*s_op->u.tree_communicate.remote_join_size));
  156.  
  157.     if (!s_op->u.tree_communicate.handle_array_local  ||
  158.         !s_op->u.tree_communicate.handle_array_remote ||
  159.         !s_op->u.tree_communicate.local_join_size     ||
  160.         !s_op->u.tree_communicate.remote_join_size)
  161.     {
  162.         js_p->error_code = -PVFS_ENOMEM;
  163.         return SM_ACTION_COMPLETE;
  164.     }
  165.  
  166.     /* Separate the handles into local and remote. */
  167.     for (i = 0; i < num_data_files; i++)
  168.     {
  169.         PINT_cached_config_get_server_name(server_name, 1024, handle_array[i], fs_id);
  170.         if (! strcmp(server_config->host_id, server_name)) /* this one is local */
  171.         {
  172.             gossip_debug(GOSSIP_SERVER_DEBUG,
  173.                      "tree_communicate_partition_handles: local handle = %llu\n",
  174.                      llu(handle_array[i]));
  175.             s_op->u.tree_communicate.handle_array_local[
  176.                  s_op->u.tree_communicate.handle_array_local_count] = handle_array[i];
  177.             s_op->u.tree_communicate.local_join_size[
  178.                  s_op->u.tree_communicate.handle_array_local_count] = i;
  179.             s_op->u.tree_communicate.handle_array_local_count++;
  180.         }
  181.         else
  182.         {
  183.             gossip_debug(GOSSIP_SERVER_DEBUG,
  184.                      "tree_communicate_partition_handles: remote handle = %llu\n",
  185.                      llu(handle_array[i]));
  186.             s_op->u.tree_communicate.handle_array_remote[
  187.                  s_op->u.tree_communicate.handle_array_remote_count] = handle_array[i];
  188.             s_op->u.tree_communicate.remote_join_size[
  189.                  s_op->u.tree_communicate.handle_array_remote_count] = i;
  190.             s_op->u.tree_communicate.handle_array_remote_count++;
  191.         }
  192.     }/*end for*/
  193.  
  194.     if (s_op->u.tree_communicate.handle_array_local_count > 0) {
  195.  
  196.        for (i=0; i<s_op->u.tree_communicate.handle_array_local_count; i++)
  197.        {
  198.         /* Create a stack frame for the local operation. */
  199.         s_op->num_pjmp_frames++;
  200.         js_p->error_code = LOCAL_OPERATION;
  201.  
  202.         PINT_CREATE_SUBORDINATE_SERVER_FRAME(smcb, tree_communicate_s_op,
  203.             s_op->u.tree_communicate.handle_array_local[i],
  204.             fs_id, js_p->error_code, req, LOCAL_OPERATION);
  205.  
  206.         switch (operation)
  207.         {
  208.             case PVFS_SERV_TREE_REMOVE:
  209.             {
  210.                 PINT_SERVREQ_REMOVE_FILL(
  211.                     *req,
  212.                     s_op->req->credentials,
  213.                     fs_id,
  214.                     s_op->u.tree_communicate.handle_array_local[i],
  215.                     s_op->req->hints);
  216.  
  217.                 break;
  218.             }
  219.  
  220.             case PVFS_SERV_TREE_GET_FILE_SIZE:
  221.             {
  222.                 PINT_SERVREQ_GETATTR_FILL(
  223.                     *req,
  224.                     s_op->req->credentials,
  225.                     fs_id,
  226.                     s_op->u.tree_communicate.handle_array_local[i],
  227.                     PVFS_ATTR_DATA_SIZE,
  228.                     s_op->req->hints);
  229.  
  230.                 /*this identifies which "local" frame is being populated.*/
  231.                 /* we need to store this int in a location not in the union.
  232.                  * it will be accessed as u.getattr in the state machine
  233.                  * so we can't rely on a value in u.tree_communicate here.
  234.                  * All we need is an int, I'm loathe to do a malloc instead of
  235.                  * just re-purposing one of the existing ints in the s_op. */
  236.                 tree_communicate_s_op->local_index = i;
  237.  
  238.                 break;
  239.             }
  240.  
  241.             default:
  242.                 break;
  243.         }/*end switch*/
  244.        }/*end for*/
  245.     }/*end if local*/
  246.  
  247.     if (s_op->u.tree_communicate.handle_array_remote_count > 0) {
  248.  
  249.       /* Decide how to divide the remote handles. If there are only a few (MAX_PARTITIONS or
  250.          fewer) then go ahead and send to each remaining server individually. */
  251.       if (s_op->u.tree_communicate.handle_array_remote_count > MAX_PARTITIONS)
  252.       {
  253.           num_partitions = MAX_PARTITIONS;
  254.           num_files_per_server = s_op->u.tree_communicate.handle_array_remote_count /
  255.                    MAX_PARTITIONS;
  256.           if (num_partitions * num_files_per_server <
  257.                    s_op->u.tree_communicate.handle_array_remote_count) {
  258.               num_files_per_server++;
  259.           }
  260.       }
  261.       else
  262.       {
  263.           num_partitions = s_op->u.tree_communicate.handle_array_remote_count;
  264.           num_files_per_server = 1;
  265.       }
  266.  
  267.     gossip_debug(GOSSIP_SERVER_DEBUG,
  268.         "tree_communicate_partition_handles: num_data_files = %d,"
  269.         " num_remote_handles = %d, "
  270.         "num_partitions = %d, num_files_per_server = %d\n"
  271.         ,num_data_files
  272.         ,s_op->u.tree_communicate.handle_array_remote_count
  273.         ,num_partitions 
  274.         ,num_files_per_server);
  275.  
  276.         /* We need to send tree-based messages to other servers */
  277.         js_p->error_code = REMOTE_OPERATION;
  278.         s_op->num_pjmp_frames++;
  279.  
  280.         /* Prepare the stack for pjmp. */
  281.         PINT_CREATE_SUBORDINATE_SERVER_FRAME(smcb, tree_communicate_s_op,
  282.            s_op->u.tree_communicate.handle_array_remote[0],
  283.            fs_id, js_p->error_code, req, REMOTE_OPERATION);
  284.  
  285.         /*store the number of partitions*/
  286.         s_op->u.tree_communicate.num_partitions = num_partitions;
  287.  
  288.         /*keep info in new op structure for later use*/
  289.         tree_communicate_s_op->resp = s_op->resp;
  290.         tree_communicate_s_op->u.tree_communicate = s_op->u.tree_communicate;
  291.        
  292.         ret = PINT_msgpairarray_init(&tree_communicate_s_op->msgarray_op
  293.                                     ,num_partitions);
  294.         if (ret)
  295.         {
  296.             gossip_lerr("tree_communicate: failed to allocate msgarray\n");
  297.             return -PVFS_ENOMEM;
  298.         }
  299.         /* Fill in the msgarray. */
  300.         for (i = 0; i < num_partitions; i++)
  301.         {
  302.             PINT_sm_msgpair_state *msg_p;
  303.             int num_data_files_for_this_server;
  304.  
  305.             /* Handle the case where the last partition has fewer files than the 
  306.              *other partitions. 
  307.             */
  308.             for (num_data_files_for_this_server = num_files_per_server;
  309.                  i*num_files_per_server + num_data_files_for_this_server >
  310.                  s_op->u.tree_communicate.handle_array_remote_count;
  311.                  num_data_files_for_this_server--)
  312.             {
  313.                 /* Do nothing; */ ;
  314.             }
  315.  
  316.             msg_p = &tree_communicate_s_op->msgarray_op.msgarray[i];
  317.  
  318.             switch (operation)
  319.             {
  320.                 case PVFS_SERV_TREE_REMOVE:
  321.                 {
  322.                     PINT_SERVREQ_TREE_REMOVE_FILL(
  323.                         msg_p->req,
  324.                         s_op->req->credentials,
  325.                         fs_id,
  326.                         num_data_files_for_this_server,
  327.                         &s_op->u.tree_communicate.handle_array_remote[i*num_files_per_server],
  328.                         s_op->req->hints);
  329.                     msg_p->comp_fn = NULL;
  330.                     break;
  331.                 }
  332.     
  333.                 case PVFS_SERV_TREE_GET_FILE_SIZE:
  334.                 {
  335.  
  336. /* TODO: Need to pass along hints. */
  337.                   PINT_SERVREQ_TREE_GET_FILE_SIZE_FILL(
  338.                       msg_p->req,
  339.                       s_op->req->credentials,
  340.                       fs_id,
  341.                       (i * num_files_per_server),
  342.                       num_data_files_for_this_server,
  343.                       &s_op->u.tree_communicate.handle_array_remote[i*num_files_per_server],
  344.                       this_req->u.tree_get_file_size.retry_msgpair_at_leaf,
  345.                       NULL);
  346.                   msg_p->comp_fn = tree_get_file_size_comp_fn;
  347.                   break;
  348.                 }
  349.  
  350.                 default:
  351.                     break;
  352.             }
  353.             msg_p->fs_id = fs_id;
  354.             msg_p->handle =
  355.             s_op->u.tree_communicate.handle_array_remote[i*num_files_per_server];
  356.  
  357.             /* if the logical file is mirrored, then we want the mirroring logic
  358.              * to handle retries, when we are processing the leaf of the tree, 
  359.              * i.e., this tree request contains msgpairs having only one handle
  360.              * each. Otherwise, we let msgpairarray handle retries.
  361.             */
  362.             if ( (this_req->u.tree_get_file_size.retry_msgpair_at_leaf) && 
  363.                  (num_files_per_server == 1))
  364.             {
  365.                 gossip_debug(GOSSIP_SERVER_DEBUG,"%s:retry_flag:"
  366.                                                  "PVFS_MSGPAIR_NO_RETRY\n"
  367.                                                 ,__func__);
  368.                 msg_p->retry_flag = PVFS_MSGPAIR_NO_RETRY;
  369.             }
  370.             else
  371.             {
  372.                 gossip_debug(GOSSIP_SERVER_DEBUG,"%s:retry_flag:"
  373.                                                  "PVFS_MSGPAIR_RETRY\n"
  374.                                                 ,__func__);
  375.                 msg_p->retry_flag = PVFS_MSGPAIR_RETRY; 
  376.             }
  377.  
  378.             ret = PINT_cached_config_map_to_server(&msg_p->svr_addr
  379.                                                   ,msg_p->handle
  380.                                                   ,msg_p->fs_id);
  381.             if (ret)
  382.             {
  383.                 gossip_err("Failed to map server address\n");
  384.             }
  385.         }/*end for*/
  386.     }/*end if remote*/
  387.  
  388.     js_p->error_code = 0;
  389.     return SM_ACTION_COMPLETE;
  390. }
  391.  
  392. static PINT_sm_action tree_remove_setup(struct PINT_smcb *smcb, job_status_s *js_p)
  393. {
  394.     struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  395.  
  396.     assert(s_op->req->op == PVFS_SERV_TREE_REMOVE);
  397.  
  398.     return (tree_communicate_partition_handles(smcb, js_p, s_op->req->u.tree_remove.num_data_files,
  399.         s_op->req->u.tree_remove.fs_id, PVFS_SERV_TREE_REMOVE,
  400.         s_op->req->u.tree_remove.handle_array));
  401. }
  402.  
  403. static int tree_remove_work_cleanup(
  404.         struct PINT_smcb *smcb, job_status_s *js_p)
  405. {
  406.     /* get frame from bottom of stack */
  407.     PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  408.     int i, task_id, error_code;
  409.     PINT_server_op *old_frame;
  410.     int return_error_code;
  411.  
  412.     if (js_p->error_code)
  413.     {
  414.         return_error_code = js_p->error_code;
  415.     }
  416.     else
  417.     {
  418.         return_error_code = 0;
  419.     }
  420.  
  421.     assert(s_op->req->op == PVFS_SERV_TREE_REMOVE);
  422.  
  423.     /* for each state machine spawned, pop a frame */
  424.     for (i = 0; i < s_op->num_pjmp_frames; i++)
  425.     {
  426.         old_frame = PINT_sm_pop_frame(smcb, &task_id, &error_code, NULL);
  427.         if (task_id == REMOTE_OPERATION) {
  428.            PINT_msgpairarray_destroy(&old_frame->msgarray_op);
  429.         }
  430.  
  431.         gossip_debug(GOSSIP_SERVER_DEBUG,"%s:frame #%d \ttype:%s \terror_code:%d\n"
  432.                                         ,__func__
  433.                                         ,i
  434.                                         ,(task_id==LOCAL_OPERATION ? "LOCAL" : "REMOTE")
  435.                                         ,error_code);
  436.         /*retain first error encountered.*/
  437.         if (error_code && !return_error_code)
  438.             return_error_code = error_code;
  439.  
  440.         free(old_frame);
  441.     }
  442.  
  443.     /*deallocate resources*/
  444.     if (s_op->u.tree_communicate.handle_array_local)
  445.        free(s_op->u.tree_communicate.handle_array_local);
  446.     if (s_op->u.tree_communicate.handle_array_remote)
  447.        free(s_op->u.tree_communicate.handle_array_remote);
  448.     if (s_op->u.tree_communicate.local_join_size)
  449.        free(s_op->u.tree_communicate.local_join_size);
  450.     if (s_op->u.tree_communicate.remote_join_size)
  451.        free(s_op->u.tree_communicate.remote_join_size);
  452.     s_op->u.tree_communicate.handle_array_local  = NULL;
  453.     s_op->u.tree_communicate.handle_array_remote = NULL;
  454.     s_op->u.tree_communicate.local_join_size     = NULL;
  455.     s_op->u.tree_communicate.remote_join_size    = NULL;
  456.  
  457.     js_p->error_code = return_error_code;
  458.     return SM_ACTION_COMPLETE;
  459. }
  460.  
  461. static int tree_remove_cleanup(
  462.         struct PINT_smcb *smcb, job_status_s *js_p)
  463. {
  464.     return(server_state_machine_complete(smcb));
  465. }
  466.  
  467. static PINT_sm_action tree_get_file_size_setup(struct PINT_smcb *smcb, job_status_s *js_p)
  468. {
  469.     struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  470.     struct PVFS_server_req *req = s_op->req;
  471.  
  472.     assert(s_op->req->op == PVFS_SERV_TREE_GET_FILE_SIZE);
  473.  
  474.     gossip_debug(GOSSIP_SERVER_DEBUG,"%s:req->retry_msgpair_at_leaf:%s\n"
  475.                 ,__func__
  476.                 ,(req->u.tree_get_file_size.retry_msgpair_at_leaf ? "YES" : "NO"));
  477.  
  478.     s_op->resp.u.tree_get_file_size.caller_handle_index =
  479.             s_op->req->u.tree_get_file_size.caller_handle_index;
  480.     s_op->resp.u.tree_get_file_size.handle_count =
  481.             s_op->req->u.tree_get_file_size.num_data_files;
  482.  
  483.     gossip_debug(GOSSIP_SERVER_DEBUG,"%s: frame:%p \ttree.caller_handle_index:%d\n"
  484.                                      "\t\ttree.handle_count:%d "
  485.                                      "\ttree.op:%d\n"
  486.                                     ,__func__
  487.                                     ,s_op
  488.                                     ,s_op->resp.u.tree_get_file_size.caller_handle_index
  489.                                     ,s_op->resp.u.tree_get_file_size.handle_count
  490.                                     ,s_op->resp.op);
  491.  
  492.     /* allocate response arrays */
  493.     s_op->resp.u.tree_get_file_size.error = (PVFS_error *)
  494.         calloc(s_op->req->u.tree_get_file_size.num_data_files, sizeof(PVFS_error));
  495.     s_op->resp.u.tree_get_file_size.size = (PVFS_size *)
  496.         calloc(s_op->req->u.tree_get_file_size.num_data_files, sizeof(PVFS_size));
  497.     if (! s_op->resp.u.tree_get_file_size.error ||
  498.         ! s_op->resp.u.tree_get_file_size.size)
  499.     {
  500.         gossip_err("tree_get_file_size: failed to allocate arrays\n");
  501.         js_p->error_code = -PVFS_ENOMEM;
  502.         return SM_ACTION_COMPLETE;
  503.     }
  504.  
  505.     return (tree_communicate_partition_handles(smcb, js_p,
  506.         s_op->req->u.tree_get_file_size.num_data_files,
  507.         s_op->req->u.tree_get_file_size.fs_id, PVFS_SERV_TREE_GET_FILE_SIZE,
  508.         s_op->req->u.tree_get_file_size.handle_array));
  509. }
  510.  
  511. static int tree_get_file_size_comp_fn(
  512.     void *v_p, struct PVFS_server_resp *resp_p, int index)
  513. {
  514.     PINT_smcb *smcb = v_p;
  515.     PINT_server_op *s_op = PINT_sm_frame(smcb, (PINT_MSGPAIR_PARENT_SM));
  516.     struct PVFS_server_resp *op_resp = &(s_op->resp); /*op resp structure*/
  517.     struct PVFS_server_resp *m_resp = resp_p;         /*msgpair resp structure*/
  518.     struct PVFS_servresp_tree_get_file_size *op_tree = &(op_resp->u.tree_get_file_size);
  519.     struct PVFS_servresp_tree_get_file_size *m_tree  = &(m_resp->u.tree_get_file_size);
  520.     struct PINT_server_tree_communicate_op *s_tree_comm = &(s_op->u.tree_communicate); 
  521.     int i;
  522.     uint32_t size_array_index=0,
  523.              error_array_index=0;
  524.  
  525.     gossip_debug(GOSSIP_SERVER_DEBUG,
  526.                  "tree_get_file_size_comp_fn[%d], caller_handle_index = %d\n",
  527.                  index, resp_p->u.tree_get_file_size.caller_handle_index);
  528.  
  529.     assert(m_resp->op == PVFS_SERV_TREE_GET_FILE_SIZE);
  530.  
  531.     if (m_resp->status != 0)
  532.     {
  533.         PVFS_perror_gossip("Get file size failure", m_resp->status);
  534.         return resp_p->status;
  535.     }
  536.  
  537.     /* stash the sizes and error codes for each file handle */
  538.     gossip_debug(GOSSIP_SERVER_DEBUG,"%s: m_resp->u.tree_get_file_size.handle_count"
  539.                                      " is %d\n"
  540.                                     ,__func__
  541.                                     ,m_resp->u.tree_get_file_size.handle_count);
  542.  
  543.     for (i = 0; i < m_tree->handle_count; i++)
  544.     {
  545.         gossip_debug(GOSSIP_SERVER_DEBUG,"%s: size of datafile[%d] is %lld\n"
  546.                                         ,__func__
  547.                                         ,i
  548.                                         ,lld(m_tree->size[i]));
  549.         gossip_debug(GOSSIP_SERVER_DEBUG,"%s: caller_handle_index:%d "
  550.                                          "\tarray_local_count:%d\n"
  551.                                         ,__func__
  552.                                         ,m_tree->caller_handle_index
  553.                                         ,s_tree_comm->handle_array_local_count);
  554.         gossip_debug(GOSSIP_SERVER_DEBUG,"%s: error code for datafile %d is %d\n"
  555.                                         ,__func__
  556.                                         ,i
  557.                                         ,m_tree->error[i]);
  558.  
  559.         size_array_index = s_op->u.tree_communicate.remote_join_size[ i +
  560.                               resp_p->u.tree_get_file_size.caller_handle_index];
  561.         error_array_index = size_array_index;
  562.  
  563.         op_tree->size[size_array_index]   = m_tree->size[i];
  564.  
  565.         op_tree->error[error_array_index] = m_tree->error[i];
  566.     }
  567.  
  568.     return 0;
  569. }
  570.  
  571. static int tree_get_file_size_work_cleanup(
  572.         struct PINT_smcb *smcb, job_status_s *js_p)
  573. {
  574.     /* get frame from bottom of stack */
  575.     PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  576.     struct PVFS_servresp_tree_get_file_size *s_tree = &(s_op->resp.u.tree_get_file_size);
  577.     int i, j, k, task_id, error_code;
  578.     uint32_t size_array_index=0, error_array_index=0;
  579.     PINT_server_op *old_frame;
  580.     struct PVFS_servresp_tree_get_file_size *tree_resp = NULL;
  581.     struct PVFS_servreq_tree_get_file_size *tree_req = NULL;
  582.     PINT_sm_msgpair_state *tree_msgarray = NULL;
  583.     PINT_sm_msgarray_op *tree_msgop = NULL;
  584.     struct PINT_server_tree_communicate_op *s_tree_comm = &(s_op->u.tree_communicate); 
  585.  
  586.  
  587.     assert(s_op->req->op == PVFS_SERV_TREE_GET_FILE_SIZE);
  588.     gossip_debug(GOSSIP_SERVER_DEBUG,
  589.                  "%s: num_pjmp_frames = %d\n"
  590.                 ,__func__
  591.                 ,s_op->num_pjmp_frames);
  592.  
  593.     /* for each state machine spawned, pop a frame */
  594.     for (i = 0; i < s_op->num_pjmp_frames; i++)
  595.     {
  596.         old_frame = PINT_sm_pop_frame(smcb, &task_id, &error_code, NULL);
  597.         if (old_frame)
  598.         {  /* response from sub-tree request */
  599.            tree_resp = &(old_frame->resp.u.tree_get_file_size);
  600.  
  601.            /* sub-tree msgpair array*/
  602.            tree_msgarray  = old_frame->msgarray_op.msgarray;
  603.  
  604.            /* sub-tree msgop structure */
  605.            tree_msgop = &(old_frame->msgarray_op);
  606.         }
  607.  
  608.         gossip_debug(GOSSIP_SERVER_DEBUG,"%s: Value of task_id is %d\n"
  609.                                         ,__func__,task_id);
  610.         gossip_debug(GOSSIP_SERVER_DEBUG
  611.                     ,"%s: Value of handle_count is %d\n"
  612.                     ,__func__
  613.                     ,old_frame->resp.u.tree_get_file_size.handle_count);
  614.         gossip_debug(GOSSIP_SERVER_DEBUG
  615.                      ,"%s: Value of error_code is %d\n"
  616.                      ,__func__
  617.                      ,error_code);
  618.  
  619.         if (task_id == REMOTE_OPERATION) 
  620.         {
  621.             if (error_code != 0)
  622.             { /*sub-tree request failed; all handles identified in each msgpair 
  623.                *must be retried.  response structure is invalid; use request.
  624.               */
  625.               gossip_debug(GOSSIP_SERVER_DEBUG
  626.                           ,"%s: REMOTE OPERATION encountered error:%d\n"
  627.                           ,__func__
  628.                           ,error_code);
  629.               for (j=0; j < tree_msgop->count; j++)
  630.               {
  631.                  tree_req = &(tree_msgarray[j].req.u.tree_get_file_size);
  632.                  uint32_t index = 0;
  633.                  for (k=0; k < tree_req->num_data_files; k++)
  634.                  {
  635.                     index = tree_req->caller_handle_index 
  636.                             + k
  637.                             + s_op->u.tree_communicate.handle_array_local_count;
  638.                     s_op->resp.u.tree_get_file_size.size[index]  = 0;
  639.                     s_op->resp.u.tree_get_file_size.error[index] = error_code;
  640.                     gossip_err("%s:index:%d \terror[%d]:%d\n"
  641.                               ,__func__
  642.                               ,index
  643.                               ,index
  644.                               ,s_op->resp.u.tree_get_file_size.error[index]);
  645.                  }/*end for*/
  646.               }/*end for*/
  647.             }/*end if non-zero error-code*/
  648.  
  649.             PINT_msgpairarray_destroy(&old_frame->msgarray_op);
  650.         }
  651.         else { /* LOCAL OPERATION */
  652.             gossip_debug(GOSSIP_SERVER_DEBUG,
  653.                          "%s: size of local datafile is %lld\n"
  654.                          ,__func__
  655.                          ,lld(old_frame->resp.u.getattr.attr.u.data.size));
  656.             gossip_debug(GOSSIP_SERVER_DEBUG,"%s:handle_index:%d\n"
  657.                                             ,__func__
  658.                                             ,old_frame->local_index);
  659.             size_array_index = s_op->u.tree_communicate.local_join_size[
  660.                                      old_frame->local_index];
  661.             error_array_index=size_array_index;
  662.             s_op->resp.u.tree_get_file_size.size[size_array_index]   = old_frame->resp.u.getattr.attr.u.data.size;
  663.             s_op->resp.u.tree_get_file_size.error[error_array_index] = error_code;
  664.         }
  665.         free(old_frame);
  666.     }/*end for*/
  667.  
  668.     for (i=0; i<s_tree->handle_count; i++)
  669.     {
  670.         gossip_debug(GOSSIP_SERVER_DEBUG,"%s: resp->size[%d]:%u "
  671.                                          "\tresp->error[%d]:%d\n"
  672.                                         ,__func__
  673.                                         ,i
  674.                                         ,(unsigned int)s_tree->size[i]
  675.                                         ,i
  676.                                         ,s_tree->error[i]);
  677.     }
  678.  
  679.     gossip_debug(GOSSIP_SERVER_DEBUG,"%s: Resp op:%d \tResp status:%d\n"
  680.                                     ,__func__
  681.                                     ,s_op->resp.op
  682.                                     ,s_op->resp.status);
  683.     gossip_debug(GOSSIP_SERVER_DEBUG,"%s: s_op->addr:%d\n"
  684.                                     ,__func__
  685.                                     ,(int)s_op->addr);
  686.     gossip_debug(GOSSIP_SERVER_DEBUG,"%s: resp->caller_handle_index:%d "
  687.                                      "\tresp->handle_count:%d\n"
  688.                                     ,__func__
  689.                                     ,s_tree->caller_handle_index
  690.                                     ,s_tree->handle_count);
  691.  
  692.     /*cleanup tree-communicate structure*/
  693.     if (s_tree_comm->handle_array_local)
  694.        free(s_tree_comm->handle_array_local);
  695.     if (s_tree_comm->handle_array_remote)
  696.        free(s_tree_comm->handle_array_remote);
  697.     if (s_tree_comm->local_join_size)
  698.        free(s_tree_comm->local_join_size);
  699.     if (s_tree_comm->remote_join_size)
  700.        free(s_tree_comm->remote_join_size);
  701.     s_tree_comm->handle_array_local  = NULL;
  702.     s_tree_comm->handle_array_remote = NULL;
  703.     s_tree_comm->local_join_size     = NULL;
  704.     s_tree_comm->remote_join_size    = NULL;
  705.  
  706.     js_p->error_code = 0;
  707.     return SM_ACTION_COMPLETE;
  708. }/*end tree_get_file_size_work_cleanup*/
  709.  
  710. static int tree_get_file_size_cleanup(
  711.         struct PINT_smcb *smcb, job_status_s *js_p)
  712. {
  713.    PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  714.    struct PVFS_servresp_tree_get_file_size *s_tree = &(s_op->resp.u.tree_get_file_size);
  715.  
  716.    /*cleanup response structure*/
  717.    if (s_tree->size)
  718.       free(s_tree->size);
  719.    if (s_tree->error)
  720.       free(s_tree->error);
  721.     
  722.    return(server_state_machine_complete(smcb));
  723. }
  724.  
  725. static inline int PINT_get_object_ref_tree_remove(
  726.     struct PVFS_server_req *req, PVFS_fs_id *fs_id, PVFS_handle *handle)
  727. {
  728.     *fs_id = req->u.tree_remove.fs_id;
  729.     *handle = PVFS_HANDLE_NULL;
  730.     return 0;
  731. };
  732.  
  733. struct PINT_server_req_params pvfs2_tree_remove_params =
  734. {
  735.     .string_name = "tree_remove",
  736.     .get_object_ref = PINT_get_object_ref_tree_remove,
  737.     .perm = PINT_SERVER_CHECK_NONE,
  738.     .access_type = PINT_server_req_modify,
  739.     .state_machine = &pvfs2_tree_remove_sm
  740. };
  741.  
  742. static inline int PINT_get_object_ref_tree_get_file_size(
  743.     struct PVFS_server_req *req, PVFS_fs_id *fs_id, PVFS_handle *handle)
  744. {
  745.     *fs_id = req->u.tree_get_file_size.fs_id;
  746.     *handle = PVFS_HANDLE_NULL;
  747.     return 0;
  748. };
  749.  
  750. struct PINT_server_req_params pvfs2_tree_get_file_size_params =
  751. {
  752.     .string_name = "tree_get_file_size",
  753.     .get_object_ref = PINT_get_object_ref_tree_get_file_size,
  754.     .perm = PINT_SERVER_CHECK_NONE,
  755.     .access_type = PINT_server_req_readonly,
  756.     .state_machine = &pvfs2_tree_get_file_size_sm
  757. };
  758.  
  759.