GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/receiver/receiver.cc
Date: 2025-04-20 02:34:28
Exec Total Coverage
Lines: 0 78 0.0%
Branches: 0 170 0.0%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4
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
21 swissknife::ParameterList MakeParameterList() {
22 swissknife::ParameterList params;
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) {
64 LogCvmfs(kLogReceiver, kLogSyslog,
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
102 SetLogSyslogFacility(1);
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)) {
129 LogCvmfs(kLogReceiver, kLogSyslogErr | kLogStderr,
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) {
137 LogCvmfs(kLogReceiver, kLogSyslogErr | kLogStderr,
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()) {
150 LogCvmfs(kLogReceiver, kLogSyslogErr,
151 "Error running CVMFS Receiver event loop");
152 return 1;
153 }
154 } catch (const ECvmfsException& e) {
155 LogCvmfs(kLogReceiver, kLogSyslogErr,
156 "Runtime error during CVMFS Receiver event loop.\n"
157 "%s",
158 e.what());
159 return 2;
160 } catch (...) {
161 LogCvmfs(kLogReceiver, kLogSyslogErr,
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 }
170