rippled
DatabaseCon.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/basics/Log.h>
21 #include <ripple/basics/contract.h>
22 #include <ripple/core/DatabaseCon.h>
23 #include <ripple/core/SociDB.h>
24 #include <boost/algorithm/string.hpp>
25 #include <boost/format.hpp>
26 #include <memory>
27 
28 namespace ripple {
29 
30 DatabaseCon::Setup
31 setup_DatabaseCon(Config const& c, boost::optional<beast::Journal> j)
32 {
33  DatabaseCon::Setup setup;
34 
35  setup.startUp = c.START_UP;
36  setup.standAlone = c.standalone();
37  setup.dataDir = c.legacy("database_path");
38  if (!setup.standAlone && setup.dataDir.empty())
39  {
40  Throw<std::runtime_error>("database_path must be set.");
41  }
42 
43  if (!setup.globalPragma)
44  {
45  setup.globalPragma = [&c, &j]() {
46  auto const& sqlite = c.section("sqlite");
47  auto result = std::make_unique<std::vector<std::string>>();
48  result->reserve(3);
49 
50  // defaults
51  std::string safety_level;
52  std::string journal_mode = "wal";
53  std::string synchronous = "normal";
54  std::string temp_store = "file";
55  bool showRiskWarning = false;
56 
57  if (set(safety_level, "safety_level", sqlite))
58  {
59  if (boost::iequals(safety_level, "low"))
60  {
61  // low safety defaults
62  journal_mode = "memory";
63  synchronous = "off";
64  temp_store = "memory";
65  showRiskWarning = true;
66  }
67  else if (!boost::iequals(safety_level, "high"))
68  {
69  Throw<std::runtime_error>(
70  "Invalid safety_level value: " + safety_level);
71  }
72  }
73 
74  {
75  // #journal_mode Valid values : delete, truncate, persist,
76  // memory, wal, off
77  if (set(journal_mode, "journal_mode", sqlite) &&
78  !safety_level.empty())
79  {
80  Throw<std::runtime_error>(
81  "Configuration file may not define both "
82  "\"safety_level\" and \"journal_mode\"");
83  }
84  bool higherRisk = boost::iequals(journal_mode, "memory") ||
85  boost::iequals(journal_mode, "off");
86  showRiskWarning = showRiskWarning || higherRisk;
87  if (higherRisk || boost::iequals(journal_mode, "delete") ||
88  boost::iequals(journal_mode, "truncate") ||
89  boost::iequals(journal_mode, "persist") ||
90  boost::iequals(journal_mode, "wal"))
91  {
92  result->emplace_back(boost::str(
93  boost::format(CommonDBPragmaJournal) % journal_mode));
94  }
95  else
96  {
97  Throw<std::runtime_error>(
98  "Invalid journal_mode value: " + journal_mode);
99  }
100  }
101 
102  {
103  //#synchronous Valid values : off, normal, full, extra
104  if (set(synchronous, "synchronous", sqlite) &&
105  !safety_level.empty())
106  {
107  Throw<std::runtime_error>(
108  "Configuration file may not define both "
109  "\"safety_level\" and \"synchronous\"");
110  }
111  bool higherRisk = boost::iequals(synchronous, "off");
112  showRiskWarning = showRiskWarning || higherRisk;
113  if (higherRisk || boost::iequals(synchronous, "normal") ||
114  boost::iequals(synchronous, "full") ||
115  boost::iequals(synchronous, "extra"))
116  {
117  result->emplace_back(boost::str(
118  boost::format(CommonDBPragmaSync) % synchronous));
119  }
120  else
121  {
122  Throw<std::runtime_error>(
123  "Invalid synchronous value: " + synchronous);
124  }
125  }
126 
127  {
128  // #temp_store Valid values : default, file, memory
129  if (set(temp_store, "temp_store", sqlite) &&
130  !safety_level.empty())
131  {
132  Throw<std::runtime_error>(
133  "Configuration file may not define both "
134  "\"safety_level\" and \"temp_store\"");
135  }
136  bool higherRisk = boost::iequals(temp_store, "memory");
137  showRiskWarning = showRiskWarning || higherRisk;
138  if (higherRisk || boost::iequals(temp_store, "default") ||
139  boost::iequals(temp_store, "file"))
140  {
141  result->emplace_back(boost::str(
142  boost::format(CommonDBPragmaTemp) % temp_store));
143  }
144  else
145  {
146  Throw<std::runtime_error>(
147  "Invalid temp_store value: " + temp_store);
148  }
149  }
150 
151  if (showRiskWarning && j && c.LEDGER_HISTORY > SQLITE_TUNING_CUTOFF)
152  {
153  JLOG(j->warn())
154  << "reducing the data integrity guarantees from the "
155  "default [sqlite] behavior is not recommended for "
156  "nodes storing large amounts of history, because of the "
157  "difficulty inherent in rebuilding corrupted data.";
158  }
159  assert(result->size() == 3);
160  return result;
161  }();
162  }
163  setup.useGlobalPragma = true;
164 
165  return setup;
166 }
167 
170 
171 void
173 {
174  if (!q)
175  Throw<std::logic_error>("No JobQueue");
177 }
178 
179 } // namespace ripple
ripple::DatabaseCon::Setup::globalPragma
static std::unique_ptr< std::vector< std::string > const > globalPragma
Definition: DatabaseCon.h:105
std::string
STL class.
ripple::Logs
Manages partitions for logging.
Definition: Log.h:48
ripple::DatabaseCon::Setup
Definition: DatabaseCon.h:86
ripple::DatabaseCon::Setup::startUp
Config::StartUpType startUp
Definition: DatabaseCon.h:90
ripple::DatabaseCon::Setup::dataDir
boost::filesystem::path dataDir
Definition: DatabaseCon.h:92
ripple::DatabaseCon::setupCheckpointing
void setupCheckpointing(JobQueue *, Logs &)
Definition: DatabaseCon.cpp:172
ripple::DatabaseCon::Setup::useGlobalPragma
bool useGlobalPragma
Definition: DatabaseCon.h:95
ripple::DatabaseCon::Setup::standAlone
bool standAlone
Definition: DatabaseCon.h:91
ripple::Config
Definition: Config.h:67
ripple::makeCheckpointer
std::unique_ptr< Checkpointer > makeCheckpointer(soci::session &session, JobQueue &queue, Logs &logs)
Returns a new checkpointer which makes checkpoints of a soci database every checkpointPageCount pages...
Definition: SociDB.cpp:280
ripple::DatabaseCon::session_
soci::session session_
Definition: DatabaseCon.h:184
ripple::Config::standalone
bool standalone() const
Definition: Config.h:222
ripple::set
bool set(T &target, std::string const &name, Section const &section)
Set a value from a configuration Section If the named value is not found or doesn't parse as a T,...
Definition: BasicConfig.h:276
ripple::BasicConfig::legacy
void legacy(std::string const &section, std::string value)
Set a value that is not a key/value pair.
Definition: BasicConfig.cpp:175
ripple::SQLITE_TUNING_CUTOFF
constexpr std::uint32_t SQLITE_TUNING_CUTOFF
Definition: DBInit.h:39
ripple::Config::START_UP
StartUpType START_UP
Definition: Config.h:124
ripple::CommonDBPragmaTemp
constexpr char const * CommonDBPragmaTemp
Definition: DBInit.h:33
ripple::CommonDBPragmaJournal
constexpr char const * CommonDBPragmaJournal
Definition: DBInit.h:31
memory
ripple::Config::LEDGER_HISTORY
std::uint32_t LEDGER_HISTORY
Definition: Config.h:164
ripple::JobQueue
A pool of threads to perform work.
Definition: JobQueue.h:55
ripple::setup_DatabaseCon
DatabaseCon::Setup setup_DatabaseCon(Config const &c, boost::optional< beast::Journal > j=boost::none)
Definition: DatabaseCon.cpp:31
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::DatabaseCon::checkpointer_
std::unique_ptr< Checkpointer > checkpointer_
Definition: DatabaseCon.h:185
std::string::empty
T empty(T... args)
ripple::CommonDBPragmaSync
constexpr char const * CommonDBPragmaSync
Definition: DBInit.h:32
std::unique_ptr
STL class.
ripple::BasicConfig::section
Section & section(std::string const &name)
Returns the section with the given name.
Definition: BasicConfig.cpp:138