00001 /*<std-header orig-src='shore'> 00002 00003 $Id: init_config_options.cpp,v 1.5 2010/09/21 14:26:28 nhall Exp $ 00004 00005 SHORE -- Scalable Heterogeneous Object REpository 00006 00007 Copyright (c) 1994-99 Computer Sciences Department, University of 00008 Wisconsin -- Madison 00009 All Rights Reserved. 00010 00011 Permission to use, copy, modify and distribute this software and its 00012 documentation is hereby granted, provided that both the copyright 00013 notice and this permission notice appear in all copies of the 00014 software, derivative works or modified versions, and any portions 00015 thereof, and that both notices appear in supporting documentation. 00016 00017 THE AUTHORS AND THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY 00018 OF WISCONSIN - MADISON ALLOW FREE USE OF THIS SOFTWARE IN ITS 00019 "AS IS" CONDITION, AND THEY DISCLAIM ANY LIABILITY OF ANY KIND 00020 FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 00021 00022 This software was developed with support by the Advanced Research 00023 Project Agency, ARPA order number 018 (formerly 8230), monitored by 00024 the U.S. Army Research Laboratory under contract DAAB07-91-C-Q518. 00025 Further funding for this work was provided by DARPA through 00026 Rome Research Laboratory Contract No. F30602-97-2-0247. 00027 00028 */ 00029 00030 #include "w_defines.h" 00031 00032 /* -- do not edit anything above this line -- </std-header>*/ 00033 00034 /**\anchor init_config_options_example */ 00035 /* 00036 * This file illustrates processing of run-time options 00037 * from the command line and from a file. 00038 * The options are processed in a single static function, 00039 * init_config_options. 00040 * 00041 * It is used by several of the storage manager examples. 00042 */ 00043 00044 00045 /* Since this file only deals with the SSM option package, 00046 * rather than including sm_vas.h, just include what's needed for 00047 * options: 00048 */ 00049 #include <w_stream.h> 00050 #include <cstring> 00051 #include "w.h" 00052 #include "option.h" 00053 #include <w_strstream.h> 00054 00055 /* 00056 * init_config_options() 00057 * 00058 * The first argument, the options parameter, 00059 * is the option group holding all the options. It must have 00060 * been created by the caller. 00061 * 00062 * This is designed to be called by server-side code and 00063 * by client-side code, so it uses a 3-level hierarchy for 00064 * naming the options: example.<server-or-client>.<program-name>, 00065 * where, presumably, the server-side code will be written to 00066 * call this with the 00067 * second argument, prog_type, to be "server", and the 00068 * client-side code will use "client" for the prog_type argument. 00069 * This function, however, doesn't care what the value of 00070 * prog_type is; it just inserts it in the hierarchy. 00071 * 00072 * In the server-side case, because (presumably) the storage manager will be used, 00073 * the storage manager options must have been added to the options group before this 00074 * function is called. 00075 * 00076 * If the argc and argv parameters are argc and argv from main(), then the 00077 * executables can be invoked with storage manager options on the command-line, e.g., 00078 * <argv0> -sm_logdir /tmp/logdir -sm_num_page_writers 4 00079 * 00080 * Recognized options will be located in argv and removed from the argv list, and 00081 * argc is changed to reflect the removal, which is why it is passed by 00082 * reference. 00083 * After this function is used, the calling code can process the remainder 00084 * of the command line without interference by storage manager option-value 00085 * pairs. 00086 * 00087 * In this function, we have hard-wired the name of the file (EXAMPLE_SHORECONFIG) to be 00088 * read for options values, and we have hard-wired the options' class hierarchy to be 00089 * example.<prog_type>.<program-name> 00090 * 00091 * You might not want to use such a hierarchy -- if you don't have client- and server- 00092 * side executables for the same "program", and if you don't want to collect 00093 * options for different programs in the same file, you might dispense with the 00094 * hierarchy. 00095 */ 00096 00097 w_rc_t 00098 init_config_options( 00099 option_group_t& options, 00100 const char* prog_type, 00101 int& argc, 00102 char** argv) 00103 { 00104 w_rc_t rc; // return code 00105 00106 // set prog_name to the file name of the program without the path 00107 char* prog_name = strrchr(argv[0], '/'); 00108 if (prog_name == NULL) { 00109 prog_name = argv[0]; 00110 } else { 00111 prog_name += 1; /* skip the '/' */ 00112 if (prog_name[0] == '\0') { 00113 prog_name = argv[0]; 00114 } 00115 } 00116 00117 W_DO(options.add_class_level("example")); 00118 W_DO(options.add_class_level(prog_type)); // server or client 00119 W_DO(options.add_class_level(prog_name)); // program name 00120 00121 // read the example config file to set options 00122 { 00123 w_ostrstream err_stream; 00124 const char* opt_file = "EXAMPLE_SHORECONFIG"; // option config file 00125 option_file_scan_t opt_scan(opt_file, &options); 00126 00127 // Scan the file and override any default option settings. 00128 // Options names must be spelled correctly 00129 rc = opt_scan.scan(true /*override*/, 00130 err_stream, 00131 true /*option names must be complete and correct*/ ); 00132 if (rc.is_error()) { 00133 cerr << "Error in reading option file: " << opt_file << endl; 00134 cerr << "\t" << err_stream.c_str() << endl; 00135 return rc; 00136 } 00137 } 00138 00139 // parse command line for more options. 00140 if (!rc.is_error()) { 00141 // parse command line 00142 w_ostrstream err_stream; 00143 rc = options.parse_command_line( 00144 (const char **)argv, 00145 argc, 00146 2, /* minimum length of an option name*/ 00147 &err_stream /* send error messages here */ 00148 ); 00149 err_stream << ends; 00150 if (rc.is_error()) { 00151 cerr << "Error on Command line " << endl; 00152 cerr << "\t" << w_error_t::error_string(rc.err_num()) << endl; 00153 cerr << "\t" << err_stream.c_str() << endl; 00154 return rc; 00155 } 00156 } 00157 00158 // check required options for values 00159 { 00160 w_ostrstream err_stream; 00161 rc = options.check_required(&err_stream); 00162 if (rc.is_error()) { 00163 cerr << "These required options are not set:" << endl; 00164 cerr << err_stream.c_str() << endl; 00165 return rc; 00166 } 00167 } 00168 00169 return RCOK; 00170 }