23 #include "../bblogfile.h"
25 #include <utils/system/argparser.h>
26 #include <utils/system/signal.h>
27 #include <utils/time/time.h>
28 #include <utils/system/fam.h>
30 #include <blackboard/remote.h>
31 #include <blackboard/internal/instance_factory.h>
32 #include <interfaces/SwitchInterface.h>
38 #include <arpa/inet.h>
39 #include <sys/types.h>
44 using namespace fawkes;
47 print_usage(
const char *program_name)
49 printf(
"Usage: %s [-h] [-r host:port] <COMMAND> <logfile>\n"
50 " %s print <logfile> <index> [index ...]\n"
51 " %s convert <infile> <outfile> <format>\n"
53 " -h Print this usage information\n"
55 " watch Continuously watch a log file (like tail)\n"
56 " info Print meta information of log file\n"
57 " print Print specific data index\n"
58 " <index> [index ...] is a list of indices to print\n"
59 " replay Replay log file in real-time to console\n"
60 " repair Repair file, i.e. properly set number of entries\n"
61 " enable Enable logging on a remotely running bblogger\n"
62 " disable Disable logging on a remotely running bblogger\n"
63 " convert Convert logfile to different format\n"
64 " <infile> input log file\n"
65 " <outfile> converted output file\n"
66 " <format> format to convert to, currently supported:\n"
67 " - csv Comma-separated values\n",
68 program_name, program_name, program_name);
73 print_info(std::string &filename)
80 printf(
"Failed to print info, exception follows\n");
87 repair_file(std::string &filename)
91 printf(
"Nothing to repair, files are fine\n");
94 if (strcmp(e.
type_id(),
"repair-success") == 0) {
95 printf(
"Repair successful, actions done follow.\n");
99 printf(
"Repair failed, exception follows.\n");
107 print_indexes(std::string &filename, std::vector<unsigned int> &indexes)
111 for (
unsigned int i = 0; i < indexes.size(); ++i) {
117 printf(
"Failed to print info, exception follows\n");
126 replay_file(std::string &filename)
131 Time last_offset((
long)0);
133 if (! bf.has_next()) {
134 printf(
"File does not have any entries, aborting.\n");
142 last_offset = bf.entry_offset();
145 while (bf.has_next()) {
147 diff = bf.entry_offset() - last_offset;
149 last_offset = bf.entry_offset();
154 printf(
"Failed to print info, exception follows\n");
168 BBLogWatcher(
const char *filename,
BBLogFile &file)
173 __fam->add_listener(
this);
174 __fam->watch_file(filename);
180 __fam->remove_listener(
this);
184 virtual void fam_event(
const char *filename,
unsigned int mask)
186 if (mask & FAM_DELETE) {
190 unsigned int remaining = __file.remaining_entries();
191 for (
unsigned int i = 0; i < remaining; ++i) {
193 __file.print_entry();
198 virtual void handle_signal(
int signal)
207 __fam->process_events(-1);
219 watch_file(std::string &filename)
221 BBLogFile file(filename.c_str(), NULL,
false);
226 BBLogWatcher watcher(filename.c_str(), file);
234 set_enabled(
const char *hostname,
unsigned short int port,
bool enabled)
241 printf(
"No writer exists, BBLogger not loaded?\n");
259 convert_file_csv(
BBLogFile &bf, FILE *outf)
264 fprintf(outf,
"# Time relative to beginning (in sec)");
267 fprintf(outf,
";%s (%s[%zu])",
278 fprintf(outf,
";%s", i.get_value_string());
286 convert_file(std::string &infile, std::string &outfile, std::string &format)
288 if (format !=
"csv") {
289 printf(
"Unsupported output format '%s'\n", format.c_str());
293 FILE *outf = fopen(outfile.c_str(),
"wx");
295 perror(
"Failed to open output file");
303 if (format ==
"csv") {
304 convert_file_csv(bf, outf);
308 printf(
"Failed to convert log file: %s\n", e.
what());
324 main(
int argc,
char **argv)
328 if ( argp.has_arg(
"h") ) {
329 print_usage(argv[0]);
333 std::string command, file;
334 if (argp.num_items() < 1) {
335 printf(
"Invalid number of arguments\n");
336 print_usage(argv[0]);
338 }
else if (argp.num_items() >= 2) {
339 file = argp.items()[1];
342 command = argp.items()[0];
344 if (command ==
"watch") {
345 return watch_file(file);
347 }
else if (command ==
"info") {
348 return print_info(file);
350 }
else if (command ==
"print") {
351 std::vector<const char *> index_strings = argp.items();
352 index_strings.erase(index_strings.begin(), index_strings.begin() + 2);
354 std::vector<unsigned int> indexes(index_strings.size());
355 for (
unsigned int i = 0; i < index_strings.size(); ++i) {
356 long l = atol(index_strings[i]);
357 if (l < 0)
throw Exception(
"Invalid index %li", l);
362 if (indexes.size() == 0) {
363 printf(
"No indexes given.\n\n");
364 print_usage(argv[0]);
368 return print_indexes(file, indexes);
370 }
else if (command ==
"replay") {
371 return replay_file(file);
373 }
else if (command ==
"repair") {
374 return repair_file(file);
376 }
else if ( (command ==
"enable") || (command ==
"disable")) {
377 char *host = strdup(
"localhost");
378 unsigned short int port = 1910;
379 if (argp.has_arg(
"r")) {
380 argp.parse_hostport(
"r", &host, &port);
382 int rv = set_enabled(host, port, (command ==
"enable"));
386 }
else if (command ==
"convert") {
387 if (argp.num_items() != 4) {
388 printf(
"Invalid number of arguments\n");
389 print_usage(argv[0]);
392 std::string outfile = argp.items()[2];
393 std::string format = argp.items()[3];
394 return convert_file(file, outfile, format);
397 printf(
"Invalid command '%s'\n", command.c_str());
398 print_usage(argv[0]);