MACSio  0.9
Multi-purpose, Application-Centric, Scalable I/O Proxy App
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
macsio_main.c
Go to the documentation of this file.
1 /*
2 Copyright (c) 2015, Lawrence Livermore National Security, LLC.
3 Produced at the Lawrence Livermore National Laboratory.
4 Written by Mark C. Miller
5 
6 LLNL-CODE-676051. All rights reserved.
7 
8 This file is part of MACSio
9 
10 Please also read the LICENSE file at the top of the source code directory or
11 folder hierarchy.
12 
13 This program is free software; you can redistribute it and/or modify it under
14 the terms of the GNU General Public License (as published by the Free Software
15 Foundation) version 2, dated June 1991.
16 
17 This program is distributed in the hope that it will be useful, but WITHOUT
18 ANY WARRANTY; without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS
19 FOR A PARTICULAR PURPOSE. See the terms and conditions of the GNU General
20 Public License for more details.
21 
22 You should have received a copy of the GNU General Public License along with
23 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
24 Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26 
27 #include <errno.h>
28 #include <float.h>
29 #include <math.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <sys/stat.h>
34 #include <sys/time.h>
35 #include <sys/types.h>
36 #include <unistd.h>
37 
38 #ifdef HAVE_SCR
39 #ifdef __cplusplus
40 extern "C" {
41 #endif
42 #include <scr.h>
43 #ifdef __cplusplus
44 }
45 #endif
46 #endif
47 
48 #include <macsio_clargs.h>
49 #include <macsio_data.h>
50 #include <macsio_iface.h>
51 #include <macsio_log.h>
52 #include <macsio_main.h>
53 #include <macsio_timing.h>
54 #include <macsio_utils.h>
55 
56 #include <json-c/json.h>
57 
58 #ifdef HAVE_MPI
59 #include <mpi.h>
60 #endif
61 
274 #define MAX(A,B) (((A)>(B))?(A):(B))
275 
276 extern char **enviornp;
277 
278 #ifdef HAVE_MPI
279 MPI_Comm MACSIO_MAIN_Comm = MPI_COMM_WORLD;
280 #else
281 int MACSIO_MAIN_Comm = 0;
282 #endif
283 
286 
287 static void handle_help_request_and_exit(int argi, int argc, char **argv)
288 {
289  int i, n, *ids=0;;
290  FILE *outFILE = (isatty(2) ? stderr : stdout);
291 
292  MACSIO_IFACE_GetIds(&n, &ids);
293  for (i = 0; i < n; i++)
294  {
295  const MACSIO_IFACE_Handle_t *iface = MACSIO_IFACE_GetById(ids[i]);
296  if (iface->processArgsFunc)
297  {
298  fprintf(outFILE, "\nOptions specific to the \"%s\" I/O plugin\n", iface->name);
299  (*(iface->processArgsFunc))(argi, argc, argv);
300  }
301  }
302 #ifdef HAVE_MPI
303  { int result;
304  if ((MPI_Initialized(&result) == MPI_SUCCESS) && result)
305  MPI_Finalize();
306  }
307 #endif
308  exit(0);
309 }
310 
312 {
313  int i, n, *ids = 0;
314  FILE *outFILE = (isatty(2) ? stderr : stdout);
315  char names_buf[1024];
316 
317  names_buf[0] = '\0';
318  MACSIO_IFACE_GetIds(&n, &ids);
319  for (i = 0; i < n; i++)
320  {
321  char const *nm = MACSIO_IFACE_GetName(ids[i]);
322  strcat(names_buf, "\"");
323  strcat(names_buf, nm);
324  strcat(names_buf, "\", ");
325  if (!((i+1) % 10)) strcat(names_buf, "\n");
326  }
327  fprintf(outFILE, "List of available I/O-library plugins...\n");
328  fprintf(outFILE, "%s\n", names_buf);
329 #ifdef HAVE_MPI
330  { int result;
331  if ((MPI_Initialized(&result) == MPI_SUCCESS) && result)
332  MPI_Finalize();
333  }
334 #endif
335  exit(0);
336 }
337 
338 static json_object *ProcessCommandLine(int argc, char *argv[], int *plugin_argi)
339 {
341  json_object *mainJargs = 0;
342  int plugin_args_start = -1;
343  int cl_result;
344 
345 #warning SUBGROUP OPTIONS INTO READ AND WRITE OPTIONS
346 #warning MAYBE MAKE IT EASIER TO SPECIFY STRONG OR WEAK SCALING CASE
347 #warning OPTION TO CONTROL TOTAL BUFFER SIZE IN LOWER-LAYERS
348 #warning OPTION TO SET OUTPUT PRECISION TO FLOAT
349 
350  cl_result = MACSIO_CLARGS_ProcessCmdline((void**)&mainJargs, argFlags, 1, argc, argv,
351  "--units_prefix_system %s", "binary",
352  "Specify which SI units prefix system to use both in reporting performance\n"
353  "data and in interpreting sizing modifiers to arguments. The options are\n"
354  "\"binary\" and \"decimal\". For \"binary\" unit prefixes, sizes are reported\n"
355  "in powers of 1024 and unit symbols Ki, Mi, Gi, Ti, Pi are used. For \"decimal\",\n"
356  "sizes are reported in powers of 1000 and unit symbols are Kb, Mb, Gb, Tb, Pb.\n"
357  "See http://en.wikipedia.org/wiki/Binary_prefix. for more information",
358  "--interface %s", "miftmpl",
359  "Specify the name of the interface to be tested. Use keyword 'list'\n"
360  "to print a list of all known interface names and then exit.",
361  "--parallel_file_mode %s %d", "MIF 4",
362  "Specify the parallel file mode. There are several choices.\n"
363  "Use 'MIF' for Multiple Independent File (Poor Man's) mode and then\n"
364  "also specify the number of files. Or, use 'MIFFPP' for MIF mode and\n"
365  "one file per processor or 'MIFOPT' for MIF mode and let the test\n"
366  "determine the optimum file count. Use 'SIF' for SIngle shared File\n"
367  "(Rich Man's) mode. If you also give a file count for SIF mode, then\n"
368  "MACSio will perform a sort of hybrid combination of MIF and SIF modes.\n"
369  "It will produce the specified number of files by grouping ranks in the\n"
370  "the same way MIF does, but I/O within each group will be to a single,\n"
371  "shared file using SIF mode.",
372  "--avg_num_parts %f", "1",
373  "The average number of mesh parts per MPI rank. Non-integral values\n"
374  "are acceptable. For example, a value that is half-way between two\n"
375  "integers, K and K+1, means that half the ranks have K mesh parts\n"
376  "and half have K+1 mesh parts. As another example, a value of 2.75\n"
377  "here would mean that 75% of the ranks get 3 parts and 25% of the\n"
378  "ranks get 2 parts. Note that the total number of parts is this\n"
379  "number multiplied by the MPI communicator size. If the result of that\n"
380  "product is non-integral, it will be rounded and a warning message will\n"
381  "be generated.",
382  "--part_size %d", "80000",
383  "Mesh part size in bytes. This becomes the nominal I/O request size\n"
384  "used by each MPI rank when marshalling data. A following B|K|M|G\n"
385  "character indicates 'B'ytes, 'K'ilo-, 'M'ega- or 'G'iga- bytes\n"
386  "representing powers of either 1000 or 1024 according to the selected\n"
387  "units prefix system. With no size modifier character, 'B' is assumed.\n"
388  "Mesh and variable data is then sized by MACSio to hit this target byte\n"
389  "count. However, due to contraints involved in creating valid mesh\n"
390  "topology and variable data with realistic variation in features (e.g.\n"
391  "zone- and node-centering), this target byte count is hit exactly for\n"
392  "only the most frequently dumped objects and approximately for other objects.",
393  "--part_dim %d", "2",
394  "Spatial dimension of parts; 1, 2, or 3",
395  "--part_type %s", "rectilinear",
396  "Options are 'uniform', 'rectilinear', 'curvilinear', 'unstructured'\n"
397  "and 'arbitrary' (currently, only rectilinear is implemented)",
398  "--part_map %s", MACSIO_CLARGS_NODEFAULT,
399  "Specify the name of an ascii file containing part assignments to MPI ranks.\n"
400  "The ith line in the file, numbered from 0, holds the MPI rank to which the\n"
401  "ith part is to be assigned. (currently ignored)",
402  "--vars_per_part %d", "20",
403  "Number of mesh variable objects in each part. The smallest this can\n"
404  "be depends on the mesh type. For rectilinear mesh it is 1. For\n"
405  "curvilinear mesh it is the number of spatial dimensions and for\n"
406  "unstructured mesh it is the number of spatial dimensions plus\n"
407  "2^number of topological dimensions. [50]",
408  "--topology_change_probability %f", "0.0",
409  "The probability that the topology of the mesh (e.g. something fundamental\n"
410  "about the mesh's structure) will change between dumps. A value of 1.0\n"
411  "indicates it should be changed every dump. A value of 0.0, the default,\n"
412  "indicates it will never change. A value of 0.1 indicates it will change\n"
413  "about once every 10 dumps. Note: at present MACSio will not actually\n"
414  "compute/construct a different topology. It will only inform a plugin\n"
415  "that a given dump should be treated as a change in topology.",
416  "--meta_type %s", "tabular",
417  "Specify the type of metadata objects to include in each main dump.\n"
418  "Options are 'tabular', 'amorphous'. For tabular type data, MACSio\n"
419  "will generate a random set of tables of somewhat random structure\n"
420  "and content. For amorphous, MACSio will generate a random hierarchy\n"
421  "of random type and sized objects.",
422 #warning MAY WANT SOME PORTIONS OF METADATA TO SCALE WITH MESH PIECE COUNT
423  "--meta_size %d %d", "10000 50000",
424  "Specify the size of the metadata objects on each processor and\n"
425  "separately, the root (or master) processor (MPI rank 0). The size\n"
426  "is specified in terms of the total number of bytes in the metadata\n"
427  "objects MACSio creates. For example, a type of tabular and a size of\n"
428  "10K bytes might result in 3 random tables; one table with 250 unnamed\n"
429  "records where each record is an array of 3 doubles for a total of\n"
430  "6000 bytes, another table of 200 records where each record is a\n"
431  "named integer value where each name is length 8 chars for a total of\n"
432  "2400 bytes and a 3rd table of 40 unnamed records where each record\n"
433  "is a 40 byte struct comprised of ints and doubles for a total of 1600\n"
434  "bytes.",
435  "--num_dumps %d", "10",
436  "Total number of dumps to marshal",
437  "--max_dir_size %d", MACSIO_CLARGS_NODEFAULT,
438  "The maximum number of filesystem objects (e.g. files or subdirectories)\n"
439  "that MACSio will create in any one subdirectory. This is typically\n"
440  "relevant only in MIF mode because MIF mode can wind up generating many\n"
441  "files on each dump. The default setting is unlimited meaning that MACSio\n"
442  "will continue to create output files in the same directory until it has\n"
443  "completed all dumps. Use a value of zero to force MACSio to put each\n"
444  "dump in a separate directory but where the number of top-level directories\n"
445  "is still unlimited. The result will be a 2-level directory hierarchy\n"
446  "with dump directories at the top and individual dump files in each\n"
447  "directory. A value > 0 will cause MACSio to create a tree-like directory\n"
448  "structure where the files are the leaves and encompassing dir tree is\n"
449  "created such as to maintain the max_dir_size constraint specified here.\n"
450  "For example, if the value is set to 32 and the MIF file count is 1024,\n"
451  "then each dump will involve a 3-level dir-tree; the top dir containing\n"
452  "32 sub-dirs and each sub-dir containing 32 of the 1024 files for the\n"
453  "dump. If more than 32 dumps are performed, then the dir-tree will really\n"
454  "be 4 or more levels with the first 32 dumps' dir-trees going into the\n"
455  "first dir, etc.",
456 #ifdef HAVE_SCR
457  "--exercise_scr", "",
458  "Exercise the Scalable Checkpoint and Restart (SCR)\n"
459  "(https://computation.llnl.gov/project/scr/library) to marshal\n"
460  "files. Note that this works only in MIFFPP mode. A request to exercise\n"
461  "SCR in any other mode will be ignored and en error message generated.",
462 #endif
463  "--debug_level %d", "0",
464  "Set debugging level (1, 2 or 3) of log files. Higher numbers mean\n"
465  "more frequent and detailed output. A value of zero, the default,\n"
466  "turns all debugging output off. A value of 1 should not adversely\n"
467  "effect performance. A value of 2 may effect performance and a value\n"
468  "of 3 will almost certainly effect performance. For debug level 3,\n"
469  "MACSio will generate ascii json files from each processor for the main\n"
470  "dump object prior to starting dumps.",
471  MACSIO_CLARGS_ARG_GROUP_BEG(Log File Options),
472  "Options to control size and shape of log file",
473  "--log_file_name %s", "macsio-log.log",
474  "The name of the log file.",
475  "--log_line_cnt %d %d", "64 0",
476  "Set number of lines per rank in the log file and number of extra lines\n"
477  "for rank 0.",
478  "--log_line_length %d", "128",
479  "Set log file line length.",
480  "--timings_file_name %s", "macsio-timings.log",
481  "Specify the name of the timings file. Passing an empty string, \"\"\n"
482  "will disable the creation of a timings file.",
483  MACSIO_CLARGS_ARG_GROUP_END(Log File Options),
484  "--alignment %d", MACSIO_CLARGS_NODEFAULT,
485  "Not currently documented",
486  "--filebase %s", "macsio",
487  "Basename of generated file(s).",
488  "--fileext %s", "dat",
489  "Extension of generated file(s).",
490  "--read_path %s", MACSIO_CLARGS_NODEFAULT,
491  "Specify a path name (file or dir) to start reading for a read test.",
492  "--num_loads %d", MACSIO_CLARGS_NODEFAULT,
493  "Number of loads in succession to test.",
494  "--no_validate_read", "",
495  "Don't validate data on read.",
496  "--read_mesh %s", MACSIO_CLARGS_NODEFAULT,
497  "Specficify mesh name to read.",
498  "--read_vars %s", MACSIO_CLARGS_NODEFAULT,
499  "Specify variable names to read. \"all\" means all variables. If listing more\n"
500  "than one, be sure to either enclose space separated list in quotes or\n"
501  "use a comma-separated list with no spaces",
502  "--time_randomize_seeds", "",
503  "Make randomness in MACSio vary from dump to dump and run to run by\n"
504  "time-modulating all random number seeding.",
505 #if 0
506  MACSIO_CLARGS_LAST_ARG_SEPERATOR(plugin_args)
507 #endif
508  "--plugin_args %n", MACSIO_CLARGS_NODEFAULT,
509  "All arguments after this sentinel are passed to the I/O plugin\n"
510  "plugin. The '%n' is a special designator for the builtin 'argi'\n"
511  "value.",
513 
514  plugin_args_start = json_object_path_get_int(mainJargs, "argi");
515  if (plugin_args_start == 0) plugin_args_start = -1;
516 
517  /* if we discovered help was requested, then print each plugin's help too */
518  if (cl_result == MACSIO_CLARGS_HELP)
519  handle_help_request_and_exit(plugin_args_start+1, argc, argv);
520 
521  if (!strcmp(json_object_path_get_string(mainJargs, "interface"), "list"))
523 
524  /* sanity check some values */
525  if (!strcmp(json_object_path_get_string(mainJargs, "interface"), ""))
526  MACSIO_LOG_MSG(Die, ("no io-interface specified"));
527 
528  if (plugin_argi)
529  *plugin_argi = plugin_args_start>-1?plugin_args_start+1:argc;
530 
531  return mainJargs;
532 }
533 
534 static int
536 {
537  char **timer_strs = 0, **rtimer_strs = 0;
538  int i, ntimers, maxlen, rntimers = 0, rmaxlen = 0, rdata[3], rdata_out[3];
539  MACSIO_LOG_LogHandle_t *timing_log;
540 
541  MACSIO_TIMING_DumpTimersToStrings(MACSIO_TIMING_ALL_GROUPS, &timer_strs, &ntimers, &maxlen);
543  if (MACSIO_MAIN_Rank == 0)
544  MACSIO_TIMING_DumpReducedTimersToStrings(MACSIO_TIMING_ALL_GROUPS, &rtimer_strs, &rntimers, &rmaxlen);
545  rdata[0] = maxlen > rmaxlen ? maxlen : rmaxlen;
546  rdata[1] = ntimers;
547  rdata[2] = rntimers;
548 #ifdef HAVE_MPI
549  MPI_Allreduce(rdata, rdata_out, 3, MPI_INT, MPI_MAX, MACSIO_MAIN_Comm);
550 #endif
551 
552  timing_log = MACSIO_LOG_LogInit(MACSIO_MAIN_Comm, filename, rdata_out[0], rdata_out[1], rdata_out[2]+1);
553 
554  /* dump this processor's timers */
555  for (i = 0; i < ntimers; i++)
556  {
557  if (!timer_strs[i] || !strlen(timer_strs[i])) continue;
558  MACSIO_LOG_MSGL(timing_log, Info, (timer_strs[i]));
559  free(timer_strs[i]);
560  }
561  free(timer_strs);
562 
563  /* dump MPI reduced timers */
564  if (MACSIO_MAIN_Rank == 0)
565  {
566  MACSIO_LOG_LogMsg(timing_log, "Reduced Timers...");
567 
568  for (i = 0; i < rntimers; i++)
569  {
570  if (!rtimer_strs[i] || !strlen(rtimer_strs[i])) continue;
571  MACSIO_LOG_MSGL(timing_log, Info, (rtimer_strs[i]));
572  free(rtimer_strs[i]);
573  }
574  free(rtimer_strs);
575  }
576 
577  MACSIO_LOG_LogFinalize(timing_log);
578 }
579 
580 static int
581 main_write(int argi, int argc, char **argv, json_object *main_obj)
582 {
583  int rank = 0, dumpNum = 0, dumpCount = 0;
584  unsigned long long problem_nbytes, dumpBytes = 0, summedBytes = 0;
585  char nbytes_str[32], seconds_str[32], bandwidth_str[32], seconds_str2[32];
586  double dumpTime = 0;
587  double bandwidth, summedBandwidth;
588  MACSIO_TIMING_GroupMask_t main_wr_grp = MACSIO_TIMING_GroupMask("main_write");
589  double dump_loop_start, dump_loop_end;
590  double min_dump_loop_start, max_dump_loop_end;
591  int exercise_scr = JsonGetInt(main_obj, "clargs/exercise_scr");
592 
593  /* Sanity check args */
594 
595  /* Generate a static problem object to dump on each dump */
596  json_object *problem_obj = MACSIO_DATA_GenerateTimeZeroDumpObject(main_obj,0);
597  problem_nbytes = (unsigned long long) json_object_object_nbytes(problem_obj);
598 
599 #warning MAKE JSON OBJECT KEY CASE CONSISTENT
600  json_object_object_add(main_obj, "problem", problem_obj);
601 
602  /* Just here for debugging for the moment */
603  if (MACSIO_LOG_DebugLevel >= 2)
604  {
605  char outfName[256];
606  FILE *outf;
607  int json_c_print_flags = JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED;
608 
609  if (MACSIO_LOG_DebugLevel < 3)
610  json_c_print_flags |= JSON_C_TO_STRING_NO_EXTARR_VALS;
611 
612  snprintf(outfName, sizeof(outfName), "main_obj_write_%03d.json", MACSIO_MAIN_Rank);
613  outf = fopen(outfName, "w");
614  fprintf(outf, "\"%s\"\n", json_object_to_json_string_ext(main_obj, json_c_print_flags));
615  fclose(outf);
616  }
617 
618 #warning WERE NOT GENERATING OR WRITING ANY METADATA STUFF
619 
620 #warning MAKE THIS LOOP MORE LIKE A MAIN SIM LOOP WITH SIMPLE COMPUTE AND COMM STEP
621  dump_loop_start = MT_Time();
622  dumpTime = 0.0;
623  for (dumpNum = 0; dumpNum < json_object_path_get_int(main_obj, "clargs/num_dumps"); dumpNum++)
624  {
625  double dt;
626  int scr_need_checkpoint_flag = 1;
627  MACSIO_TIMING_TimerId_t heavy_dump_tid;
628 
629 #warning ADD OPTION TO UNLINK OLD FILE SETS
630 
631 #ifdef HAVE_SCR
632  if (exercise_scr)
633  SCR_Need_checkpoint(&scr_need_checkpoint_flag);
634 #endif
635 
637  json_object_path_get_string(main_obj, "clargs/interface"));
638 
639  /* log dump start */
640 
641  if (!exercise_scr || scr_need_checkpoint_flag)
642  {
643  int scr_valid = 0;
644 
645 #ifdef HAVE_SCR
646  if (exercise_scr)
647  SCR_Start_checkpoint();
648 #endif
649 
650  /* Start dump timer */
651  heavy_dump_tid = MT_StartTimer("heavy dump", main_wr_grp, dumpNum);
652 
653 #warning REPLACE DUMPN AND DUMPT WITH A STATE TUPLE
654 #warning SHOULD HAVE PLUGIN RETURN FILENAMES SO MACSIO CAN STAT FOR TOTAL BYTES ON DISK
655  /* do the dump */
656  (*(iface->dumpFunc))(argi, argc, argv, main_obj, dumpNum, dumpTime);
657 
658  dt = MT_StopTimer(heavy_dump_tid);
659 
660 #ifdef HAVE_SCR
661  if (exercise_scr)
662  SCR_Complete_checkpoint(scr_valid);
663 #endif
664  }
665 
666  /* stop timer */
667  dumpTime += dt;
668  dumpBytes += problem_nbytes;
669  dumpCount += 1;
670 
671  /* log dump timing */
672  MACSIO_LOG_MSG(Info, ("Dump %02d BW: %s/%s = %s", dumpNum,
673  MU_PrByts(problem_nbytes, 0, nbytes_str, sizeof(nbytes_str)),
674  MU_PrSecs(dt, 0, seconds_str, sizeof(seconds_str)),
675  MU_PrBW(problem_nbytes, dt, 0, bandwidth_str, sizeof(bandwidth_str))));
676  }
677 
678  dump_loop_end = MT_Time();
679 
680  MACSIO_LOG_MSG(Info, ("Overall BW: %s/%s = %s",
681  MU_PrByts(dumpBytes, 0, nbytes_str, sizeof(nbytes_str)),
682  MU_PrSecs(dumpTime, 0, seconds_str, sizeof(seconds_str)),
683  MU_PrBW(dumpBytes, dumpTime, 0, bandwidth_str, sizeof(bandwidth_str))));
684 
685  bandwidth = dumpBytes / dumpTime;
686  summedBandwidth = bandwidth;
687  min_dump_loop_start = dump_loop_start;
688  max_dump_loop_end = dump_loop_end;
689 
690 #ifdef HAVE_MPI
691  MPI_Comm_rank(MACSIO_MAIN_Comm, &rank);
692  MPI_Reduce(&bandwidth, &summedBandwidth, 1, MPI_DOUBLE, MPI_SUM, 0, MACSIO_MAIN_Comm);
693  MPI_Reduce(&dumpBytes, &summedBytes, 1, MPI_UNSIGNED_LONG_LONG, MPI_SUM, 0, MACSIO_MAIN_Comm);
694  MPI_Reduce(&dump_loop_start, &min_dump_loop_start, 1, MPI_DOUBLE, MPI_MIN, 0, MACSIO_MAIN_Comm);
695  MPI_Reduce(&dump_loop_end, &max_dump_loop_end, 1, MPI_DOUBLE, MPI_MAX, 0, MACSIO_MAIN_Comm);
696 #endif
697 
698  if (rank == 0)
699  {
700  MACSIO_LOG_MSG(Info, ("Summed BW: %s",
701  MU_PrBW(summedBandwidth, 1.0, 0, bandwidth_str, sizeof(bandwidth_str))));
702  MACSIO_LOG_MSG(Info, ("Total Bytes: %s; Last finisher - First starter = %s; BW = %s",
703  MU_PrByts(summedBytes, 0, nbytes_str, sizeof(nbytes_str)),
704  MU_PrSecs(max_dump_loop_end - min_dump_loop_start, 0, seconds_str, sizeof(seconds_str)),
705  MU_PrBW(summedBytes, max_dump_loop_end - min_dump_loop_start, 0, bandwidth_str, sizeof(bandwidth_str))));
706  }
707 }
708 
709 #warning DO WE REALLY CALL IT THE MAIN_OBJ HERE
710 static int
711 main_read(int argi, int argc, char **argv, json_object *main_obj)
712 {
713  int loadNum;
714  MACSIO_TIMING_GroupMask_t main_rd_grp = MACSIO_TIMING_GroupMask("main_read");
715 
716  for (loadNum = 0; loadNum < json_object_path_get_int(main_obj, "clargs/num_loads"); loadNum++)
717  {
718  json_object *data_read_obj;
719  MACSIO_TIMING_TimerId_t heavy_load_tid;
720 
722  json_object_path_get_string(main_obj, "clargs/interface"));
723 
724  /* log load start */
725 
726  /* Start load timer */
727  heavy_load_tid = MT_StartTimer("heavy load", main_rd_grp, loadNum);
728 
729  /* do the load */
730  (*(iface->loadFunc))(argi, argc, argv,
731  JsonGetStr(main_obj, "clargs/read_path"), main_obj, &data_read_obj);
732 
733  /* stop timer */
734  MT_StopTimer(heavy_load_tid);
735 
736  /* log load completion */
737 
738  /* Validate the data */
739  if (JsonGetBool(main_obj, "clargs/validate_read"))
740  MACSIO_DATA_ValidateDataRead(data_read_obj);
741  }
742 
743  /* Just here for debugging for the moment */
744  if (MACSIO_LOG_DebugLevel >= 3)
745  {
746  char outfName[256];
747  FILE *outf;
748  snprintf(outfName, sizeof(outfName), "main_obj_read_%03d.json", MACSIO_MAIN_Rank);
749  outf = fopen(outfName, "w");
750  fprintf(outf, "\"%s\"\n", json_object_to_json_string_ext(main_obj, JSON_C_TO_STRING_PRETTY));
751  fclose(outf);
752  }
753 }
754 
755 int
756 main(int argc, char *argv[])
757 {
758  json_object *main_obj = json_object_new_object();
759  json_object *parallel_obj = json_object_new_object();
760  json_object *problem_obj = 0;
761  json_object *clargs_obj = 0;
762  MACSIO_TIMING_GroupMask_t main_grp;
763  MACSIO_TIMING_TimerId_t main_tid;
764  int i, argi, exercise_scr = 0;
765  int size = 1, rank = 0;
766 
767  /* quick pre-scan for scr cl flag */
768  for (i = 0; i < argc && !exercise_scr; i++)
769  exercise_scr = !strcmp("exercise_scr", argv[i]);
770 
771 #warning SHOULD WE BE USING MPI-3 API
772 #ifdef HAVE_MPI
773  MPI_Init(&argc, &argv);
774 #ifdef HAVE_SCR
775 #warning SANITY CHECK WITH MIFFPP
776  if (exercise_scr)
777  SCR_Init();
778 #endif
779  MPI_Comm_dup(MPI_COMM_WORLD, &MACSIO_MAIN_Comm);
780  MPI_Errhandler_set(MACSIO_MAIN_Comm, MPI_ERRORS_RETURN);
781  MPI_Comm_size(MACSIO_MAIN_Comm, &MACSIO_MAIN_Size);
782  MPI_Comm_rank(MACSIO_MAIN_Comm, &MACSIO_MAIN_Rank);
783  mpi_errno = MPI_SUCCESS;
784 #endif
785  errno = 0;
786 
787  main_grp = MACSIO_TIMING_GroupMask("MACSIO main()");
788  main_tid = MT_StartTimer("main", main_grp, MACSIO_TIMING_ITER_AUTO);
789 
791 
792  /* Process the command line and put the results in the problem */
793  clargs_obj = ProcessCommandLine(argc, argv, &argi);
794  json_object_object_add(main_obj, "clargs", clargs_obj);
795 
796  strncpy(MACSIO_UTILS_UnitsPrefixSystem, JsonGetStr(clargs_obj, "units_prefix_system"),
798 
800  JsonGetStr(clargs_obj, "log_file_name"),
801  JsonGetInt(clargs_obj, "log_line_length"),
802  JsonGetInt(clargs_obj, "log_line_cnt/0"),
803  JsonGetInt(clargs_obj, "log_line_cnt/1"));
804 
805 #warning THESE INITIALIZATIONS SHOULD BE IN MACSIO_LOG
806  MACSIO_LOG_DebugLevel = JsonGetInt(clargs_obj, "debug_level");
807 
808  /* Setup parallel information */
809  json_object_object_add(parallel_obj, "mpi_size", json_object_new_int(MACSIO_MAIN_Size));
810  json_object_object_add(parallel_obj, "mpi_rank", json_object_new_int(MACSIO_MAIN_Rank));
811  json_object_object_add(main_obj, "parallel", parallel_obj);
812 
813 #warning SHOULD WE INCLUDE TOP-LEVEL INFO ON VAR NAMES AND WHETHER THEYRE RESTRICTED
814 #warning CREATE AN IO CONTEXT OBJECT
815  /* Acquire an I/O context handle from the plugin */
816 
817  /* Do a read or write test */
818  if (strcmp(JsonGetStr(clargs_obj, "read_path"),"null"))
819  main_read(argi, argc, argv, main_obj);
820  else
821  main_write(argi, argc, argv, main_obj);
822 
823  /* stop total timer */
824  MT_StopTimer(main_tid);
825 
826  /* Write timings data file if requested */
827  if (strlen(JsonGetStr(clargs_obj, "timings_file_name")))
828  write_timings_file(JsonGetStr(clargs_obj, "timings_file_name"));
829 
831 
832 #warning ATEXIT THESE
835 
836 #ifdef HAVE_SCR
837  if (exercise_scr)
838  SCR_Finalize();
839 #endif
840 
841 #ifdef HAVE_MPI
842  { int result;
843  if ((MPI_Initialized(&result) == MPI_SUCCESS) && result)
844  MPI_Finalize();
845  }
846 #endif
847 
848  return (0);
849 }
static void handle_help_request_and_exit(int argi, int argc, char **argv)
Definition: macsio_main.c:287
int MACSIO_DATA_ValidateDataRead(json_object *main_obj)
Definition: macsio_data.c:955
#define MACSIO_LOG_MSGL(LOG, SEV, MSG)
Convenience macro for logging a message to any specific log.
Definition: macsio_log.h:163
void MACSIO_TIMING_ReduceTimers(MPI_Comm comm, int root)
Reduce timers across MPI tasks.
static json_object * ProcessCommandLine(int argc, char *argv[], int *plugin_argi)
Definition: macsio_main.c:338
#define MT_StopTimer(ID)
Convenience macro for stopping a timer.
MACSIO_LOG_LogHandle_t * MACSIO_LOG_StdErr
Log handle for MACSIO's stderr output.
Definition: macsio_log.c:46
static const char * filename
Definition: macsio_hdf5.c:683
#define JsonGetStr(OBJ,...)
Get the string value at specified path.
Definition: json_object.h:765
#define MACSIO_CLARGS_WARN
Definition: macsio_clargs.h:35
void MACSIO_TIMING_ClearTimers(MACSIO_TIMING_GroupMask_t gmask)
Clear a group of timers.
#define MACSIO_TIMING_ALL_GROUPS
Group mask representing all groups.
struct json_object * json_object_new_object(void)
Definition: json_object.c:369
int mpi_errno
Error code returned by most recent MPI call.
Definition: macsio_log.c:43
MACSIO_LOG_LogHandle_t * MACSIO_LOG_LogInit(MPI_Comm comm, char const *path, int line_len, int lines_per_proc, int extra_lines_proc0)
Initialize a log.
Definition: macsio_log.c:113
#define JSON_C_TO_STRING_NO_EXTARR_VALS
Definition: json_object.h:62
#define MACSIO_CLARGS_ARG_GROUP_END(GRPNAME)
Definition: macsio_clargs.h:52
#define MU_PrSecs(S, FMT, STR, N)
Definition: macsio_utils.h:58
#define MT_Time
Convenience macro for getting current time.
int MACSIO_CLARGS_ProcessCmdline(void **retobj, MACSIO_CLARGS_ArgvFlags_t flags, int argi, int argc, char **argv,...)
unsigned long long MACSIO_TIMING_GroupMask_t
int64_t json_object_object_nbytes(struct json_object *const obj)
Definition: json_object.c:2295
void MACSIO_LOG_LogFinalize(MACSIO_LOG_LogHandle_t *log)
Finalize and close an open log Should be called collectively by all processors that created the log...
Definition: macsio_log.c:295
unsigned int MACSIO_TIMING_TimerId_t
void MACSIO_IFACE_GetIds(int *cnt, int **ids)
Definition: macsio_iface.c:88
#define MU_PrBW(B, S, FMT, STR, N)
Definition: macsio_utils.h:59
int MACSIO_LOG_DebugLevel
Definition: macsio_log.c:44
MACSIO_IFACE_Handle_t const * MACSIO_IFACE_GetByName(char const *name)
Definition: macsio_iface.c:100
ProcessArgsFunc processArgsFunc
Definition: macsio_iface.h:59
struct json_object * json_object_new_int(int32_t i)
Definition: json_object.c:495
static int write_timings_file(char const *filename)
Definition: macsio_main.c:535
MACSIO_LOG_LogHandle_t * MACSIO_LOG_MainLog
Log handle for MACSIO's main log.
Definition: macsio_log.c:45
#define JsonGetBool(OBJ,...)
Get the bool value at specified path.
Definition: json_object.h:741
MACSIO_IFACE_Handle_t const * MACSIO_IFACE_GetById(int i)
Definition: macsio_iface.c:93
char ** enviornp
#define JsonGetInt(OBJ,...)
Get the int value at specified path.
Definition: json_object.h:747
static int main_read(int argi, int argc, char **argv, json_object *main_obj)
Definition: macsio_main.c:711
#define MACSIO_CLARGS_END_OF_ARGS
Definition: macsio_clargs.h:53
#define MACSIO_CLARGS_NODEFAULT
Definition: macsio_clargs.h:54
int MACSIO_MAIN_Rank
Definition: macsio_main.c:285
void MACSIO_LOG_LogMsg(MACSIO_LOG_LogHandle_t const *log, char const *fmt,...)
Issue a printf-style message to a log.
Definition: macsio_log.c:186
char const * json_object_path_get_string(struct json_object *src, char const *key_path)
Get a string value for the object at specified path.
Definition: json_object.c:2198
void MACSIO_TIMING_DumpReducedTimersToStrings(MACSIO_TIMING_GroupMask_t gmask, char ***strs, int *nstrs, int *maxlen)
Dump reduced timers to ascii strings.
json_object * MACSIO_DATA_GenerateTimeZeroDumpObject(json_object *main_obj, int *rank_owning_chunkId)
Definition: macsio_data.c:837
#define MT_StartTimer(LAB, GMASK, ITER)
Convenience macro for starting a timer.
#define MACSIO_CLARGS_HELP
Definition: macsio_clargs.h:46
#define MACSIO_CLARGS_ARG_GROUP_BEG(GRPNAME)
Definition: macsio_clargs.h:51
char MACSIO_UTILS_UnitsPrefixSystem[32]
Definition: macsio_utils.c:34
#define JSON_C_TO_STRING_PRETTY
Definition: json_object.h:55
int MACSIO_MAIN_Size
Definition: macsio_main.c:284
char name[MACSIO_IFACE_MAX_NAME]
Definition: macsio_iface.h:54
#define MACSIO_CLARGS_TOJSON
Definition: macsio_clargs.h:40
void MACSIO_TIMING_DumpTimersToStrings(MACSIO_TIMING_GroupMask_t gmask, char ***strs, int *nstrs, int *maxlen)
Dump timers to ascii strings.
static int main_write(int argi, int argc, char **argv, json_object *main_obj)
Definition: macsio_main.c:581
char const * MACSIO_IFACE_GetName(int i)
Definition: macsio_iface.c:60
#define JSON_C_TO_STRING_SPACED
Definition: json_object.h:46
const char * json_object_to_json_string_ext(struct json_object *obj, int flags)
Definition: json_object.c:277
int32_t json_object_path_get_int(struct json_object *src, char const *key_path)
Get integer value for object at specified path.
Definition: json_object.c:2103
#define MU_PrByts(B, FMT, STR, N)
Definition: macsio_utils.h:57
MACSIO_TIMING_GroupMask_t MACSIO_TIMING_GroupMask(char const *grpName)
Create a group name and mask.
MPI_Comm MACSIO_MAIN_Comm
Definition: macsio_main.c:279
int main(int argc, char *argv[])
Definition: macsio_main.c:756
static void handle_list_request_and_exit()
Definition: macsio_main.c:311
#define MACSIO_LOG_MSG(SEV, MSG)
Convenience macro for logging a message to the main log.
Definition: macsio_log.h:133
void json_object_object_add(struct json_object *obj, const char *key, struct json_object *val)
Definition: json_object.c:391
#define MACSIO_TIMING_ITER_AUTO
Automatic iteration numbering Use for iter argument to StartTimer() when you don't want to manager it...
Definition: macsio_timing.h:97