no-DB mode implementation #94
@@ -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." },
|
||||
|
jabber.developer marked this conversation as resolved
Outdated
|
||||
{ "verify [<jid>]", "Verify integrity of message history. Optionally specify a JID to check only one contact." },
|
||||
|
jabber.developer marked this conversation as resolved
Outdated
jabber.developer
commented
How does it align with flatfile manual editability? How does it align with flatfile manual editability?
jabber.developer2
commented
needs a doc paragraph explaining that ff_verify_integrity flags timestamp drift, dup IDs, broken LMC refs etc. so manual edits remain auditable. Doc-only follow-up needs a doc paragraph explaining that ff_verify_integrity flags timestamp drift, dup IDs, broken LMC refs etc. so manual edits remain auditable. Doc-only follow-up
|
||||
{ "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.");
|
||||
|
jabber.developer2 marked this conversation as resolved
Outdated
jabber.developer
commented
It future, this requirement should be removed as it doesn't make much sense. Offline capabilities are really lacking. But I see why it exists (local SQLite is getting disconnected on disconnect). Feel free to click "resolve" on this comment. It future, this requirement should be removed as it doesn't make much sense. Offline capabilities are really lacking. But I see why it exists (local SQLite is getting disconnected on disconnect).
Feel free to click "resolve" on this comment.
|
||||
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) {
|
||||
|
jabber.developer2 marked this conversation as resolved
Outdated
jabber.developer
commented
Nice nesting: everything is flat. Easy to read, easy to maintain. Resolveable. Nice nesting: everything is flat. Easy to read, easy to maintain.
Resolveable.
|
||||
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();
|
||||
|
jabber.developer marked this conversation as resolved
jabber.developer
commented
Typically, prefs are not autosaved and need manual saving via Typically, prefs are not autosaved and need manual saving via `/save` command. This place creates an exception, which needs to be discussed (e.g., later we might add `/autosave` command).
jabber.developer2
commented
Corrected Corrected
|
||||
|
||||
// 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
Does the switch automatically export/import? It is unclear from documentation.
documentation-only clarification, queued. /history switch only swaps the active backend; data is not migrated unless the user runs /history export and /history import explicitly.