zookeeper-cpp
ZooKeeper Client for C++
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Groups
server_group.cpp
1 #include "server_group.hpp"
2 
3 #include <algorithm>
4 #include <cerrno>
5 #include <fstream>
6 #include <sstream>
7 #include <stdexcept>
8 #include <system_error>
9 
10 #include <sys/stat.h>
11 #include <sys/types.h>
12 
13 #include "classpath.hpp"
14 #include "configuration.hpp"
15 #include "server.hpp"
16 
17 namespace zk::server
18 {
19 
21 {
23  std::string name;
24  std::string path;
25  std::uint16_t peer_port;
26  std::uint16_t leader_port;
27  std::shared_ptr<server> instance;
28 
29  info(const configuration& base) :
30  settings(base)
31  { }
32 };
33 
35 { }
36 
37 server_group::server_group(server_group&&) noexcept = default;
38 
39 server_group& server_group::operator=(server_group&& src) noexcept
40 {
41  _servers = std::move(src._servers);
42  _conn_string = std::move(src._conn_string);
43  return *this;
44 }
45 
46 static void create_directory(const std::string& path)
47 {
48  if (::mkdir(path.c_str(), 0755))
49  {
50  throw std::system_error(errno, std::system_category());
51  }
52 }
53 
54 static void save_id_file(const std::string& path, const server_id& id)
55 {
56  std::ofstream ofs(path.c_str());
57  if (!ofs)
58  throw std::runtime_error("IO failure");
59  ofs << id << '\n';
60  ofs.flush();
61 }
62 
63 server_group server_group::make_ensemble(std::size_t size, const configuration& base_settings_in)
64 {
65  auto base_settings = base_settings_in;
66 
67  if (!base_settings.data_directory())
68  throw std::invalid_argument("Settings must specify a base directory");
69 
70  auto base_directory = base_settings.data_directory().value();
71  auto base_port = base_settings.client_port() == configuration::default_client_port ? std::uint16_t(18500)
72  : base_settings.client_port();
73 
74  server_group out;
75  for (std::size_t idx = 0U; idx < size; ++idx)
76  {
77  auto id = server_id(idx + 1);
78  auto px = std::make_shared<info>(base_settings);
79  auto& x = *px;
80  x.name = std::to_string(id.value);
81  x.path = base_directory + "/" + x.name;
82  x.settings
83  .client_port(base_port++)
84  .data_directory(x.path + "/data")
85  ;
86  x.peer_port = base_port++;
87  x.leader_port = base_port++;
88 
89  out._servers.emplace(id, px);
90  }
91 
92  std::ostringstream conn_str_os;
93  conn_str_os << "zk://";
94  bool first = true;
95 
96  create_directory(base_directory);
97  for (auto& [id, srvr] : out._servers)
98  {
99  for (const auto& [id2, srvr2] : out._servers)
100  {
101  srvr->settings.add_server(id2, "127.0.0.1", srvr2->peer_port, srvr2->leader_port);
102  }
103 
104  create_directory(srvr->path);
105  create_directory(srvr->path + "/data");
106  save_id_file(srvr->path + "/data/myid", id);
107  srvr->settings.save_file(srvr->path + "/settings.cfg");
108 
109  if (!std::exchange(first, false))
110  conn_str_os << ',';
111  conn_str_os << "127.0.0.1:" << srvr->settings.client_port();
112  }
113  conn_str_os << '/';
114  out._conn_string = conn_str_os.str();
115 
116  return out;
117 }
118 
120 {
121  return _conn_string;
122 }
123 
125 {
126  for (auto& [name, srvr] : _servers)
127  {
128  static_cast<void>(name);
129 
130  if (!srvr->instance)
131  {
132  srvr->instance = std::make_shared<server>(packages, srvr->settings);
133  }
134  }
135 }
136 
137 }
configuration settings
Settings for this server.
std::string name
Name of this server (string version of its ID)
Represents the ID of a server in the ensemble.
Create and manage a group of server instances on this local machine (most likely in a single ensemble...
Represents a collection of JARs or other Java entities that should be provided as the --classpath to ...
Definition: classpath.hpp:18
const optional< std::string > & data_directory() const
const std::string & get_connection_string()
Get a connection string which can connect to any the servers in the group.
std::uint16_t peer_port
settings.peer_port
static const std::uint16_t default_client_port
The default value for client_port.
std::shared_ptr< server > instance
Instance(if this is running)
void start_all_servers(const classpath &packages)
Start all servers in the group.
std::string path
settings.data_directory
std::size_t size() const
How many servers are in this group?
Represents a configuration which should be run by server instance.
server_group() noexcept
Create an empty server group.
std::uint16_t leader_port
settings.leader_port
static server_group make_ensemble(std::size_t size, const configuration &base_settings)
Create an ensemble of the given size.