blob: cc2fea70fcc01768e1a56fdb1b65008bc176574f [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>
Christopher Wileyb76eb292014-05-05 16:09:16 -070015#include <dbus/bus.h>
Chris Sosaababc5c2014-04-09 15:42:01 -070016#include <sysexits.h>
Chris Sosa45d9f102014-03-24 11:18:54 -070017
Christopher Wiley90016242014-04-01 17:33:29 -070018#include "buffet/async_event_sequencer.h"
Alex Vakulenkoe4efaaf2014-07-22 08:08:44 -070019#include "buffet/commands/command_manager.h"
Christopher Wileyadb901d2014-05-07 09:58:45 -070020#include "buffet/dbus_constants.h"
21#include "buffet/exported_object_manager.h"
Christopher Wileya4915c42014-03-27 14:45:37 -070022#include "buffet/manager.h"
Chris Sosa45d9f102014-03-24 11:18:54 -070023
Christopher Wiley90016242014-04-01 17:33:29 -070024using buffet::dbus_utils::AsyncEventSequencer;
Christopher Wileyadb901d2014-05-07 09:58:45 -070025using buffet::dbus_utils::ExportedObjectManager;
Christopher Wiley90016242014-04-01 17:33:29 -070026
Chris Sosa45d9f102014-03-24 11:18:54 -070027namespace {
28
Chris Sosaababc5c2014-04-09 15:42:01 -070029static const char kLogRoot[] = "logroot";
30static const char kHelp[] = "help";
31static const char kDefaultLogRoot[] = "/var/log";
32
33// The help message shown if help flag is passed to the program.
34static const char kHelpMessage[] = "\n"
35 "Available Switches: \n"
36 " --logroot=/path/to/logroot\n"
37 " Specifies parent directory to put buffet logs in.\n";
38
Chris Sosa45d9f102014-03-24 11:18:54 -070039// Returns |utime| as a string
40std::string GetTimeAsString(time_t utime) {
41 struct tm tm;
42 CHECK_EQ(localtime_r(&utime, &tm), &tm);
43 char str[16];
44 CHECK_EQ(strftime(str, sizeof(str), "%Y%m%d-%H%M%S", &tm), 15UL);
45 return std::string(str);
46}
47
48// Sets up a symlink to point to log file.
49void SetupLogSymlink(const std::string& symlink_path,
50 const std::string& log_path) {
51 base::DeleteFile(base::FilePath(symlink_path), true);
52 if (symlink(log_path.c_str(), symlink_path.c_str()) == -1) {
53 LOG(ERROR) << "Unable to create symlink " << symlink_path
54 << " pointing at " << log_path;
55 }
56}
57
Chris Sosaababc5c2014-04-09 15:42:01 -070058// Creates new log file based on timestamp in |log_root|/buffet.
59std::string SetupLogFile(const std::string& log_root) {
60 const auto log_symlink = log_root + "/buffet.log";
61 const auto logs_dir = log_root + "/buffet";
Chris Sosa45d9f102014-03-24 11:18:54 -070062 const auto log_path =
63 base::StringPrintf("%s/buffet.%s",
64 logs_dir.c_str(),
65 GetTimeAsString(::time(NULL)).c_str());
66 mkdir(logs_dir.c_str(), 0755);
67 SetupLogSymlink(log_symlink, log_path);
68 return log_symlink;
69}
70
71// Sets up logging for buffet.
Chris Sosaababc5c2014-04-09 15:42:01 -070072void SetupLogging(const std::string& log_root) {
73 const auto log_file = SetupLogFile(log_root);
Chris Sosa45d9f102014-03-24 11:18:54 -070074 logging::LoggingSettings settings;
75 settings.logging_dest = logging::LOG_TO_ALL;
76 settings.log_file = log_file.c_str();
77 settings.lock_log = logging::DONT_LOCK_LOG_FILE;
78 settings.delete_old = logging::APPEND_TO_OLD_LOG_FILE;
79 logging::InitLogging(settings);
80}
81
Christopher Wiley90016242014-04-01 17:33:29 -070082void TakeServiceOwnership(scoped_refptr<dbus::Bus> bus, bool success) {
83 // Success should always be true since we've said that failures are
84 // fatal.
85 CHECK(success) << "Init of one or more objects has failed.";
86 CHECK(bus->RequestOwnershipAndBlock(buffet::dbus_constants::kServiceName,
87 dbus::Bus::REQUIRE_PRIMARY))
88 << "Unable to take ownership of " << buffet::dbus_constants::kServiceName;
89}
90
91void EnterMainLoop(base::MessageLoopForIO* message_loop,
92 scoped_refptr<dbus::Bus> bus) {
93 scoped_refptr<AsyncEventSequencer> sequencer(new AsyncEventSequencer());
Christopher Wileyadb901d2014-05-07 09:58:45 -070094 ExportedObjectManager object_manager(
95 bus, dbus::ObjectPath(buffet::dbus_constants::kRootServicePath));
96 buffet::Manager manager(bus, object_manager.AsWeakPtr());
97 object_manager.Init(
98 sequencer->GetHandler("ObjectManager.Init() failed.", true));
Christopher Wiley90016242014-04-01 17:33:29 -070099 manager.Init(sequencer->GetHandler("Manager.Init() failed.", true));
100 sequencer->OnAllTasksCompletedCall(
101 {base::Bind(&TakeServiceOwnership, bus)});
102 // Release our handle on the sequencer so that it gets deleted after
103 // both callbacks return.
104 sequencer = nullptr;
Alex Vakulenkoe4efaaf2014-07-22 08:08:44 -0700105
106 buffet::CommandManager::Startup();
107
Christopher Wiley90016242014-04-01 17:33:29 -0700108 LOG(INFO) << "Entering mainloop.";
109 message_loop->Run();
110}
111
Chris Sosa45d9f102014-03-24 11:18:54 -0700112} // namespace
113
114int main(int argc, char* argv[]) {
115 // Parse the args and check for extra args.
116 CommandLine::Init(argc, argv);
Chris Sosaababc5c2014-04-09 15:42:01 -0700117 CommandLine* cl = CommandLine::ForCurrentProcess();
Chris Sosa45d9f102014-03-24 11:18:54 -0700118
Chris Sosaababc5c2014-04-09 15:42:01 -0700119 if (cl->HasSwitch(kHelp)) {
120 LOG(INFO) << kHelpMessage;
121 return EX_USAGE;
122 }
123
124 std::string log_root = std::string(kDefaultLogRoot);
125 if (cl->HasSwitch(kLogRoot)) {
126 log_root = cl->GetSwitchValueASCII(kLogRoot);
127 }
128
129 SetupLogging(log_root);
Chris Sosa45d9f102014-03-24 11:18:54 -0700130
131 base::AtExitManager at_exit_manager;
132 base::MessageLoopForIO message_loop;
133
Christopher Wiley90016242014-04-01 17:33:29 -0700134 dbus::Bus::Options options;
135 // TODO(sosa): Should this be on the system bus?
136 options.bus_type = dbus::Bus::SYSTEM;
137 scoped_refptr<dbus::Bus> bus(new dbus::Bus(options));
138 CHECK(bus->Connect());
139 // Our top level objects expect the bus to exist in a connected state for
140 // the duration of their lifetimes.
141 EnterMainLoop(&message_loop, bus);
142 bus->ShutdownAndBlock();
Chris Sosa45d9f102014-03-24 11:18:54 -0700143
Chris Sosaababc5c2014-04-09 15:42:01 -0700144 return EX_OK;
Chris Sosa45d9f102014-03-24 11:18:54 -0700145}