Skip to content

Commit 1fb4df0

Browse files
grammmikejengelh
authored andcommitted
exmdb: add ephemeral storage location
If /var/lib/gromox/user is on a networked filesystem, there may be a latency benefit of keeping tables.sqlite3 on a local disk (its data is currently specific to the running process anyway).
1 parent ca7d97a commit 1fb4df0

File tree

5 files changed

+21
-7
lines changed

5 files changed

+21
-7
lines changed

doc/exmdb_provider.4gx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
.\" SPDX-License-Identifier: CC-BY-SA-4.0 or-later
2-
.\" SPDX-FileCopyrightText: 2020-2022 grommunio GmbH
2+
.\" SPDX-FileCopyrightText: 2020–2025 grommunio GmbH
33
.TH exmdb_provider 4gx "" "Gromox" "Gromox admin reference"
44
.SH Name
55
exmdb_provider \(em Gromox Information Store
@@ -123,6 +123,17 @@ double its size, so ample disk space may be required.)
123123
.br
124124
Default: \fIyes\fP
125125
.TP
126+
\fBexmdb_eph_prefix\fP
127+
A path for where variadic data files that are process-temporary can be stored.
128+
This may be used to keep the tables.sqlite3 file off an NFS-backed homedir.
129+
Required disk space scales linearly with open table handles and linearly with
130+
messages in the opened folders, at about 80 bytes per messages. (In other
131+
words, don't lump molasses of messages into a single folder in a shared mailbox
132+
read by multiple people.) When you create the directory, set its ownership to
133+
gromox:gromox and mode to 0770.
134+
.br
135+
Default: (empty)
136+
.TP
126137
\fBexmdb_search_pacing\fP
127138
When initially populating a search folder (static or dynamic), yield the lock
128139
on the sqlite database (file descriptor) after so many messages to give other

exch/exmdb/db_engine.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#include <gromox/rop_util.hpp>
4848
#include <gromox/sortorder_set.hpp>
4949
#include <gromox/util.hpp>
50+
#include <gromox/fileio.h>
5051
#include "db_engine.hpp"
5152
#include "notification_agent.hpp"
5253
#define MAX_DYNAMIC_NODES 100
@@ -112,6 +113,7 @@ unsigned long long g_exmdb_search_pacing_time = 2000000000;
112113
unsigned int g_exmdb_search_yield, g_exmdb_search_nice;
113114
unsigned int g_exmdb_pvt_folder_softdel, g_exmdb_max_sqlite_spares;
114115
unsigned long long g_sqlite_busy_timeout_ns;
116+
std::string exmdb_eph_prefix;
115117

116118
static bool remove_from_hash(const db_base &, time_point);
117119
static void dbeng_notify_cttbl_modify_row(db_conn *, uint64_t folder_id, uint64_t message_id, db_base &) __attribute__((nonnull(1)));
@@ -568,7 +570,7 @@ db_handle db_base::get_db(const char* dir, DB_TYPE type)
568570
return handle;
569571
}
570572
const auto &path = type == DB_MAIN ? fmt::format("{}/exmdb/exchange.sqlite3", dir) :
571-
fmt::format("{}/tables.sqlite3", dir);
573+
fmt::format("{}/{}/tables.sqlite3", exmdb_eph_prefix, dir);
572574
int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_NOMUTEX;
573575
flags |= type == DB_MAIN? 0 : SQLITE_OPEN_CREATE;
574576
sqlite3 *db = nullptr;
@@ -625,7 +627,7 @@ void db_base::get_dbs(const char* dir, sqlite3 *&main, sqlite3 *&eph)
625627
void db_base::ctor2_and_open(const char *dir)
626628
{
627629
auto unlock = HX::make_scope_exit([this] { sqlite_lock.unlock(); --reference; }); /* unlock whenever we're done */
628-
auto db_path = fmt::format("{}/tables.sqlite3", dir);
630+
auto db_path = fmt::format("{}/{}/tables.sqlite3", exmdb_eph_prefix, dir);
629631
auto ret = ::unlink(db_path.c_str());
630632
if (ret != 0 && errno != ENOENT)
631633
throw std::runtime_error(fmt::format("E-1351: unlink {}: {}", db_path.c_str(), strerror(errno)));

exch/exmdb/db_engine.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ extern unsigned int g_exmdb_schema_upgrades, g_exmdb_search_pacing;
233233
extern unsigned long long g_exmdb_search_pacing_time, g_exmdb_lock_timeout;
234234
extern unsigned int g_exmdb_search_yield, g_exmdb_search_nice;
235235
extern unsigned int g_exmdb_pvt_folder_softdel;
236-
extern std::string g_exmdb_ics_log_file;
236+
extern std::string g_exmdb_ics_log_file, exmdb_eph_prefix;
237237
/* Max number of cached DB connections per store, 0 = unlimited */
238238
extern unsigned int g_exmdb_max_sqlite_spares;
239239
extern unsigned long long g_sqlite_busy_timeout_ns;

exch/exmdb/main.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ static constexpr cfg_directive exmdb_cfg_defaults[] = {
4747
{"dbg_synthesize_content", "0"},
4848
{"enable_dam", "1", CFG_BOOL},
4949
{"exmdb_body_autosynthesis", "1", CFG_BOOL},
50+
{"exmdb_eph_prefix", ""},
5051
{"exmdb_file_compression", "zstd-6"},
5152
{"exmdb_hosts_allow", ""}, /* ::1 default set later during startup */
5253
{"exmdb_listen_port", "5000"},
@@ -112,6 +113,7 @@ static bool exmdb_provider_reload(std::shared_ptr<config_file> gxcfg = nullptr,
112113
g_exmdb_search_pacing_time = pconfig->get_ll("exmdb_search_pacing_time");
113114
g_exmdb_max_sqlite_spares = pconfig->get_ll("exmdb_max_sqlite_spares");
114115
g_sqlite_busy_timeout_ns = pconfig->get_ll("sqlite_busy_timeout");
116+
exmdb_eph_prefix = pconfig->get_value("exmdb_eph_prefix");
115117
gx_sql_deep_backtrace = gxcfg->get_ll("exmdb_deep_backtrace");
116118
gx_force_write_txn = gxcfg->get_ll("exmdb_force_write_txn");
117119
auto s = gxcfg->get_value("exmdb_ics_log_file");

exch/exmdb/table.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
#include "db_engine.hpp"
3434
#include "parser.hpp"
3535

36-
using namespace std::string_literals;
3736
using LLU = unsigned long long;
3837
using namespace gromox;
3938

@@ -3033,7 +3032,7 @@ BOOL exmdb_server::store_table_state(const char *dir, uint32_t table_id,
30333032
return TRUE;
30343033
if (ptnode->type != table_type::content)
30353034
return TRUE;
3036-
const auto &state_path = exmdb_server::get_dir() + "/tmp/state.sqlite3"s;
3035+
const auto &state_path = exmdb_eph_prefix + "/" + exmdb_server::get_dir() + "/tablestate.sqlite3";
30373036
auto ret = gx_mkbasedir(state_path.c_str(), FMODE_PRIVATE | S_IXUSR | S_IXGRP);
30383037
if (ret < 0) {
30393038
mlog(LV_ERR, "E-2711: mkbasedir %s: %s", state_path.c_str(), strerror(-ret));
@@ -3322,7 +3321,7 @@ BOOL exmdb_server::restore_table_state(const char *dir, uint32_t table_id,
33223321
return TRUE;
33233322
if (ptnode->type != table_type::content)
33243323
return TRUE;
3325-
const auto &state_path = exmdb_server::get_dir() + "/tmp/state.sqlite3"s;
3324+
const auto &state_path = exmdb_eph_prefix + "/" + exmdb_server::get_dir() + "/tablestate.sqlite3";
33263325
if (stat(state_path.c_str(), &node_stat) != 0)
33273326
return TRUE;
33283327
sqlite3 *psqlite = nullptr;

0 commit comments

Comments
 (0)