blob: 6d8ddc2c9ddb7db27ef5a2a00c88d3ec9a83f8e6 [file] [log] [blame]
Chris Sosa45d9f102014-03-24 11:18:54 -07001// Copyright 2014 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <string>
6
7#include <base/at_exit.h>
8#include <base/command_line.h>
9#include <base/file_util.h>
10#include <base/files/file_path.h>
11#include <base/logging.h>
12#include <base/message_loop/message_loop.h>
13#include <base/strings/string_util.h>
14#include <base/strings/stringprintf.h>
Chris Sosaababc5c2014-04-09 15:42:01 -070015#include <sysexits.h>
Chris Sosa45d9f102014-03-24 11:18:54 -070016
Christopher Wiley90016242014-04-01 17:33:29 -070017#include "buffet/async_event_sequencer.h"
Chris Sosa45d9f102014-03-24 11:18:54 -070018#include "buffet/dbus_manager.h"
Christopher Wileya4915c42014-03-27 14:45:37 -070019#include "buffet/manager.h"
Chris Sosa45d9f102014-03-24 11:18:54 -070020
Christopher Wiley90016242014-04-01 17:33:29 -070021using buffet::dbus_utils::AsyncEventSequencer;
22
Chris Sosa45d9f102014-03-24 11:18:54 -070023namespace {
24
Chris Sosaababc5c2014-04-09 15:42:01 -070025static const char kLogRoot[] = "logroot";
26static const char kHelp[] = "help";
27static const char kDefaultLogRoot[] = "/var/log";
28
29// The help message shown if help flag is passed to the program.
30static const char kHelpMessage[] = "\n"
31 "Available Switches: \n"
32 " --logroot=/path/to/logroot\n"
33 " Specifies parent directory to put buffet logs in.\n";
34
Chris Sosa45d9f102014-03-24 11:18:54 -070035// Returns |utime| as a string
36std::string GetTimeAsString(time_t utime) {
37 struct tm tm;
38 CHECK_EQ(localtime_r(&utime, &tm), &tm);
39 char str[16];
40 CHECK_EQ(strftime(str, sizeof(str), "%Y%m%d-%H%M%S", &tm), 15UL);
41 return std::string(str);
42}
43
44// Sets up a symlink to point to log file.
45void SetupLogSymlink(const std::string& symlink_path,
46 const std::string& log_path) {
47 base::DeleteFile(base::FilePath(symlink_path), true);
48 if (symlink(log_path.c_str(), symlink_path.c_str()) == -1) {
49 LOG(ERROR) << "Unable to create symlink " << symlink_path
50 << " pointing at " << log_path;
51 }
52}
53
Chris Sosaababc5c2014-04-09 15:42:01 -070054// Creates new log file based on timestamp in |log_root|/buffet.
55std::string SetupLogFile(const std::string& log_root) {
56 const auto log_symlink = log_root + "/buffet.log";
57 const auto logs_dir = log_root + "/buffet";
Chris Sosa45d9f102014-03-24 11:18:54 -070058 const auto log_path =
59 base::StringPrintf("%s/buffet.%s",
60 logs_dir.c_str(),
61 GetTimeAsString(::time(NULL)).c_str());
62 mkdir(logs_dir.c_str(), 0755);
63 SetupLogSymlink(log_symlink, log_path);
64 return log_symlink;
65}
66
67// Sets up logging for buffet.
Chris Sosaababc5c2014-04-09 15:42:01 -070068void SetupLogging(const std::string& log_root) {
69 const auto log_file = SetupLogFile(log_root);
Chris Sosa45d9f102014-03-24 11:18:54 -070070 logging::LoggingSettings settings;
71 settings.logging_dest = logging::LOG_TO_ALL;
72 settings.log_file = log_file.c_str();
73 settings.lock_log = logging::DONT_LOCK_LOG_FILE;
74 settings.delete_old = logging::APPEND_TO_OLD_LOG_FILE;
75 logging::InitLogging(settings);
76}
77
Christopher Wiley90016242014-04-01 17:33:29 -070078void TakeServiceOwnership(scoped_refptr<dbus::Bus> bus, bool success) {
79 // Success should always be true since we've said that failures are
80 // fatal.
81 CHECK(success) << "Init of one or more objects has failed.";
82 CHECK(bus->RequestOwnershipAndBlock(buffet::dbus_constants::kServiceName,
83 dbus::Bus::REQUIRE_PRIMARY))
84 << "Unable to take ownership of " << buffet::dbus_constants::kServiceName;
85}
86
87void EnterMainLoop(base::MessageLoopForIO* message_loop,
88 scoped_refptr<dbus::Bus> bus) {
89 scoped_refptr<AsyncEventSequencer> sequencer(new AsyncEventSequencer());
90 buffet::DBusManager dbus_manager(bus.get());
91 dbus_manager.Init(sequencer->GetHandler("DBusManager.Init() failed.", true));
92 buffet::Manager manager(bus.get());
93 manager.Init(sequencer->GetHandler("Manager.Init() failed.", true));
94 sequencer->OnAllTasksCompletedCall(
95 {base::Bind(&TakeServiceOwnership, bus)});
96 // Release our handle on the sequencer so that it gets deleted after
97 // both callbacks return.
98 sequencer = nullptr;
99 LOG(INFO) << "Entering mainloop.";
100 message_loop->Run();
101}
102
Chris Sosa45d9f102014-03-24 11:18:54 -0700103} // namespace
104
105int main(int argc, char* argv[]) {
106 // Parse the args and check for extra args.
107 CommandLine::Init(argc, argv);
Chris Sosaababc5c2014-04-09 15:42:01 -0700108 CommandLine* cl = CommandLine::ForCurrentProcess();
Chris Sosa45d9f102014-03-24 11:18:54 -0700109
Chris Sosaababc5c2014-04-09 15:42:01 -0700110 if (cl->HasSwitch(kHelp)) {
111 LOG(INFO) << kHelpMessage;
112 return EX_USAGE;
113 }
114
115 std::string log_root = std::string(kDefaultLogRoot);
116 if (cl->HasSwitch(kLogRoot)) {
117 log_root = cl->GetSwitchValueASCII(kLogRoot);
118 }
119
120 SetupLogging(log_root);
Chris Sosa45d9f102014-03-24 11:18:54 -0700121
122 base::AtExitManager at_exit_manager;
123 base::MessageLoopForIO message_loop;
124
Christopher Wiley90016242014-04-01 17:33:29 -0700125 dbus::Bus::Options options;
126 // TODO(sosa): Should this be on the system bus?
127 options.bus_type = dbus::Bus::SYSTEM;
128 scoped_refptr<dbus::Bus> bus(new dbus::Bus(options));
129 CHECK(bus->Connect());
130 // Our top level objects expect the bus to exist in a connected state for
131 // the duration of their lifetimes.
132 EnterMainLoop(&message_loop, bus);
133 bus->ShutdownAndBlock();
Chris Sosa45d9f102014-03-24 11:18:54 -0700134
Chris Sosaababc5c2014-04-09 15:42:01 -0700135 return EX_OK;
Chris Sosa45d9f102014-03-24 11:18:54 -0700136}