6 #include <boost/property_tree/ptree.hpp>
7 #include <boost/property_tree/json_parser.hpp>
10 #include <sdl/asyncstorage.hpp>
11 #include <boost/asio.hpp>
13 #include "private/cli/commandmap.hpp"
14 #include "private/configurationpaths.hpp"
15 #include "private/createlogger.hpp"
16 #include "private/engineimpl.hpp"
17 #include "private/databaseconfigurationimpl.hpp"
18 #include "private/configurationreader.hpp"
19 #include "private/redis/databaseinfo.hpp"
20 #include "private/asyncstorageimpl.hpp"
21 #include "private/redis/asyncredisstorage.hpp"
23 using namespace shareddatalayer;
24 using namespace shareddatalayer::cli;
25 using namespace shareddatalayer::redis;
29 void handler(std::shared_ptr<shareddatalayer::AsyncStorage> sdl, boost::asio::posix::stream_descriptor& sd)
32 sd.async_read_some(boost::asio::null_buffers(), std::bind(handler, sdl, std::ref(sd)));
35 std::shared_ptr<AsyncStorage> createStorage(const std::string& nsStr, std::ostream& out)
39 std::shared_ptr<AsyncStorage> sdl(AsyncStorage::create());
40 boost::asio::io_service ios;
41 boost::asio::posix::stream_descriptor sd(ios);
43 sd.async_read_some(boost::asio::null_buffers(), std::bind(handler, sdl, std::ref(sd)));
44 sdl->waitReadyAsync(nsStr, [&ios](const std::error_code& error)
47 std::cerr << "SDL waitReadyAsync failed. Error:\n" << error.message() << std::endl;
52 out << "Storage to namespace " << nsStr << " created." << std::endl;
55 catch (const shareddatalayer::Exception& error)
57 out << "Storage create failed: " << error.what() << std::endl;
62 std::string getHosts(const DatabaseConfiguration::Addresses& databaseAddresses)
64 std::string hosts("");
65 for (auto i(databaseAddresses.begin()); i != databaseAddresses.end(); ++i)
66 hosts = hosts + i->getHost() + " ";
70 std::string getPorts(const DatabaseConfiguration::Addresses& databaseAddresses)
72 std::string ports("");
73 for (auto i(databaseAddresses.begin()); i != databaseAddresses.end(); ++i)
74 ports = ports + std::to_string(ntohs(i->getPort())) + " ";
78 void PrintStaticConfiguration(std::ostream& out)
80 auto engine(std::make_shared<EngineImpl>());
81 DatabaseConfigurationImpl databaseConfigurationImpl;
82 ConfigurationReader configurationReader(createLogger(SDL_LOG_PREFIX));
83 configurationReader.readDatabaseConfiguration(databaseConfigurationImpl);
84 auto staticAddresses(databaseConfigurationImpl.getServerAddresses());
85 auto defaultAddresses(databaseConfigurationImpl.getDefaultServerAddresses());
86 auto staticDbType(databaseConfigurationImpl.getDbType());
87 if (!staticAddresses.empty())
89 out << "\nStatic Server Addresses:" << std::endl;
90 out << "Static Host: " << getHosts(staticAddresses) << std::endl;
91 out << "Static Port: " << getPorts(staticAddresses) << std::endl;
92 if (staticDbType == DatabaseConfiguration::DbType::REDIS_CLUSTER)
93 out << "Static DB type: redis-cluster" << std::endl;
94 else if (staticDbType == DatabaseConfiguration::DbType::REDIS_STANDALONE)
95 out << "Static DB type: redis-standalone" << std::endl;
97 out << "Static DB type not defined" << std::endl;
99 if (!defaultAddresses.empty() && staticAddresses.empty())
101 out << "\nDefault Server Addresses:" << std::endl;
102 out << "Default Host: " << getHosts(defaultAddresses) << std::endl;
103 out << "Default Port: " << getPorts(defaultAddresses) << std::endl;
105 const auto var(DB_HOST_ENV_VAR_NAME);
106 const auto conf(getenv(var));
108 out << var << ": " << conf << std::endl;
111 void PrintDatabaseInfo(const DatabaseInfo& databaseInfo, std::ostream& out)
113 out << "Used database configuration (databaseInfo):" << std::endl;
114 out << "Host: " << getHosts(databaseInfo.hosts) << std::endl;
115 out << "Port: " << getPorts(databaseInfo.hosts) << std::endl;
116 switch (databaseInfo.type)
118 case DatabaseInfo::Type::SINGLE:
119 out << "Database type: SINGLE" << std::endl;
121 case DatabaseInfo::Type::REDUNDANT:
122 out << "Database type: REDUNDANT" << std::endl;
124 case DatabaseInfo::Type::CLUSTER:
125 out << "Database type: CLUSTER" << std::endl;
128 switch (databaseInfo.discovery)
130 case DatabaseInfo::Discovery::HIREDIS:
131 out << "Discovery type:: HIREDIS" << std::endl;
132 PrintStaticConfiguration(out);
137 [[noreturn]] void timeoutThread(const int& timeout)
139 std::this_thread::sleep_for(std::chrono::seconds(timeout));
140 std::cerr << "Storage create timeout, aborting after " << timeout << " seconds"<< std::endl;
141 PrintStaticConfiguration(std::cerr);
142 std::exit(EXIT_FAILURE);
145 void setTimeout(const int& timeout)
149 std::thread t(timeoutThread, timeout);
154 int TestConnectivityCommand(std::ostream& out,
155 const boost::program_options::variables_map& map)
157 const auto ns(map["ns"].as<std::string>());
158 const auto timeout(map["timeout"].as<int>());
160 auto sdl(createStorage(ns, out));
163 auto asyncStorageImpl(std::dynamic_pointer_cast<AsyncStorageImpl>(sdl));
164 if (asyncStorageImpl != nullptr)
166 AsyncStorage& operationalHandler(asyncStorageImpl->getOperationHandler(ns));
167 AsyncRedisStorage* redisStorage = dynamic_cast<AsyncRedisStorage*>(&operationalHandler);
168 if (redisStorage != nullptr)
170 auto databaseinfo (redisStorage->getDatabaseInfo());
171 PrintDatabaseInfo(databaseinfo, out);
175 // @TODO Improve output for the case if dummy backend is used.
176 out << "Cannot get AsyncRedisStorage." << std::endl;
182 out << "Cannot get AsyncStorageImpl." << std::endl;
190 AUTO_REGISTER_COMMAND(std::bind(TestConnectivityCommand, std::placeholders::_1, std::placeholders::_3),
192 "Test SDL backend connectivity",
193 "Check that SDL database backend is available and show discovered redis host address and port",
194 CommandMap::Category::UTIL, 30020,
195 ("ns", boost::program_options::value<std::string>()->default_value("sdltoolns"), "Used namespace")
196 ("timeout", boost::program_options::value<int>()->default_value(0), "Timeout (in seconds), Default is no timeout"));