feat: add /history switch for runtime database backend switching
All checks were successful
CI Code / Check spelling (pull_request) Successful in 18s
CI Code / Check coding style (pull_request) Successful in 1m10s
CI Code / Linux (debian) (pull_request) Successful in 6m20s
CI Code / Linux (ubuntu) (pull_request) Successful in 6m27s
CI Code / Code Coverage (pull_request) Successful in 9m5s
CI Code / Linux (arch) (pull_request) Successful in 11m22s
All checks were successful
CI Code / Check spelling (pull_request) Successful in 18s
CI Code / Check coding style (pull_request) Successful in 1m10s
CI Code / Linux (debian) (pull_request) Successful in 6m20s
CI Code / Linux (ubuntu) (pull_request) Successful in 6m27s
CI Code / Code Coverage (pull_request) Successful in 9m5s
CI Code / Linux (arch) (pull_request) Successful in 11m22s
Add log_database_switch_backend() that closes the current backend, updates PREF_DBLOG preference, and reinitializes with the new backend without requiring a reconnect or restart. New command: /history switch sqlite|flatfile - Validates connection state and backend name - Skips if already using the requested backend - Autocomplete support for the subcommand
This commit is contained in:
@@ -276,6 +276,7 @@ static Autocomplete logging_group_ac;
|
||||
static Autocomplete privacy_ac;
|
||||
static Autocomplete privacy_log_ac;
|
||||
static Autocomplete history_ac;
|
||||
static Autocomplete history_switch_ac;
|
||||
static Autocomplete color_ac;
|
||||
static Autocomplete correction_ac;
|
||||
static Autocomplete avatar_ac;
|
||||
@@ -431,6 +432,7 @@ static Autocomplete* all_acs[] = {
|
||||
&privacy_ac,
|
||||
&privacy_log_ac,
|
||||
&history_ac,
|
||||
&history_switch_ac,
|
||||
&color_ac,
|
||||
&correction_ac,
|
||||
&avatar_ac,
|
||||
@@ -1144,10 +1146,14 @@ cmd_ac_init(void)
|
||||
|
||||
autocomplete_add(history_ac, "on");
|
||||
autocomplete_add(history_ac, "off");
|
||||
autocomplete_add(history_ac, "switch");
|
||||
autocomplete_add(history_ac, "verify");
|
||||
autocomplete_add(history_ac, "export");
|
||||
autocomplete_add(history_ac, "import");
|
||||
|
||||
autocomplete_add(history_switch_ac, "sqlite");
|
||||
autocomplete_add(history_switch_ac, "flatfile");
|
||||
|
||||
autocomplete_add(logging_group_ac, "on");
|
||||
autocomplete_add(logging_group_ac, "off");
|
||||
autocomplete_add(logging_group_ac, "color");
|
||||
@@ -1795,6 +1801,11 @@ _cmd_ac_complete_params(ProfWin* window, const char* const input, gboolean previ
|
||||
}
|
||||
}
|
||||
|
||||
result = autocomplete_param_with_ac(input, "/history switch", history_switch_ac, TRUE, previous);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = autocomplete_param_with_ac(input, "/history", history_ac, TRUE, previous);
|
||||
if (result) {
|
||||
return result;
|
||||
|
||||
@@ -1882,17 +1882,20 @@ static const struct cmd_t command_defs[] = {
|
||||
CMD_TAG_CHAT)
|
||||
CMD_SYN(
|
||||
"/history on|off",
|
||||
"/history switch sqlite|flatfile",
|
||||
"/history verify [<jid>]",
|
||||
"/history export [<jid>]",
|
||||
"/history import [<jid>]")
|
||||
CMD_DESC(
|
||||
"Switch chat history on or off, /logging chat will automatically be enabled when this setting is on. "
|
||||
"When history is enabled, previous messages are shown in chat windows. "
|
||||
"Use 'switch' to change the active database backend at runtime without reconnecting. "
|
||||
"Use 'verify' to check integrity of stored message history. "
|
||||
"Use 'export' to copy messages from SQLite to flat-file format, or 'import' to copy from flat-file to SQLite. "
|
||||
"Both export and import merge with existing data (duplicates are skipped).")
|
||||
CMD_ARGS(
|
||||
{ "on|off", "Enable or disable showing chat history." },
|
||||
{ "switch sqlite|flatfile", "Switch the active database backend at runtime." },
|
||||
{ "verify [<jid>]", "Verify integrity of message history. Optionally specify a JID to check only one contact." },
|
||||
{ "export [<jid>]", "Export SQLite history to flat-file format. Optionally specify a JID to export only one contact." },
|
||||
{ "import [<jid>]", "Import flat-file history into SQLite. Optionally specify a JID to import only one contact." })
|
||||
|
||||
@@ -6735,6 +6735,37 @@ cmd_history(ProfWin* window, const char* const command, gchar** args)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (g_strcmp0(args[0], "switch") == 0) {
|
||||
jabber_conn_status_t conn_status = connection_get_status();
|
||||
if (conn_status != JABBER_CONNECTED) {
|
||||
cons_show_error("You must be connected to switch database backend.");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (args[1] == NULL) {
|
||||
cons_bad_cmd_usage(command);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (g_strcmp0(args[1], "sqlite") != 0 && g_strcmp0(args[1], "flatfile") != 0) {
|
||||
cons_show_error("Backend must be 'sqlite' or 'flatfile'.");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (active_db_backend && g_strcmp0(active_db_backend->name, args[1]) == 0) {
|
||||
cons_show("Already using '%s' backend.", args[1]);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
cons_show("Switching database backend to '%s'...", args[1]);
|
||||
if (log_database_switch_backend(args[1])) {
|
||||
cons_show("Database backend switched to '%s'.", args[1]);
|
||||
} else {
|
||||
cons_show_error("Failed to switch database backend.");
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (g_strcmp0(args[0], "verify") == 0) {
|
||||
const gchar* contact_jid = args[1]; // may be NULL (verify all)
|
||||
cons_show("Verifying history integrity...");
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include "config.h"
|
||||
#include "database.h"
|
||||
#include "config/preferences.h"
|
||||
#include "config/accounts.h"
|
||||
#include "ui/ui.h"
|
||||
#include "xmpp/xmpp.h"
|
||||
#include "xmpp/message.h"
|
||||
@@ -96,6 +97,34 @@ log_database_close(void)
|
||||
active_db_backend = NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
log_database_switch_backend(const char* new_backend)
|
||||
{
|
||||
// Close current backend
|
||||
log_database_close();
|
||||
|
||||
// Update preference
|
||||
prefs_set_string(PREF_DBLOG, new_backend);
|
||||
prefs_save();
|
||||
|
||||
// Get current account to reinitialize
|
||||
const char* account_name = session_get_account_name();
|
||||
if (!account_name) {
|
||||
log_error("log_database_switch_backend: no active session");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ProfAccount* account = accounts_get_account(account_name);
|
||||
if (!account) {
|
||||
log_error("log_database_switch_backend: account '%s' not found", account_name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean result = log_database_init(account);
|
||||
account_free(account);
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
log_database_add_incoming(ProfMessage* message)
|
||||
{
|
||||
|
||||
@@ -93,6 +93,7 @@ db_backend_t* db_backend_flatfile(void);
|
||||
|
||||
// Public API (dispatches to active_db_backend)
|
||||
gboolean log_database_init(ProfAccount* account);
|
||||
gboolean log_database_switch_backend(const char* new_backend);
|
||||
void log_database_add_incoming(ProfMessage* message);
|
||||
void log_database_add_outgoing_chat(const char* const id, const char* const barejid, const char* const message, const char* const replace_id, prof_enc_t enc);
|
||||
void log_database_add_outgoing_muc(const char* const id, const char* const barejid, const char* const message, const char* const replace_id, prof_enc_t enc);
|
||||
|
||||
@@ -25,9 +25,14 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "database.h"
|
||||
#include "database_flatfile.h"
|
||||
|
||||
db_backend_t* active_db_backend = NULL;
|
||||
|
||||
// The flatfile parser needs this global for path construction.
|
||||
// In tests we keep it NULL since no real file I/O happens via the backend.
|
||||
char* g_flatfile_account_jid = NULL;
|
||||
|
||||
gboolean
|
||||
log_database_init(ProfAccount* account)
|
||||
{
|
||||
@@ -53,6 +58,11 @@ void
|
||||
log_database_close(void)
|
||||
{
|
||||
}
|
||||
gboolean
|
||||
log_database_switch_backend(const char* new_backend)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
GSList*
|
||||
log_database_verify_integrity(const gchar* const contact_barejid)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user