CernVM-FS  2.13.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
receiver.cc
Go to the documentation of this file.
1 
5 #include <string>
6 
7 
8 
9 #include "monitor.h"
10 #include "swissknife.h"
11 #include "util/exception.h"
12 #include "util/logging.h"
13 #include "util/posix.h"
14 #include "util/string.h"
15 
16 #include "reactor.h"
17 
18 static const char *kDefaultReceiverLogDir = "/var/log/cvmfs_receiver/";
19 static const char *kDefaultDebugLog = "/dev/null";
20 
23  params.push_back(
24  swissknife::Parameter::Optional('i', "File descriptor to use for input"));
25  params.push_back(swissknife::Parameter::Optional(
26  'o', "File descriptor to use for output"));
27  params.push_back(swissknife::Parameter::Optional(
28  'w', "Watchdog stacktrace output dir, "
29  "use without parameter to disable watchdog. "
30  "Default: " + std::string(kDefaultReceiverLogDir)));
31  params.push_back(swissknife::Parameter::Optional(
32  'd', "Path to debug log. Ignored if the non-debug version runs, "
33  "Default: " + std::string(kDefaultDebugLog)));
34  return params;
35 }
36 
37 bool ReadCmdLineArguments(int argc, char** argv,
38  const swissknife::ParameterList& params,
39  swissknife::ArgumentList* arguments) {
40  // parse the command line arguments for the Command
41  optind = 1;
42  std::string option_string = "";
43 
44  for (unsigned j = 0; j < params.size(); ++j) {
45  option_string.push_back(params[j].key());
46  if (!params[j].switch_only()) option_string.push_back(':');
47  }
48 
49  int c;
50  while ((c = getopt(argc, argv, option_string.c_str())) != -1) {
51  bool valid_option = false;
52  for (unsigned j = 0; j < params.size(); ++j) {
53  if (c == params[j].key()) {
54  valid_option = true;
55  (*arguments)[c].Reset();
56  if (!params[j].switch_only()) {
57  (*arguments)[c].Reset(new std::string(optarg));
58  }
59  break;
60  }
61  }
62 
63  if (!valid_option) {
65  "CVMFS gateway services receiver component. Usage:");
66  for (size_t i = 0; i < params.size(); ++i) {
67  LogCvmfs(kLogReceiver, kLogSyslog, " \"%c\" - %s", params[i].key(),
68  params[i].description().c_str());
69  }
70  return false;
71  }
72  }
73 
74  for (size_t j = 0; j < params.size(); ++j) {
75  if (!params[j].optional()) {
76  if (arguments->find(params[j].key()) == arguments->end()) {
77  LogCvmfs(kLogReceiver, kLogSyslogErr, "parameter -%c missing",
78  params[j].key());
79  return false;
80  }
81  }
82  }
83 
84  return true;
85 }
86 
87 int main(int argc, char** argv) {
88  swissknife::ArgumentList arguments;
89  if (!ReadCmdLineArguments(argc, argv, MakeParameterList(), &arguments)) {
90  return 1;
91  }
92 
93  // The receiver is spawned from the gateway go service. The gateway connects
94  // a pipe to stdout and stderr but will collect the results only at the end.
95  // This means that only small pieces of output can be send to stdout or
96  // stderr, otherwise the pipes run full and block.
97  // This should probably be addressed.
98  //
99  // For the debug mode, the gateway sets a debug log file that is collected
100  // after the application quits.
101 
103  SetLogSyslogShowPID(true);
104 
105  int fdin = 0;
106  int fdout = 1;
107  std::string watchdog_out_dir = kDefaultReceiverLogDir;
108  std::string debug_log = kDefaultDebugLog;
109  if (arguments.find('i') != arguments.end()) {
110  fdin = std::atoi(arguments.find('i')->second->c_str());
111  }
112  if (arguments.find('o') != arguments.end()) {
113  fdout = std::atoi(arguments.find('o')->second->c_str());
114  }
115  if (arguments.find('w') != arguments.end()) {
116  watchdog_out_dir = *arguments.find('w')->second;
117  }
118  if (arguments.find('d') != arguments.end()) {
119  debug_log = *arguments.find('d')->second;
120  }
121 
122  // The gateway hard-codes this to /var/log/cvmfs_receiver/debug.log
123  SetLogDebugFile(debug_log);
124 
125  // Spawn monitoring process (watchdog)
126  UniquePtr<Watchdog> watchdog;
127  if (watchdog_out_dir != "") {
128  if (!MkdirDeep(watchdog_out_dir, 0755)) {
130  "Failed to create stacktrace directory: %s",
131  watchdog_out_dir.c_str());
132  return 1;
133  }
134  std::string timestamp = GetGMTimestamp("%Y.%m.%d-%H.%M.%S");
135  watchdog = Watchdog::Create(NULL);
136  if (watchdog.IsValid() == false) {
138  "Failed to initialize watchdog");
139  return 1;
140  }
141  watchdog->Spawn(watchdog_out_dir + "/stacktrace." + timestamp);
142  }
143 
144  LogCvmfs(kLogReceiver, kLogSyslog, "CVMFS receiver started");
145 
146  receiver::Reactor reactor(fdin, fdout);
147 
148  try {
149  if (!reactor.Run()) {
151  "Error running CVMFS Receiver event loop");
152  return 1;
153  }
154  } catch (const ECvmfsException& e) {
156  "Runtime error during CVMFS Receiver event loop.\n"
157  "%s",
158  e.what());
159  return 2;
160  } catch (...) {
162  "Unknown error during CVMFS Receiver event loop.\n");
163  return 3;
164  }
165 
166  LogCvmfs(kLogReceiver, kLogSyslog, "CVMFS receiver finished");
167 
168  return 0;
169 }
static Parameter Optional(const char key, const std::string &desc)
Definition: swissknife.h:41
void SetLogSyslogFacility(const int local_facility)
Definition: logging.cc:183
std::string GetGMTimestamp(const std::string &format)
Definition: string.cc:633
static const char * kDefaultDebugLog
Definition: receiver.cc:19
void SetLogSyslogShowPID(bool flag)
Definition: logging.cc:254
std::vector< Parameter > ParameterList
Definition: swissknife.h:71
#define SetLogDebugFile(filename)
static const char * kDefaultReceiverLogDir
Definition: receiver.cc:18
int main()
Definition: helper_allow.cc:16
static Watchdog * Create(FnOnCrash on_crash)
Definition: monitor.cc:70
bool MkdirDeep(const std::string &path, const mode_t mode, bool verify_writable)
Definition: posix.cc:857
bool ReadCmdLineArguments(int argc, char **argv, const swissknife::ParameterList &params, swissknife::ArgumentList *arguments)
Definition: receiver.cc:37
swissknife::ParameterList MakeParameterList()
Definition: receiver.cc:21
std::map< char, SharedPtr< std::string > > ArgumentList
Definition: swissknife.h:72
void Spawn(const std::string &crash_dump_path)
Definition: monitor.cc:510
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)
Definition: logging.cc:528