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 / description / pvfs-request.c < prev    next >
C/C++ Source or Header  |  2006-05-28  |  16KB  |  494 lines

  1. /*
  2.  * (C) 2000 Clemson University, Scyld Computing Inc.,
  3.  *                 and The University of Chicago
  4.  * 
  5.  * See COPYING in top-level directory.
  6.  */
  7.  
  8. #include <stdlib.h>
  9. #include <stdio.h>
  10. #include <unistd.h>
  11. #include "string.h"
  12. #include "pvfs2-types.h"
  13. #include "pint-request.h"
  14. #include "pvfs2-request.h"
  15. #include "pvfs2-debug.h"
  16. #include "gossip.h"
  17.  
  18. #define PVFS_SUCCESS 0
  19. #define PVFS_ERR_REQ -1
  20.  
  21. /* elementary reqs */
  22.  
  23. static struct PINT_Request PINT_CHAR =
  24.     { 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, -1, NULL, NULL };
  25. PVFS_Request PVFS_CHAR = &PINT_CHAR;
  26.  
  27. static struct PINT_Request PINT_SHORT =
  28.     { 0, 1, 0, 1, 2, 0, 2, 1, 1, 0, 0, -1, NULL, NULL };
  29. PVFS_Request PVFS_SHORT = &PINT_SHORT;
  30.  
  31. static struct PINT_Request PINT_INT =
  32.     { 0, 1, 0, 1, 4, 0, 4, 1, 1, 0, 0, -1, NULL, NULL };
  33. PVFS_Request PVFS_INT = &PINT_INT;
  34.  
  35. static struct PINT_Request PINT_LONG =
  36.     { 0, 1, 0, 1, 4, 0, 4, 1, 1, 0, 0, -1, NULL, NULL };
  37. PVFS_Request PVFS_LONG = &PINT_LONG;
  38.  
  39. static struct PINT_Request PINT_UNSIGNED_CHAR =
  40.     { 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, -1, NULL, NULL };
  41. PVFS_Request PVFS_UNSIGNED_CHAR = &PINT_UNSIGNED_CHAR;
  42.  
  43. static struct PINT_Request PINT_UNSIGNED_SHORT =
  44.     { 0, 1, 0, 1, 2, 0, 2, 1, 1, 0, 0, -1, NULL, NULL };
  45. PVFS_Request PVFS_UNSIGNED_SHORT = &PINT_UNSIGNED_SHORT;
  46.  
  47. static struct PINT_Request PINT_UNSIGNED =
  48.     { 0, 1, 0, 1, 4, 0, 4, 1, 1, 0, 0, -1, NULL, NULL };
  49. PVFS_Request PVFS_UNSIGNED = &PINT_UNSIGNED;
  50.  
  51. static struct PINT_Request PINT_UNSIGNED_LONG =
  52.     { 0, 1, 0, 1, 4, 0, 4, 1, 1, 0, 0, -1, NULL, NULL };
  53. PVFS_Request PVFS_UNSIGNED_LONG = &PINT_UNSIGNED_LONG;
  54.  
  55. static struct PINT_Request PINT_FLOAT =
  56.     { 0, 1, 0, 1, 4, 0, 4, 1, 1, 0, 0, -1, NULL, NULL };
  57. PVFS_Request PVFS_FLOAT = &PINT_FLOAT;
  58.  
  59. static struct PINT_Request PINT_DOUBLE =
  60.     { 0, 1, 0, 1, 8, 0, 8, 1, 1, 0, 0, -1, NULL, NULL };
  61. PVFS_Request PVFS_DOUBLE = &PINT_DOUBLE;
  62.  
  63. static struct PINT_Request PINT_LONG_DOUBLE =
  64.     { 0, 1, 0, 1, 8, 0, 8, 1, 1, 0, 0, -1, NULL, NULL };
  65. PVFS_Request PVFS_LONG_DOUBLE = &PINT_LONG_DOUBLE;
  66.  
  67. static struct PINT_Request PINT_BYTE =
  68.     { 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, -1, NULL, NULL };
  69. PVFS_Request PVFS_BYTE = &PINT_BYTE;
  70.  
  71. static struct PINT_Request PINT_PACKED =
  72.     { 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, -1, NULL, NULL };
  73. PVFS_Request PVFS_PACKED = &PINT_PACKED;
  74.  
  75. static struct PINT_Request PINT_NULL =
  76.     { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, -1, NULL, NULL };
  77. PVFS_Request PVFS_NULL = &PINT_NULL;
  78.  
  79. /* int PVFS_Request_extent(PVFS_Request request, PVFS_size *extent); */
  80.  
  81. int PVFS_Request_contiguous(int32_t count,
  82.                             PVFS_Request oldreq,
  83.                             PVFS_Request * newreq)
  84. {
  85.     return PVFS_Request_hvector(1, count, 0, oldreq, newreq);
  86. }
  87.  
  88. int PVFS_Request_vector(int32_t count,
  89.                         int32_t blocklength,
  90.                         PVFS_offset stride,
  91.                         PVFS_Request oldreq,
  92.                         PVFS_Request * newreq)
  93. {
  94.     int64_t extent;
  95.     if (oldreq == NULL)
  96.         return PVFS_ERR_REQ;
  97.     PVFS_Request_extent(oldreq, &extent);
  98.     return PVFS_Request_hvector(count, blocklength, stride * extent,
  99.                                 oldreq, newreq);
  100. }
  101.  
  102. /*
  103.  * This function creates a record representing a strided set of
  104.  * blocks, each of which is a contiguous array of the old request.
  105.  *
  106.  * A request is considered contiguous if its num_contig_chunks is 1
  107.  * and its extent is equal to its aggregate_size. 
  108.  *
  109.  * The new request computes its num_contig_chunks by first seeing if
  110.  * the old request is contiguous, then seeing if the stride equals
  111.  * the extent times bsize or if the count is 1.
  112.  * In this case the new request is contiguous.
  113.  *
  114.  * Otherwise, we assume that the old num_contig_chunks must be
  115.  * multiplied by the bsize and count.  This may over estimate the
  116.  * number of chunks, as chunks at the end of a block may be adjacent
  117.  * to chunks at the beginning of the next block ... but for now
  118.  * we're going to err on the side of caution.
  119.  *
  120.  * WBL 3/3/05
  121.  */
  122.  
  123. static int PINT_subreq(PVFS_offset offset,
  124.                        int32_t bsize,
  125.                        PVFS_size stride,
  126.                        int32_t count,
  127.                        PVFS_Request oldreq,
  128.                        PVFS_size oldext,
  129.                        PVFS_Request * newreq)
  130. {
  131.     if (oldreq == NULL)
  132.         return PVFS_ERR_REQ;
  133.     (*newreq)->offset = offset;
  134.     (*newreq)->num_ereqs = bsize;
  135.     (*newreq)->stride = stride;
  136.     (*newreq)->num_blocks = count;
  137.     (*newreq)->ub = offset + ((count - 1) * stride) + (bsize * oldext);
  138.     (*newreq)->lb = offset;
  139.     (*newreq)->aggregate_size = oldreq->aggregate_size * count * bsize;
  140.     /* compute num_contig_chunks */
  141.     if (oldreq->aggregate_size == oldext && oldreq->num_contig_chunks == 1)
  142.         /* oldreq is contiguous */
  143.         if (count == 1 || stride == bsize * oldext || -stride == bsize * oldext)
  144.             /* newreq will be contiguous */
  145.             (*newreq)->num_contig_chunks = 1;
  146.         else
  147.             /* each block will be contiguous */
  148.             (*newreq)->num_contig_chunks = count;
  149.     else
  150.         /* nothing is contiguous */
  151.         (*newreq)->num_contig_chunks =
  152.             oldreq->num_contig_chunks * bsize * count;
  153.     (*newreq)->depth = oldreq->depth + 1;
  154.     (*newreq)->num_nested_req = oldreq->num_nested_req + 1;
  155.     (*newreq)->committed = 0;
  156.     (*newreq)->refcount = 0;
  157.     (*newreq)->ereq = oldreq;
  158.     PINT_REQUEST_REFINC(oldreq);
  159.     return PVFS_SUCCESS;
  160. }
  161.  
  162. int PVFS_Request_hvector(int32_t count,
  163.                          int32_t blocklength,
  164.                          PVFS_size stride,
  165.                          PVFS_Request oldreq,
  166.                          PVFS_Request * newreq)
  167. {
  168.     PVFS_size oldext;
  169.     if (oldreq == NULL)
  170.         return PVFS_ERR_REQ;
  171.     PVFS_Request_extent(oldreq, &oldext);
  172.     // PINT_REQUEST_REFINC(oldreq);
  173.     *newreq = (PINT_Request *) malloc(sizeof(struct PINT_Request));
  174.     (*newreq)->sreq = NULL;
  175.     PINT_subreq(0, blocklength, stride, count, oldreq, oldext, newreq);
  176.     /* calculate statistics like ub, lb, depth, etc. */
  177.     if (stride < 0)
  178.     {
  179.         (*newreq)->lb = (count - 1) * stride;
  180.     }
  181.     PINT_REQUEST_REFSET(*newreq);
  182.     return PVFS_SUCCESS;
  183. }
  184.  
  185. static int PINT_reqstats(PVFS_Request * newreq)
  186. {
  187.     /* calculate statistics like ub, lb, depth, etc. */
  188.     if ((*newreq)->sreq)
  189.     {
  190.         if ((*newreq)->lb > (*newreq)->sreq->lb)
  191.             (*newreq)->lb = (*newreq)->sreq->lb;
  192.         if ((*newreq)->ub < (*newreq)->sreq->ub)
  193.             (*newreq)->ub = (*newreq)->sreq->ub;
  194.         if ((*newreq)->depth < (*newreq)->sreq->depth)
  195.             (*newreq)->depth = (*newreq)->sreq->depth;
  196.         (*newreq)->aggregate_size = (*newreq)->aggregate_size +
  197.             (*newreq)->sreq->aggregate_size;
  198.         (*newreq)->num_contig_chunks = (*newreq)->num_contig_chunks +
  199.             (*newreq)->sreq->num_contig_chunks;
  200.         if ((*newreq)->sreq)
  201.         {
  202.             /* contribution of ereq handled in subreq */
  203.             (*newreq)->num_nested_req += (*newreq)->sreq->num_nested_req + 1;
  204.             /* this tries to deal with non-tree request graphs */
  205.             if ((*newreq)->ereq == (*newreq)->sreq->ereq)
  206.             {
  207.                 (*newreq)->num_nested_req -=
  208.                     (*newreq)->ereq->num_nested_req + 1;
  209.             }
  210.         }
  211.     }
  212.     return PVFS_SUCCESS;
  213. }
  214.  
  215. int PVFS_Request_indexed(int32_t count,
  216.                          int32_t * blocklengths,
  217.                          PVFS_size * displacements,
  218.                          PVFS_Request oldreq,
  219.                          PVFS_Request * newreq)
  220. {
  221.     PINT_Request *dt;
  222.     int64_t oldext;
  223.     *newreq = NULL;
  224.     if (oldreq == NULL)
  225.         return PVFS_ERR_REQ;
  226.     PVFS_Request_extent(oldreq, &oldext);
  227.     // PINT_REQUEST_REFINC(oldreq);
  228.     while (count--)
  229.     {
  230.         dt = *newreq;
  231.         *newreq = (PINT_Request *) malloc(sizeof(struct PINT_Request));
  232.         (*newreq)->sreq = dt;
  233.         PINT_subreq(displacements[count] * oldext, blocklengths[count],
  234.                     0, 1, oldreq, oldext, newreq);
  235.         PINT_reqstats(newreq);
  236.     }
  237.     PINT_REQUEST_REFSET(*newreq);
  238.     return PVFS_SUCCESS;
  239. }
  240.  
  241. static int PVFS_Request_indexed_block(int32_t count,
  242.                                int32_t blocklength,
  243.                                PVFS_size * displacements,
  244.                                PVFS_Request oldreq,
  245.                                PVFS_Request * newreq) __attribute__((unused));
  246. /* this is a stupid first approach, fix it later - WBL */
  247. static int PVFS_Request_indexed_block(int32_t count,
  248.                                int32_t blocklength,
  249.                                PVFS_size * displacements,
  250.                                PVFS_Request oldreq,
  251.                                PVFS_Request * newreq)
  252. {
  253.     int i;
  254.     int32_t *blocklengths;
  255.     blocklengths = alloca(count * sizeof(int32_t));
  256.     for (i = 0; i < count; i++)
  257.         blocklengths[i] = blocklength;
  258.     return PVFS_Request_indexed(count, blocklengths, displacements,
  259.                                 oldreq, newreq);
  260. }
  261.  
  262. int PVFS_Request_hindexed(int32_t count,
  263.                           int32_t * blocklengths,
  264.                           PVFS_size * displacements,
  265.                           PVFS_Request oldreq,
  266.                           PVFS_Request * newreq)
  267. {
  268.     PINT_Request *dt;
  269.     int64_t oldext;
  270.     *newreq = NULL;
  271.     if (oldreq == NULL)
  272.         return PVFS_ERR_REQ;
  273.     PVFS_Request_extent(oldreq, &oldext);
  274.     // PINT_REQUEST_REFINC(oldreq);
  275.     while (count--)
  276.     {
  277.         dt = *newreq;
  278.         *newreq = (PINT_Request *) malloc(sizeof(struct PINT_Request));
  279.         (*newreq)->sreq = dt;
  280.         PINT_subreq(displacements[count], blocklengths[count], 0, 1,
  281.                     oldreq, oldext, newreq);
  282.         PINT_reqstats(newreq);
  283.     }
  284.     PINT_REQUEST_REFSET(*newreq);
  285.     return PVFS_SUCCESS;
  286. }
  287.  
  288. int PVFS_Request_struct(int32_t count,
  289.                         int32_t * blocklengths,
  290.                         PVFS_size * displacements,
  291.                         PVFS_Request * oldreqs,
  292.                         PVFS_Request * newreq)
  293. {
  294.     PINT_Request *dt;
  295.     int64_t oldext;
  296.     *newreq = NULL;
  297.     if (oldreqs == NULL)
  298.         return PVFS_ERR_REQ;
  299.     while (count--)
  300.     {
  301.         if (oldreqs[count] == NULL)
  302.             return PVFS_ERR_REQ;
  303.         PVFS_Request_extent(oldreqs[count], &oldext);
  304.         dt = *newreq;
  305.         *newreq = (PINT_Request *) malloc(sizeof(struct PINT_Request));
  306.         (*newreq)->sreq = dt;
  307.         PINT_subreq(displacements[count], blocklengths[count],
  308.                     0, 1, oldreqs[count], oldext, newreq);
  309.         // PINT_REQUEST_REFINC(oldreqs[count]);
  310.         PINT_reqstats(newreq);
  311.     }
  312.     PINT_REQUEST_REFSET(*newreq);
  313.     return PVFS_SUCCESS;
  314. }
  315.  
  316. int PVFS_Request_resized(PVFS_Request oldreq,
  317.                          PVFS_offset lb,
  318.                          PVFS_size extent,
  319.                          PVFS_Request * newreq)
  320. {
  321.     int retval;
  322.     if (oldreq == NULL)
  323.         return PVFS_ERR_REQ;
  324.     if (oldreq->ereq && !oldreq->sreq &&
  325.         oldreq->offset == 0 && oldreq->num_ereqs == 1 &&
  326.         oldreq->num_blocks == 1 && oldreq->stride == 0)
  327.         /* existing resize record or useless vector - bypass it */
  328.         retval = PVFS_Request_hvector(1, 1, 0, oldreq->ereq, newreq);
  329.     else
  330.         retval = PVFS_Request_hvector(1, 1, 0, oldreq, newreq);
  331.     (*newreq)->lb = lb;
  332.     (*newreq)->ub = lb + extent;
  333.     return retval;
  334. }
  335.  
  336. int PVFS_Address(void *location,
  337.                  PVFS_offset * address)
  338. {
  339.     *address = (char *) location - (char *) PVFS_BOTTOM;
  340.     return PVFS_SUCCESS;
  341. }
  342.  
  343. int PVFS_Request_extent(PVFS_Request request,
  344.                         PVFS_size * extent)
  345. {
  346.     if (request == NULL)
  347.         return PVFS_ERR_REQ;
  348.     *extent = request->ub - request->lb;
  349.     return PVFS_SUCCESS;
  350. }
  351.  
  352. int PVFS_Request_size(PVFS_Request request,
  353.                       PVFS_size * size)
  354. {
  355.     if (request == NULL)
  356.         return PVFS_ERR_REQ;
  357.     *size = request->aggregate_size;
  358.     return PVFS_SUCCESS;
  359. }
  360.  
  361. int PVFS_Request_lb(PVFS_Request request,
  362.                     PVFS_size * displacement)
  363. {
  364.     if (request == NULL)
  365.         return PVFS_ERR_REQ;
  366.     *displacement = request->lb;
  367.     return PVFS_SUCCESS;
  368. }
  369.  
  370. int PVFS_Request_ub(PVFS_Request request,
  371.                     PVFS_size * displacement)
  372. {
  373.     if (request == NULL)
  374.         return PVFS_ERR_REQ;
  375.     *displacement = request->ub;
  376.     return PVFS_SUCCESS;
  377. }
  378.  
  379. /* This function will take the request that points to all the 
  380.  * contained types, separate out each of the types and then lay them out in a
  381.  * contiguous region of memory. A pointer to this contiguous region will
  382.  * then be passed back in the argument
  383.  */
  384. int PVFS_Request_commit(PVFS_Request * reqp)
  385. {
  386.     PVFS_Request region = NULL;
  387.     PVFS_Request req;
  388.  
  389.     /* check pointer to pointer */
  390.     if (reqp == NULL)
  391.     {
  392.         gossip_lerr("PVFS_Request_commit: NULL pointer argument\n");
  393.         return PVFS_ERR_REQ;
  394.     }
  395.  
  396.     req = *reqp;
  397.  
  398.     /* now check the pointer */
  399.     if (req == NULL)
  400.     {
  401.         gossip_lerr("PVFS_Request_commit: pointer to NULL pointer argument\n");
  402.         return PVFS_ERR_REQ;
  403.     }
  404.  
  405.     /* this is a committed request - can't re-commit */
  406.     if (PINT_REQUEST_IS_PACKED(req))
  407.     {
  408.         gossip_lerr("PVFS_Request_commit: pointer to commited request\n");
  409.         return PVFS_ERR_REQ;
  410.     }
  411.  
  412.     /* Allocate memory for contiguous region */
  413.     if (PINT_REQUEST_NEST_SIZE(req) > 0)
  414.     {
  415.         region = (PVFS_Request) malloc(PINT_REQUEST_PACK_SIZE(req));
  416.         if (region == NULL)
  417.         {
  418.             gossip_lerr("PVFS_Request_commit: Memory cannot be allocated\n");
  419.             return PVFS_ERR_REQ;
  420.         }
  421.         /* pack the request */
  422.         PINT_request_commit(region, req);
  423.     }
  424.     /* return the pointer to the memory region */
  425.     *reqp = region;
  426.     return PVFS_SUCCESS;
  427. }
  428.  
  429. int PVFS_Request_free(PVFS_Request * req)
  430. {
  431.     PVFS_Request reqp;
  432.     if (req == NULL)
  433.     {
  434.         gossip_lerr("PVFS_Request_free: NULL pointer argument\n");
  435.         return PVFS_ERR_REQ;
  436.     }
  437.     if (*req == NULL)
  438.     {
  439.         gossip_lerr("PVFS_Request_free: pointer to NULL pointer argument\n");
  440.         return PVFS_ERR_REQ;
  441.     }
  442.     if ((*req)->refcount <= 0)
  443.     {
  444.         /* if refcount is 0 then it has already been freed */
  445.         /* if less than 0 it should not be freed */
  446.         /* can't be sure if this is users's variable or not */
  447.         gossip_debug(GOSSIP_REQUEST_DEBUG, "don't free special request\n");
  448.         return PVFS_SUCCESS;
  449.     }
  450.     PINT_REQUEST_REFDEC(*req);
  451.     if ((*req)->refcount > 0)
  452.     {
  453.         /* not ready to free this yet */
  454.         *req = NULL;
  455.         gossip_debug(GOSSIP_REQUEST_DEBUG, "don't free referenced request\n");
  456.         return PVFS_SUCCESS;
  457.     }
  458.     if (PINT_REQUEST_IS_PACKED(*req))
  459.     {
  460.         /* these are contiguous and have no external refs */
  461.         free(*req);
  462.         *req = NULL;
  463.         gossip_debug(GOSSIP_REQUEST_DEBUG, "free packed request\n");
  464.         return PVFS_SUCCESS;
  465.     }
  466.     /* this deals with the sreq chain */
  467.     reqp = (*req)->sreq;
  468.     while (reqp)
  469.     {
  470.         PVFS_Request reqp_next;
  471.         PVFS_Request_free(&(reqp->ereq));
  472.         /* this is a little awkward but it works */
  473.         reqp_next = reqp->sreq;
  474.         free(reqp);
  475.         gossip_debug(GOSSIP_REQUEST_DEBUG, "free sreq linked request\n");
  476.         reqp = reqp_next;
  477.     }
  478.     /* now deal with the main struct */
  479.     PVFS_Request_free(&((*req)->ereq));
  480.     free(*req);
  481.     *req = NULL;
  482.     gossip_debug(GOSSIP_REQUEST_DEBUG, "free unpacked request\n");
  483.     return PVFS_SUCCESS;
  484. }
  485.  
  486. /*
  487.  * Local variables:
  488.  *  c-indent-level: 4
  489.  *  c-basic-offset: 4
  490.  * End:
  491.  *
  492.  * vim: ts=8 sts=4 sw=4 expandtab
  493.  */
  494.