LogCabin
|
00001 /* Copyright (c) 2012 Stanford University 00002 * 00003 * Permission to use, copy, modify, and distribute this software for any 00004 * purpose with or without fee is hereby granted, provided that the above 00005 * copyright notice and this permission notice appear in all copies. 00006 * 00007 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES 00008 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 00009 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR 00010 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 00011 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 00012 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 00013 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 00014 */ 00015 00016 #include <cassert> 00017 #include <getopt.h> 00018 #include <iostream> 00019 00020 #include <LogCabin/Client.h> 00021 #include <LogCabin/Debug.h> 00022 #include <LogCabin/Util.h> 00023 00024 namespace { 00025 00026 using LogCabin::Client::Cluster; 00027 using LogCabin::Client::Tree; 00028 using LogCabin::Client::Util::parseNonNegativeDuration; 00029 00030 /** 00031 * Parses argv for the main function. 00032 */ 00033 class OptionParser { 00034 public: 00035 OptionParser(int& argc, char**& argv) 00036 : argc(argc) 00037 , argv(argv) 00038 , cluster("logcabin:5254") 00039 , logPolicy("") 00040 , timeout(parseNonNegativeDuration("0s")) 00041 { 00042 while (true) { 00043 static struct option longOptions[] = { 00044 {"cluster", required_argument, NULL, 'c'}, 00045 {"help", no_argument, NULL, 'h'}, 00046 {"timeout", required_argument, NULL, 't'}, 00047 {"verbose", no_argument, NULL, 'v'}, 00048 {"verbosity", required_argument, NULL, 256}, 00049 {0, 0, 0, 0} 00050 }; 00051 int c = getopt_long(argc, argv, "c:t:hv", longOptions, NULL); 00052 00053 // Detect the end of the options. 00054 if (c == -1) 00055 break; 00056 00057 switch (c) { 00058 case 'c': 00059 cluster = optarg; 00060 break; 00061 case 't': 00062 timeout = parseNonNegativeDuration(optarg); 00063 break; 00064 case 'h': 00065 usage(); 00066 exit(0); 00067 case 'v': 00068 logPolicy = "VERBOSE"; 00069 break; 00070 case 256: 00071 logPolicy = optarg; 00072 break; 00073 case '?': 00074 default: 00075 // getopt_long already printed an error message. 00076 usage(); 00077 exit(1); 00078 } 00079 } 00080 } 00081 00082 void usage() { 00083 std::cout 00084 << "Writes a value to LogCabin. This isn't very useful on its own " 00085 << "but serves as a" 00086 << std::endl 00087 << "good starting point for more sophisticated LogCabin client " 00088 << "programs." 00089 << std::endl 00090 << std::endl 00091 << "This program is subject to change (it is not part of " 00092 << "LogCabin's stable API)." 00093 << std::endl 00094 << std::endl 00095 00096 << "Usage: " << argv[0] << " [options]" 00097 << std::endl 00098 << std::endl 00099 00100 << "Options:" 00101 << std::endl 00102 00103 << " -c <addresses>, --cluster=<addresses> " 00104 << "Network addresses of the LogCabin" 00105 << std::endl 00106 << " " 00107 << "servers, comma-separated" 00108 << std::endl 00109 << " " 00110 << "[default: logcabin:5254]" 00111 << std::endl 00112 00113 << " -h, --help " 00114 << "Print this usage information" 00115 << std::endl 00116 00117 << " -t <time>, --timeout=<time> " 00118 << "Set timeout for individual operations" 00119 << std::endl 00120 << " " 00121 << "(0 means wait forever) [default: 0s]" 00122 << std::endl 00123 00124 << " -v, --verbose " 00125 << "Same as --verbosity=VERBOSE" 00126 << std::endl 00127 00128 << " --verbosity=<policy> " 00129 << "Set which log messages are shown." 00130 << std::endl 00131 << " " 00132 << "Comma-separated LEVEL or PATTERN@LEVEL rules." 00133 << std::endl 00134 << " " 00135 << "Levels: SILENT ERROR WARNING NOTICE VERBOSE." 00136 << std::endl 00137 << " " 00138 << "Patterns match filename prefixes or suffixes." 00139 << std::endl 00140 << " " 00141 << "Example: Client@NOTICE,Test.cc@SILENT,VERBOSE." 00142 << std::endl; 00143 } 00144 00145 int& argc; 00146 char**& argv; 00147 std::string cluster; 00148 std::string logPolicy; 00149 uint64_t timeout; 00150 }; 00151 00152 } // anonymous namespace 00153 00154 int 00155 main(int argc, char** argv) 00156 { 00157 try { 00158 00159 OptionParser options(argc, argv); 00160 LogCabin::Client::Debug::setLogPolicy( 00161 LogCabin::Client::Debug::logPolicyFromString( 00162 options.logPolicy)); 00163 Cluster cluster(options.cluster); 00164 Tree tree = cluster.getTree(); 00165 tree.setTimeout(options.timeout); 00166 tree.makeDirectoryEx("/etc"); 00167 tree.writeEx("/etc/passwd", "ha"); 00168 std::string contents = tree.readEx("/etc/passwd"); 00169 assert(contents == "ha"); 00170 tree.removeDirectoryEx("/etc"); 00171 return 0; 00172 00173 } catch (const LogCabin::Client::Exception& e) { 00174 std::cerr << "Exiting due to LogCabin::Client::Exception: " 00175 << e.what() 00176 << std::endl; 00177 exit(1); 00178 } 00179 }