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 / test / io / bmi / pingpong.c < prev    next >
C/C++ Source or Header  |  2010-09-28  |  29KB  |  765 lines

  1. /*
  2.  * (C) 2001 Clemson University and The University of Chicago
  3.  *
  4.  * See COPYING in top-level directory.
  5.  */
  6.  
  7.  
  8.  
  9.  
  10. /*
  11.  * This is an example of a server program that uses the BMI 
  12.  * library for communications
  13.  */
  14.  
  15. #include <stdio.h>
  16. #include <errno.h>
  17. #include <unistd.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <netinet/in.h>
  21. #include <sys/time.h>
  22. #include <time.h>
  23. #include <math.h>
  24.  
  25. #include "pvfs2.h"
  26. #include "bmi.h"
  27. #include "gossip.h"
  28. #include "test-bmi.h"
  29. #include <src/common/misc/pvfs2-internal.h>  /* lld(), llu() */
  30.  
  31. #include "pvfs2-test-config.h"
  32.  
  33. #ifdef HAVE_ZLIB_H
  34. #include <zlib.h>
  35. #endif
  36.  
  37. /**************************************************************
  38.  * Data structures 
  39.  */
  40.  
  41. #define SERVER          1
  42. #define CLIENT          2
  43. #define MIN_BYTES       1
  44. #define MAX_BYTES       (4<<20)
  45.  
  46. #define RECV            0
  47. #define SEND            1
  48.  
  49. #define EXPECTED        0
  50. #define UNEXPECTED      1
  51.  
  52. #define ITERATIONS      10000
  53.  
  54. struct msg {
  55.         int test;
  56. };
  57.  
  58. /* A little structure to hold program options, either defaults or
  59.  * specified on the command line 
  60.  */
  61. struct options
  62. {
  63.         char *hostid;           /* host identifier */
  64.         char *method;
  65.         int  which;
  66.         int  test;
  67.         int  crc;
  68. };
  69.  
  70.  
  71. /**************************************************************
  72.  * Internal utility functions
  73.  */
  74.  
  75. static struct options *parse_args(int argc, char *argv[]);
  76. static int do_server(struct options *opts, bmi_context_id *context);
  77. static int do_client(struct options *opts, bmi_context_id *context);
  78.  
  79. static void print_usage(void)
  80. {
  81.         fprintf(stderr, "usage: pingpong -h HOST_URI -s|-c [-u] [-r]\n");
  82.         fprintf(stderr, "       where:\n");
  83.         fprintf(stderr, "       HOST_URI is tcp://host:port, mx://host:board:endpoint, etc\n");
  84.         fprintf(stderr, "       -s is server and -c is client\n");
  85.         fprintf(stderr, "       -u will use unexpected messages (pass to client only)\n");
  86.         fprintf(stderr, "       -r will calculate and verify checksums (adler32)\n");
  87.         return;
  88. }
  89.  
  90. /**************************************************************/
  91.  
  92. int main(int argc, char **argv)
  93. {
  94.         struct options                  *opts = NULL;
  95.         int                             ret = -1;
  96.         bmi_context_id                  context;
  97.  
  98.         /* grab any command line options */
  99.         opts = parse_args(argc, argv);
  100.         if (!opts) {
  101.                 print_usage();
  102.                 return (-1);
  103.         }
  104.  
  105.         /* set debugging stuff */
  106.         gossip_enable_stderr();
  107.         gossip_set_debug_mask(0, GOSSIP_BMI_DEBUG_ALL);
  108.  
  109.         /* initialize local interface (default options) */
  110.         if (opts->which == SERVER)
  111.             ret = BMI_initialize(opts->method, opts->hostid, BMI_INIT_SERVER);
  112.         else
  113.             ret = BMI_initialize(NULL, NULL, 0);
  114.  
  115.         if (ret < 0) {
  116.                 errno = -ret;
  117.                 perror("BMI_initialize");
  118.                 return (-1);
  119.         }
  120.  
  121.         ret = BMI_open_context(&context);
  122.         if (ret < 0) {
  123.                 errno = -ret;
  124.                 perror("BMI_open_context()");
  125.                 return (-1);
  126.         }
  127.  
  128.         if (opts->which == SERVER) {
  129.                 ret = do_server(opts, &context);
  130.         } else {
  131.                 ret = do_client(opts, &context);
  132.         }
  133.  
  134.         /* shutdown the local interface */
  135.         BMI_close_context(context);
  136.         ret = BMI_finalize();
  137.         if (ret < 0) {
  138.                 errno = -ret;
  139.                 perror("BMI_finalize");
  140.                 return (-1);
  141.         }
  142.  
  143.         /* turn off debugging stuff */
  144.         gossip_disable();
  145.  
  146.         return (0);
  147. }
  148.  
  149. static int bytes_to_iterations(int bytes)
  150. {
  151.         int     ret     = ITERATIONS;
  152.         if (bytes >= (128*1024)) ret = 5000;
  153.         if (bytes >= (256*1024)) ret = 2500;
  154.         if (bytes >= (1024*1024)) ret = 1000;
  155.         if (bytes >= (2*1024*1024)) ret = 500;
  156.         if (bytes >= (4*1024*1024)) ret = 250;
  157.         return ret;
  158. }
  159.  
  160. static int do_server(struct options *opts, bmi_context_id *context)
  161. {
  162.         int                             ret = 0;
  163.         int                             i = 0;
  164.         PVFS_BMI_addr_t                 peer_addr;
  165.         PVFS_BMI_addr_t                 server_addr;
  166.         void                            *recv_buffer = NULL;
  167.         void                            *send_buffer = NULL;
  168.         bmi_op_id_t                     op_id[2];
  169.         bmi_error_code_t                error_code;
  170.         int                             outcount = 0;
  171.         struct BMI_unexpected_info      request_info;
  172.         bmi_size_t                      actual_size;
  173.         struct msg                      *tx_msg  = NULL;
  174.         struct msg                      *rx_msg  = NULL;
  175.         int                             bytes   = MIN_BYTES;
  176.         int                             max_bytes       = MAX_BYTES;
  177.         int                             warmup  = 1;
  178.         int                             iterations      = 0;
  179.         int                             msg_len         = 0;
  180.         int                             run     = 0;
  181.  
  182.         /* wait for an initial request to get size */
  183.         do {
  184.                 ret = BMI_testunexpected(1, &outcount, &request_info, 10);
  185.         } while (ret == 0 && outcount == 0);
  186.  
  187.         if (ret < 0) {
  188.                 fprintf(stderr, "Request recv failure (bad state).\n");
  189.                 errno = -ret;
  190.                 perror("BMI_testunexpected");
  191.                 return ret;
  192.         }
  193.         if (request_info.error_code != 0) {
  194.                 fprintf(stderr, "Request recv failure (bad state).\n");
  195.                 return ret;
  196.         }
  197.         
  198.         if (request_info.size != sizeof(struct msg)) {
  199.                 fprintf(stderr, "Bad Request! Received %d bytes\n", 
  200.                                 (int) request_info.size);
  201.                 return ret;
  202.         }
  203.  
  204.         rx_msg = (struct msg *) request_info.buffer;
  205.         opts->test = ntohl(rx_msg->test);
  206.  
  207.         printf("Starting %s test%s\n", opts->test == EXPECTED ? "expected" : "unexpected",
  208.                opts->crc ? " with checksums" : "");
  209.  
  210.         peer_addr = request_info.addr;
  211.  
  212.         BMI_unexpected_free(peer_addr, request_info.buffer);
  213.  
  214.         ret = BMI_get_info(server_addr, BMI_CHECK_MAXSIZE,
  215.                            (void *)&max_bytes);
  216.         if (ret < 0) {
  217.                 fprintf(stderr, "BMI_get_info() returned %d\n", ret);
  218.                 return ret;
  219.         }
  220.         if (max_bytes > MAX_BYTES) max_bytes = MAX_BYTES;
  221.  
  222.         if (opts->test == UNEXPECTED) {
  223.                 ret = BMI_addr_lookup(&server_addr, opts->hostid);
  224.                 if (ret < 0) {
  225.                         errno = -ret;
  226.                         perror("BMI_addr_lookup");
  227.                         return (-1);
  228.                 }
  229.                 ret = BMI_get_info(server_addr, BMI_GET_UNEXP_SIZE,
  230.                                    (void *)&max_bytes);
  231.                 if (ret < 0) {
  232.                         fprintf(stderr, "BMI_get_info() returned %d\n", ret);
  233.                         return ret;
  234.                 }
  235.         } else {
  236.                 int     maxsize = 0;
  237.                 ret = BMI_get_info(server_addr, BMI_CHECK_MAXSIZE,
  238.                                 (void *)&maxsize);
  239.                 if (ret < 0) {
  240.                         fprintf(stderr, "BMI_get_info() returned %d\n", ret);
  241.                         return ret;
  242.                 }
  243.                 if (maxsize < max_bytes) max_bytes = maxsize;
  244.         }
  245.  
  246.         msg_len = sizeof(struct msg);
  247.     
  248.         /* create an ack */
  249.         send_buffer = BMI_memalloc(peer_addr, max_bytes, BMI_SEND);
  250.         if (!send_buffer) {
  251.                 fprintf(stderr, "BMI_memalloc failed.\n");
  252.                 return (-1);
  253.         }
  254.         memset(send_buffer, 0, max_bytes);
  255.  
  256.         tx_msg = (struct msg *) send_buffer;
  257.         tx_msg->test = htonl(opts->test);
  258.  
  259.             
  260.         /* create a buffer to recv into */
  261.         recv_buffer = BMI_memalloc(peer_addr, max_bytes, BMI_RECV);
  262.         if (!recv_buffer) {
  263.                 fprintf(stderr, "BMI_memalloc failed.\n");
  264.                 return (-1);
  265.         }
  266.  
  267.         /* post the ack */
  268.         ret = BMI_post_send(&(op_id[SEND]), peer_addr, tx_msg,
  269.                         msg_len, BMI_PRE_ALLOC, 0, NULL,
  270.                         *context, NULL);
  271.         if (ret < 0) {
  272.                 fprintf(stderr, "BMI_post_send failure.\n");
  273.                 return (-1);
  274.         } else if (ret == 0) {
  275.                 do {
  276.                         ret = BMI_test(op_id[SEND], &outcount, &error_code,
  277.                                    &actual_size, NULL, 10, *context);
  278.                 } while (ret == 0 && outcount == 0);
  279.         
  280.                 if (ret < 0 || error_code != 0) {
  281.                         fprintf(stderr, "ack send failed.\n");
  282.                         return (-1);
  283.                 }
  284.  
  285.                 if (actual_size != (bmi_size_t) msg_len) {
  286.                         fprintf(stderr, "Expected %d but received %llu\n",
  287.                                         msg_len, llu(actual_size));
  288.                 }
  289.         }
  290.  
  291.         /* start iterations */
  292.         while (bytes <= max_bytes) {
  293.                 iterations = bytes_to_iterations(bytes);
  294.  
  295.                 for (i=0; i < iterations; i++) {
  296.                         /* receive the ping */
  297.                         if (opts->test == EXPECTED) {
  298.                                 ret = BMI_post_recv(&(op_id[RECV]), peer_addr, recv_buffer,
  299.                                                 bytes, &actual_size, BMI_PRE_ALLOC, i, NULL,
  300.                                                 *context, NULL);
  301.                     
  302.                                 if (ret < 0) {
  303.                                         fprintf(stderr, "BMI_post_recv_failure.\n");
  304.                                         return (-1);
  305.                                 } else if (ret == 0) {
  306.                                         do {
  307.                                                 ret = BMI_test(op_id[RECV], &outcount, &error_code,
  308.                                                         &actual_size, NULL, 10, *context);
  309.                                         } while (ret == 0 && outcount == 0);
  310.                 
  311.                                         if (ret < 0 || error_code != 0) {
  312.                                                 fprintf(stderr, "data recv failed.\n");
  313.                                                 return (-1);
  314.                                         }
  315.                                         if (actual_size != bytes) {
  316.                                                 fprintf(stderr, "Expected %d but received %llu\n",
  317.                                                                 bytes, llu(actual_size));
  318.                                                 return (-1);
  319.                                         }
  320.                                 }
  321.                         } else { /* UNEXPECTED */
  322.                                 do {
  323.                                         ret = BMI_testunexpected(1, &outcount, &request_info, 10);
  324.                                 } while (ret == 0 && outcount == 0);
  325.                         
  326.                                 if (ret < 0) {
  327.                                         fprintf(stderr, "Request recv failure (bad state).\n");
  328.                                         errno = -ret;
  329.                                         perror("BMI_testunexpected");
  330.                                         return ret;
  331.                                 }
  332.                                 if (request_info.error_code != 0) {
  333.                                         fprintf(stderr, "Request recv failure (bad state).\n");
  334.                                         return ret;
  335.                                 }
  336.                                 
  337.                                 if (request_info.size != bytes) {
  338.                                         fprintf(stderr, "Bad Request! Received %d bytes\n", 
  339.                                                         (int) request_info.size);
  340.                                         return ret;
  341.                                 }
  342.                         }
  343.                         /* send the pong */
  344.                         ret = BMI_post_send(&(op_id[SEND]), peer_addr,
  345.                                             (opts->test == EXPECTED ?
  346.                                              recv_buffer : request_info.buffer),
  347.                                         bytes, BMI_PRE_ALLOC, i, NULL, *context, NULL);
  348.                         if (ret < 0) {
  349.                                 fprintf(stderr, "BMI_post_send failure.\n");
  350.                                 return (-1);
  351.                         } else if (ret == 0) {
  352.                                 do {
  353.                                         ret = BMI_test(op_id[SEND], &outcount, &error_code,
  354.                                                 &actual_size, NULL, 10, *context);
  355.                                 } while (ret == 0 && outcount == 0);
  356.         
  357.                                 if (ret < 0 || error_code != 0) {
  358.                                         fprintf(stderr, "ack send failed.\n");
  359.                                         return (-1);
  360.                                 }
  361.                                 if (actual_size != bytes) {
  362.                                         fprintf(stderr, "Expected %d but received %llu\n",
  363.                                                         bytes, llu(actual_size));
  364.                                         return (-1);
  365.                                 }
  366.                         }
  367.                 }
  368.                 if (!warmup) {
  369.                         bytes *= 2;
  370.                         run++;
  371.                 }
  372.                 else warmup = 0;
  373.         }
  374.  
  375.         /* free up the message buffers */
  376.         BMI_memfree(peer_addr, recv_buffer, max_bytes, BMI_RECV);
  377.         BMI_memfree(peer_addr, send_buffer, max_bytes, BMI_SEND);
  378.  
  379.         return ret;
  380. }
  381.  
  382. static int do_client(struct options *opts, bmi_context_id *context)
  383. {
  384.         int                     ret             = 0;
  385.         int                     i               = 0;
  386.         PVFS_BMI_addr_t         peer_addr;
  387.         void                    *recv_buffer    = NULL;
  388.         void                    *send_buffer    = NULL;
  389.         bmi_op_id_t             op_id[2];
  390.         bmi_error_code_t        error_code;
  391.         int                     outcount        = 0;
  392.         bmi_size_t              actual_size;
  393.         struct msg              *tx_msg         = NULL;
  394.         int                     bytes           = MIN_BYTES;
  395.         int                     max_bytes       = MAX_BYTES;
  396.         int                     warmup          = 1;
  397.         int                     iterations      = 0;
  398.         int                     msg_len         = 0;
  399.         int                     run             = 0;
  400.         struct timeval          start;
  401.         struct timeval          end;
  402.         double                  *val            = NULL;
  403.         double                  lat             = 0.0;
  404.         double                  min             = 99999.9;
  405.         double                  max             = 0.0;
  406.         double                  avg             = 0.0;
  407.         int                     offset;
  408. #ifdef HAVE_LIBZ
  409.         unsigned long           crc=0, rcrc=0;
  410. #endif
  411.  
  412.         /* get a bmi_addr for the server */
  413.         ret = BMI_addr_lookup(&peer_addr, opts->hostid);
  414.         if (ret < 0) {
  415.                 errno = -ret;
  416.                 perror("BMI_addr_lookup");
  417.                 return (-1);
  418.         }
  419.  
  420.         if (opts->test == UNEXPECTED) {
  421.                 ret = BMI_get_info(peer_addr, BMI_GET_UNEXP_SIZE,
  422.                                    (void *)&max_bytes);
  423.                 if (ret < 0) {
  424.                         fprintf(stderr, "BMI_get_info() returned %d\n", ret);
  425.                         return ret;
  426.                 }
  427.         } else {
  428.                 int     maxsize = 0;
  429.                 ret = BMI_get_info(peer_addr, BMI_CHECK_MAXSIZE,
  430.                                 (void *)&maxsize);
  431.                 if (ret < 0) {
  432.                         fprintf(stderr, "BMI_get_info() returned %d\n", ret);
  433.                         return ret;
  434.                 }
  435.                 if (maxsize < max_bytes) max_bytes = maxsize;
  436.         }
  437.  
  438.         msg_len = sizeof(struct msg);
  439.  
  440.         /* create send buffer */
  441.         send_buffer = BMI_memalloc(peer_addr, max_bytes, BMI_SEND);
  442.         if (!send_buffer) {
  443.                 fprintf(stderr, "BMI_memalloc failed.\n");
  444.                 return (-1);
  445.         }
  446.  
  447.         if(opts->crc)
  448.         {
  449.             for(i = 0; i < max_bytes; ++i)
  450.             {
  451.                 ((char *)send_buffer)[i] = i;
  452.             }
  453.         }
  454.         else
  455.         {
  456.             memset(send_buffer, 0, max_bytes);
  457.         }
  458.  
  459.         tx_msg = (struct msg *) send_buffer;
  460.         tx_msg->test = htonl(opts->test);
  461.     
  462.         /* create a buffer to recv into */
  463.         recv_buffer = BMI_memalloc(peer_addr, max_bytes, BMI_RECV);
  464.         if (!recv_buffer) {
  465.                 fprintf(stderr, "BMI_memalloc failed.\n");
  466.                 return (-1);
  467.         }
  468.  
  469.         /* post the test parameters */
  470.         ret = BMI_post_sendunexpected(&(op_id[SEND]), peer_addr, tx_msg,
  471.                         msg_len, BMI_PRE_ALLOC, 0, NULL, *context, NULL);
  472.         if (ret < 0) {
  473.                 fprintf(stderr, "BMI_post_sendunexpected failure.\n");
  474.                 return (-1);
  475.         } else if (ret == 0) {
  476.                 do {
  477.                         ret = BMI_test(op_id[SEND], &outcount, &error_code,
  478.                                 &actual_size, NULL, 10, *context);
  479.                 } while (ret == 0 && outcount == 0);
  480.                 if (ret < 0 || error_code != 0) {
  481.                         fprintf(stderr, "data send failed.\n");
  482.                         return (-1);
  483.                 }
  484.                 if (actual_size != msg_len) {
  485.                         fprintf(stderr, "Expected %d but received %llu\n",
  486.                                         msg_len, llu(actual_size));
  487.                         return (-1);
  488.                 }
  489.         }
  490.  
  491.         /* post a recv for the ack */
  492.         ret = BMI_post_recv(&(op_id[RECV]), peer_addr, recv_buffer,
  493.                         msg_len, &actual_size, BMI_PRE_ALLOC, 0, NULL, *context, NULL);
  494.         if (ret < 0) {
  495.                 fprintf(stderr, "BMI_post_recv_failure.\n");
  496.                 return (-1);
  497.         } else if (ret == 0) {
  498.                 do {
  499.                         ret = BMI_test(op_id[RECV], &outcount, &error_code,
  500.                                 &actual_size, NULL, 10, *context);
  501.                 } while (ret == 0 && outcount == 0);
  502.  
  503.                 if (ret < 0 || error_code != 0) {
  504.                         fprintf(stderr, "data recv failed.\n");
  505.                         return (-1);
  506.                 }
  507.                 if (actual_size != msg_len) {
  508.                         fprintf(stderr, "Expected %d but received %llu\n",
  509.                                         msg_len, llu(actual_size));
  510.                         return (-1);
  511.                 }
  512.         }
  513.  
  514.         val = calloc(ITERATIONS, sizeof(double));
  515.         if (val == NULL) {
  516.                 fprintf(stderr, "calloc() for val failed\n");
  517.                 return -1;
  518.         }
  519.  
  520.         /* make sure server has posted first recv */
  521.         sleep(1);
  522.  
  523.         fprintf(stdout, "     Bytes        usecs         MB/s       StdDev          Min          Max\n");
  524.  
  525.         /* start iterations */
  526.         while (bytes <= max_bytes) {
  527.  
  528.                 iterations = bytes_to_iterations(bytes);
  529.  
  530.                 for (i=0; i < iterations; i++) {
  531.  
  532.                         offset = random() % (max_bytes - bytes - 1);
  533.                         gettimeofday(&start, NULL);
  534.  
  535. #ifdef HAVE_LIBZ
  536.                         if(opts->crc)
  537.                         {
  538.                             crc = adler32(0L, Z_NULL, 0);
  539.                             crc = adler32(crc, ((unsigned char *)send_buffer + (unsigned int)offset), bytes);
  540.                         }
  541. #endif
  542.  
  543.                         /* post the recv for the pong */
  544.                         ret = BMI_post_recv(&(op_id[RECV]), peer_addr, recv_buffer,
  545.                                         bytes, &actual_size, BMI_PRE_ALLOC, i,
  546.                                         NULL, *context, NULL);
  547.             
  548.                         if (ret < 0) {
  549.                                 fprintf(stderr, "BMI_post_recv_failure.\n");
  550.                                 return (-1);
  551.                         }
  552.         
  553.                         /* send the ping */
  554.                         if (opts->test == EXPECTED) {
  555.                                 ret = BMI_post_send(&(op_id[SEND]), peer_addr, ((char *)send_buffer) + offset,
  556.                                                 bytes, BMI_PRE_ALLOC, i, NULL, *context, NULL);
  557.                         } else {
  558.                                 ret = BMI_post_sendunexpected(&(op_id[SEND]), peer_addr, 
  559.                                                 ((char*)send_buffer) + offset, bytes, BMI_PRE_ALLOC, i, 
  560.                                                 NULL, *context, NULL);
  561.                         }
  562.                         if (ret < 0) {
  563.                                 fprintf(stderr, "BMI_post_sendunexpected failure.\n");
  564.                                 return (-1);
  565.                         } else if (ret == 0) {
  566.                                 do {
  567.                                         ret = BMI_test(op_id[SEND], &outcount, &error_code,
  568.                                                         &actual_size, NULL, 10, *context);
  569.                                 } while (ret == 0 && outcount == 0);
  570.                         
  571.                                 if (ret < 0 || error_code != 0) {
  572.                                         fprintf(stderr, "send ping failed.\n");
  573.                                         return (-1);
  574.                                 }
  575.                                 if (actual_size != bytes) {
  576.                                         fprintf(stderr, "Expected %d but received %llu\n",
  577.                                                         bytes, llu(actual_size));
  578.                                         return (-1);
  579.                                 }
  580.                         }
  581.                         /* complete the receive for the pong */
  582.                         do {
  583.                                 ret = BMI_test(op_id[RECV], &outcount, &error_code,
  584.                                                 &actual_size, NULL, 10, *context);
  585.                         } while (ret == 0 && outcount == 0);
  586.         
  587.                         if (ret < 0 || error_code != 0) {
  588.                                 fprintf(stderr, "data recv failed.\n");
  589.                                 return (-1);
  590.                         }
  591.                         if (actual_size != bytes) {
  592.                                 fprintf(stderr, "Expected %d but received %llu\n",
  593.                                                 bytes, llu(actual_size));
  594.                                 return (-1);
  595.                         }
  596.  
  597. #ifdef HAVE_LIBZ
  598.                         if(opts->crc && opts->test == EXPECTED)
  599.                         {
  600.                             rcrc = adler32(0L, Z_NULL, 0);
  601.                             rcrc = adler32(rcrc, recv_buffer, bytes);
  602.                             if(rcrc != crc)
  603.                             {
  604.                                 fprintf(stderr, "CRC Mismatch!  Sent %llu but received %llu\n",
  605.                                         llu(crc), llu(rcrc));
  606.                             }
  607.                         }
  608. #endif
  609.                         gettimeofday(&end, NULL);
  610.  
  611.                         if (!warmup) {
  612.                                 val[i] =  (double) end.tv_sec + 
  613.                                           (double) end.tv_usec * 0.000001;
  614.                                 val[i] -= (double) start.tv_sec + 
  615.                                           (double) start.tv_usec * 0.000001;
  616.                                 lat += val[i];
  617.                         }
  618.                 }
  619.                 if (!warmup) {
  620.                         double stdev    = 0.0;
  621.  
  622.                         lat = lat / (double) iterations * 1000000.0 / 2.0;
  623.                         min = 999999.9;
  624.                         max = 0.0;
  625.                         avg = 0.0;
  626.  
  627.                         /* convert seconds to MB/s */
  628.                         for (i=0; i < iterations; i++) {
  629.                                 val[i] = (double) bytes * 2 / val[i] / 1000000.0;
  630.                                 avg += val[i];
  631.                                 if (val[i] < min) min = val[i];
  632.                                 if (val[i] > max) max = val[i];
  633.                         }
  634.                         avg /= iterations;
  635.  
  636.                         if (iterations > 1) {
  637.                                 for (i=0; i < iterations; i++) {
  638.                                         double diff = val[i] - avg;
  639.                                         stdev += diff * diff;
  640.                                 }
  641.                                 stdev = sqrt(stdev / (iterations - 1));
  642.                         }
  643.  
  644.                         fprintf(stdout, "%10d %12.3f %12.3f +- %9.3f %12.3f %12.3f\n", bytes, lat, avg, stdev, min, max);
  645.  
  646.                         lat = 0.0;
  647.                         bytes *= 2;
  648.                         run++;
  649.                 } else warmup = 0;
  650.         }
  651.  
  652.         /* free up the message buffers */
  653.         BMI_memfree(peer_addr, recv_buffer, max_bytes, BMI_RECV);
  654.         BMI_memfree(peer_addr, send_buffer, max_bytes, BMI_SEND);
  655.  
  656.         return ret;
  657. }
  658.  
  659. static int check_uri(char *uri)
  660. {
  661.         int ret = 0; /* failure */
  662.         if (uri[0] == ':' && uri[1] == '/' && uri[2] == '/') ret = 1;
  663.         return ret;
  664. }
  665.  
  666.  
  667. static void get_method(struct options *opts)
  668. {
  669.         char *id = opts->hostid;
  670.  
  671.         if (id[0] == 't' && id[1] == 'c' && id[2] == 'p' && check_uri(&id[3])) {
  672.                 opts->method = strdup("bmi_tcp");
  673.         } else if (id[0] == 'g' && id[1] == 'm' && check_uri(&id[2])) {
  674.                 opts->method = strdup("bmi_gm");
  675.         } else if (id[0] == 'm' && id[1] == 'x' && check_uri(&id[2])) {
  676.                 opts->method = strdup("bmi_mx");
  677.         } else if (id[0] == 'i' && id[1] == 'b' && check_uri(&id[2])) {
  678.                 opts->method = strdup("bmi_ib");
  679.         }
  680.         return;
  681. }
  682.  
  683. static struct options *parse_args(int argc, char *argv[])
  684. {
  685.  
  686.         /* getopt stuff */
  687.         extern char *optarg;
  688.         char flags[] = "h:scur";
  689.         int one_opt = 0;
  690.  
  691.         struct options *opts = NULL;
  692.  
  693.         /* create storage for the command line options */
  694.         opts = (struct options *) calloc(1, sizeof(struct options));
  695.         if (!opts) {
  696.             goto parse_args_error;
  697.         }
  698.     
  699.         /* look at command line arguments */
  700.         while ((one_opt = getopt(argc, argv, flags)) != EOF) {
  701.                 switch (one_opt) {
  702.                 case ('h'):
  703.                         opts->hostid = (char *) strdup(optarg);
  704.                         if (opts->hostid == NULL) {
  705.                             goto parse_args_error;
  706.                         }
  707.                         get_method(opts);
  708.                         break;
  709.                 case ('s'):
  710.                         if (opts->which == CLIENT) {
  711.                                 fprintf(stderr, "use -s OR -c, not both\n");
  712.                             goto parse_args_error;
  713.                         }
  714.                         opts->which = SERVER;
  715.                         break;
  716.                 case ('c'):
  717.                         if (opts->which == SERVER) {
  718.                                 fprintf(stderr, "use -s OR -c, not both\n");
  719.                             goto parse_args_error;
  720.                         }
  721.                         opts->which = CLIENT;
  722.                         break;
  723.                 case ('u'):
  724.                         opts->test = UNEXPECTED;
  725.                         break;
  726.                 case ('r'):
  727.                         opts->crc = 1;
  728.                         break;
  729.                 default:
  730.                         break;
  731.                 }
  732.         }
  733.     
  734.         /* if we didn't get a host argument, bail: */
  735.         if (opts->hostid == NULL) {
  736.                 fprintf(stderr, "you must specify -h\n");
  737.                 goto parse_args_error;
  738.         }
  739.         if (opts->method == NULL) {
  740.                 fprintf(stderr, "you must use a valid HOST_URI\n");
  741.                 goto parse_args_error;
  742.         }
  743.         if (opts->which == 0) {
  744.                 fprintf(stderr, "you must specify -s OR -c\n");
  745.                 goto parse_args_error;
  746.         }
  747.  
  748.         return (opts);
  749.  
  750. parse_args_error:
  751.  
  752.         /* if an error occurs, just free everything and return NULL */
  753.         if (opts) {
  754.                 if (opts->hostid) {
  755.                         free(opts->hostid);
  756.                 }
  757.                 free(opts);
  758.         }
  759.         return (NULL);
  760. }
  761.  
  762. /*
  763.  * vim:expandtab:shiftwidth=8:tabstop=8:
  764.  */
  765.