include/simdb/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
17 / 19
89.5%
Branches:
1 / 3
33.3%
Functions:
17 / 17
100.0%

apps/App.hpp
Line Branch Exec Source
1 // <App.hpp> -*- C++ -*-
2
3 #pragma once
4
5 #include <memory>
6 #include <vector>
7
8 /// Aside from its core SQLite functionality, SimDB provides a framework for
9 /// creating "apps" which get selectively enabled based on your simulation
10 /// configuration (e.g. command line options, config file, etc).
11 ///
12 /// - Create your own data/metadata schema tables just for your app
13 /// - Use SimDB utilities to build async compression/transform/DB pipelines
14 ///
15 /// Example applications:
16 ///
17 /// - Logger that records simulation events
18 /// - Profiler that tracks performance metrics
19 /// - Pipeline collector
20 /// - CPU pipeline instrumentation/collection with front-end viewer (Argos)
21 /// - Backend for a live data visualization GUI / web interface
22 /// - Backend for post-sim analysis using simulation state replayers
23 ///
24 /// Since SimDB is designed to be simulator-agnostic, apps also provide
25 /// a variety of hooks that allow you to run code at different stages of
26 /// the simulation lifecycle and to ensure that all apps in your simulator
27 /// are initialized and run in a consistent manner.
28 ///
29 /// - defineSchema: (static) declare the app's schema tables. Called via the
30 /// app's AppFactory before any app instance is created.
31 /// - postInit: after command-line / config parsing, before the
32 /// simulation starts.
33 /// - createPipeline: create and configure the app's pipeline(s).
34 /// - preTeardown: just before simulation teardown; push any pending data
35 /// to your app's pipeline
36 /// - postTeardown: after simulation; post-sim metadata DB writes occur here;
37 /// all running apps' postTeardown methods are executed in a
38 /// single safeTransaction automatically (don't worry about
39 /// using safeTransaction explicitly)
40 ///
41 /// The general paradigm is that your simulator has a single output database,
42 /// with 1-to-many apps that are all writing to it with their own custom schemas
43 /// and logic.
44
45 namespace simdb {
46
47 class DatabaseManager;
48 class Schema;
49
50 namespace pipeline {
51 class AsyncDatabaseAccessor;
52 class PipelineManager;
53 } // namespace pipeline
54
55 class AppManager;
56 class ThreadSafeLogger;
57
58 /*!
59 * \class App
60 *
61 * \brief Base class for SimDB applications. Subclasses receive a
62 * DatabaseManager in the constructor and can append schemas, insert
63 * records, and create pipelines. Lifecycle hooks: postInit(),
64 * createPipeline(), preTeardown(), postTeardown(). Use AppManager
65 * to register, enable, and instantiate apps.
66 */
67 class App
68 {
69 public:
70 17 virtual ~App() = default;
71
72 /// \brief Set the instance number (1-based; 0 = single-instance). Called by AppManager.
73 void setInstance(size_t instance) { instance_ = instance; }
74
75 /// \brief Get the instance number (0 if single-instance).
76 6 size_t getInstance() const { return instance_; }
77
78 /// \brief Hook called after command-line parsing, before simulation starts.
79 1 virtual void postInit([[maybe_unused]] int argc, [[maybe_unused]] char** argv) {}
80
81 /// \brief Hook to create and configure this app's pipeline(s) on the given manager.
82 virtual void createPipeline(pipeline::PipelineManager*) = 0;
83
84 /// \brief Hook called before simulation teardown.
85 8 virtual void preTeardown() {}
86
87 /// \brief Hook called after simulation teardown (resource cleanup).
88 7 virtual void postTeardown() {}
89
90 /// \brief Return the app logger (set by AppManager); may be null.
91 ThreadSafeLogger* getAppLogger() const { return app_logger_; }
92
93 /// \brief Check if we are running in verbose mode.
94 5 bool verbose() const { return verbose_; }
95
96 protected:
97 void setAppLogger_(ThreadSafeLogger* logger) { app_logger_ = logger; }
98
99 private:
100 /// Instance number for multi-instance apps (1-based).
101 /// If zero, then this is a single-instance app.
102 size_t instance_ = 0;
103
104 /// Thread-safe loggers.
105 ThreadSafeLogger* app_logger_ = nullptr;
106
107 /// Verbose flag.
108 bool verbose_ = false;
109
110 friend class AppManager;
111 };
112
113 /*!
114 * \class AppFactoryBase
115 *
116 * \brief Abstract factory for creating App instances and defining their schema.
117 * Each app type exposes a nested AppFactory that implements this interface;
118 * AppManager uses it to instantiate apps and register their tables.
119 *
120 * \note It is optional to define a custom AppFactory nested in your app class.
121 * If you don't, the default AppFactory will be used, which creates the app
122 * with the default constructor (DatabaseManager*).
123 */
124 class AppFactoryBase
125 {
126 public:
127 14 virtual ~AppFactoryBase() = default;
128
129 /// \brief Create an App instance for the given DatabaseManager.
130 virtual App* createApp(DatabaseManager*) = 0;
131
132 /// \brief Define this app's schema (tables, columns) on the given Schema.
133 virtual void defineSchema(Schema& schema) const = 0;
134 };
135
136 /*!
137 * \class AppFactory
138 *
139 * \brief Default factory that creates AppT and delegates defineSchema to AppT::defineSchema.
140 * \tparam AppT App subclass (must have defineSchema(Schema&) and a constructor taking DatabaseManager*).
141 */
142 template <typename AppT> class AppFactory : public AppFactoryBase
143 {
144 public:
145
1/3
✓ Branch 3 → 4 taken 5 times.
✗ Branch 6 → 7 not taken.
✗ Branch 6 → 8 not taken.
13 App* createApp(DatabaseManager* db_mgr) override { return new AppT(db_mgr); }
146
147 13 void defineSchema(Schema& schema) const override { AppT::defineSchema(schema); }
148 };
149
150 } // namespace simdb
151