bt_sqlite_logger.cpp
Go to the documentation of this file.
3 #include "cpp-sqlite/sqlite.hpp"
4 
5 namespace BT
6 {
7 
8 SqliteLogger::SqliteLogger(const Tree& tree, std::filesystem::path const& filepath,
9  bool append)
10  : StatusChangeLogger(tree.rootNode())
11 {
12  const auto extension = filepath.filename().extension();
13  if(extension != ".db3" && extension != ".btdb")
14  {
15  throw RuntimeError("SqliteLogger: the file extension must be [.db3] or [.btdb]");
16  }
17 
19 
20  db_ = std::make_unique<sqlite::Connection>(filepath.string());
21 
22  sqlite::Statement(*db_, "CREATE TABLE IF NOT EXISTS Transitions ("
23  "timestamp INTEGER PRIMARY KEY NOT NULL, "
24  "session_id INTEGER NOT NULL, "
25  "node_uid INTEGER NOT NULL, "
26  "duration INTEGER, "
27  "state INTEGER NOT NULL,"
28  "extra_data VARCHAR );");
29 
30  sqlite::Statement(*db_, "CREATE TABLE IF NOT EXISTS Nodes ("
31  "session_id INTEGER NOT NULL, "
32  "fullpath VARCHAR, "
33  "node_uid INTEGER NOT NULL );");
34 
35  sqlite::Statement(*db_, "CREATE TABLE IF NOT EXISTS Definitions ("
36  "session_id INTEGER PRIMARY KEY AUTOINCREMENT, "
37  "date TEXT NOT NULL,"
38  "xml_tree TEXT NOT NULL);");
39 
40  if(!append)
41  {
42  sqlite::Statement(*db_, "DELETE from Transitions;");
43  sqlite::Statement(*db_, "DELETE from Definitions;");
44  sqlite::Statement(*db_, "DELETE from Nodes;");
45  }
46 
47  auto tree_xml = WriteTreeToXML(tree, true, true);
49  "INSERT into Definitions (date, xml_tree) "
50  "VALUES (datetime('now','localtime'),?);",
51  tree_xml);
52 
53  auto res = sqlite::Query(*db_, "SELECT MAX(session_id) "
54  "FROM Definitions LIMIT 1;");
55 
56  while(res.Next())
57  {
58  session_id_ = res.Get(0);
59  }
60 
61  for(const auto& subtree : tree.subtrees)
62  {
63  for(const auto& node : subtree->nodes)
64  {
65  sqlite::Statement(*db_, "INSERT INTO Nodes VALUES (?, ?, ?)", session_id_,
66  node->fullPath(), node->UID());
67  }
68  }
69 
70  writer_thread_ = std::thread(&SqliteLogger::writerLoop, this);
71 }
72 
74 {
75  loop_ = false;
76  queue_cv_.notify_one();
77  writer_thread_.join();
78  flush();
79  sqlite::Statement(*db_, "PRAGMA optimize;");
80 }
81 
83 {
84  extra_func_ = func;
85 }
86 
87 void SqliteLogger::callback(Duration timestamp, const TreeNode& node,
88  NodeStatus prev_status, NodeStatus status)
89 {
90  using namespace std::chrono;
91  int64_t tm_usec = int64_t(duration_cast<microseconds>(timestamp).count());
92  monotonic_timestamp_ = std::max(monotonic_timestamp_ + 1, tm_usec);
93 
94  long elapsed_time = 0;
95 
96  if(prev_status == NodeStatus::IDLE && status == NodeStatus::RUNNING)
97  {
99  }
100 
101  if(prev_status == NodeStatus::RUNNING && status != NodeStatus::RUNNING)
102  {
103  elapsed_time = monotonic_timestamp_;
104  auto it = starting_time_.find(&node);
105  if(it != starting_time_.end())
106  {
107  elapsed_time -= it->second;
108  }
109  }
110 
111  Transition trans;
113  trans.duration = elapsed_time;
114  trans.node_uid = node.UID();
115  trans.status = status;
116 
117  if(extra_func_)
118  {
119  trans.extra_data = extra_func_(timestamp, node, prev_status, status);
120  }
121 
122  {
123  std::scoped_lock lk(queue_mutex_);
124  transitions_queue_.push_back(trans);
125  }
126  queue_cv_.notify_one();
127 
128  if(extra_func_)
129  {
130  extra_func_(timestamp, node, prev_status, status);
131  }
132 }
133 
134 void SqliteLogger::execSqlStatement(std::string statement)
135 {
136  sqlite::Statement(*db_, statement);
137 }
138 
140 {
141  std::deque<Transition> transitions;
142 
143  while(loop_)
144  {
145  transitions.clear();
146  {
147  std::unique_lock lk(queue_mutex_);
148  queue_cv_.wait(lk, [this]() { return !transitions_queue_.empty() || !loop_; });
149  std::swap(transitions, transitions_queue_);
150  }
151 
152  while(!transitions.empty())
153  {
154  auto const trans = transitions.front();
155  transitions.pop_front();
156 
157  sqlite::Statement(*db_, "INSERT INTO Transitions VALUES (?, ?, ?, ?, ?, ?)",
158  trans.timestamp, session_id_, trans.node_uid, trans.duration,
159  static_cast<int>(trans.status), trans.extra_data);
160  }
161  }
162 }
163 
165 {
166  sqlite3_db_cacheflush(db_->GetPtr());
167 }
168 
169 } // namespace BT
BT
Definition: ex01_wrap_legacy.cpp:29
BT::SqliteLogger::Transition::duration
int64_t duration
Definition: bt_sqlite_logger.h:88
BT::SqliteLogger::Transition::timestamp
int64_t timestamp
Definition: bt_sqlite_logger.h:87
BT::SqliteLogger::queue_mutex_
std::mutex queue_mutex_
Definition: bt_sqlite_logger.h:95
BT::SqliteLogger::flush
virtual void flush() override
Definition: bt_sqlite_logger.cpp:164
BT::TreeNode::UID
uint16_t UID() const
Definition: tree_node.cpp:330
BT::SqliteLogger::SqliteLogger
SqliteLogger(const Tree &tree, std::filesystem::path const &file, bool append=false)
To correctly read this log with Groot2, you must use the suffix ".db3". Constructor will throw otherw...
Definition: bt_sqlite_logger.cpp:8
BT::SqliteLogger::writerLoop
void writerLoop()
Definition: bt_sqlite_logger.cpp:139
BT::SqliteLogger::setAdditionalCallback
void setAdditionalCallback(ExtraCallback func)
Definition: bt_sqlite_logger.cpp:82
BT::SqliteLogger::writer_thread_
std::thread writer_thread_
Definition: bt_sqlite_logger.h:97
BT::SqliteLogger::extra_func_
ExtraCallback extra_func_
Definition: bt_sqlite_logger.h:100
BT::SqliteLogger::execSqlStatement
void execSqlStatement(std::string statement)
Definition: bt_sqlite_logger.cpp:134
BT::StatusChangeLogger::enableTransitionToIdle
void enableTransitionToIdle(bool enable)
Definition: abstract_logger.h:53
sqlite.hpp
BT::TreeNode
Abstract base class for Behavior Tree Nodes.
Definition: tree_node.h:118
bt_sqlite_logger.h
BT::Tree
Struct used to store a tree. If this object goes out of scope, the tree is destroyed.
Definition: bt_factory.h:91
BT::SqliteLogger::Transition
Definition: bt_sqlite_logger.h:84
BT::StatusChangeLogger
Definition: abstract_logger.h:15
BT::Duration
std::chrono::high_resolution_clock::duration Duration
Definition: basic_types.h:628
BT::SqliteLogger::starting_time_
std::unordered_map< const BT::TreeNode *, int64_t > starting_time_
Definition: bt_sqlite_logger.h:80
BT::WriteTreeToXML
std::string WriteTreeToXML(const Tree &tree, bool add_metadata, bool add_builtin_models)
WriteTreeToXML create a string that contains the XML that corresponds to a given tree....
Definition: xml_parsing.cpp:1497
BT::SqliteLogger::Transition::status
NodeStatus status
Definition: bt_sqlite_logger.h:89
BT::SqliteLogger::transitions_queue_
std::deque< Transition > transitions_queue_
Definition: bt_sqlite_logger.h:93
BT::SqliteLogger::callback
virtual void callback(Duration timestamp, const TreeNode &node, NodeStatus prev_status, NodeStatus status) override
Definition: bt_sqlite_logger.cpp:87
sqlite::Statement
void Statement(sqlite::Connection &connection, const std::string &command, const First &first, const Args... args)
Definition: sqlite.hpp:542
lexy::count
constexpr auto count
Sink that counts all arguments.
Definition: fold.hpp:88
BT::SqliteLogger::loop_
std::atomic_bool loop_
Definition: bt_sqlite_logger.h:98
BT::SqliteLogger::monotonic_timestamp_
int64_t monotonic_timestamp_
Definition: bt_sqlite_logger.h:79
BT::SqliteLogger::~SqliteLogger
virtual ~SqliteLogger() override
Definition: bt_sqlite_logger.cpp:73
BT::RuntimeError
Definition: exceptions.h:58
xml_parsing.h
BT::SqliteLogger::Transition::node_uid
uint16_t node_uid
Definition: bt_sqlite_logger.h:86
BT::SqliteLogger::queue_cv_
std::condition_variable queue_cv_
Definition: bt_sqlite_logger.h:94
BT::Tree::subtrees
std::vector< Subtree::Ptr > subtrees
Definition: bt_factory.h:104
BT::NodeStatus::RUNNING
@ RUNNING
BT::SqliteLogger::ExtraCallback
std::function< std::string(Duration, const TreeNode &, NodeStatus, NodeStatus)> ExtraCallback
Definition: bt_sqlite_logger.h:66
BT::SqliteLogger::session_id_
int session_id_
Definition: bt_sqlite_logger.h:82
BT::SqliteLogger::db_
std::unique_ptr< sqlite::Connection > db_
Definition: bt_sqlite_logger.h:77
BT::NodeStatus::IDLE
@ IDLE
BT::SqliteLogger::Transition::extra_data
std::string extra_data
Definition: bt_sqlite_logger.h:90
sqlite::Query
CPP_SQLITE_NODISCARD Result Query(sqlite::Connection &connection, const std::string &command, const First &first, const Args... args)
Definition: sqlite.hpp:559
std::swap
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression, cppcoreguidelines-noexcept-swap, performance-noexcept-swap) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
Definition: json.hpp:24537
BT::NodeStatus
NodeStatus
Definition: basic_types.h:33


behaviortree_cpp_v4
Author(s): Davide Faconti
autogenerated on Fri Jun 28 2024 02:20:07