no-DB mode implementation #94
@@ -379,7 +379,7 @@ log_database_export_to_flatfile(const gchar* const contact_jid)
|
||||
g_slist_free_full(merged, (GDestroyNotify)ff_parsed_line_free);
|
||||
|
||||
fflush(fp);
|
||||
fsync(fd); // ensure data is on disk before atomic rename
|
||||
fsync(fd); // ensure data is on disk before atomic rename
|
||||
fclose(fp); // also releases flock
|
||||
|
||||
// Atomic rename
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
|
||||
static sqlite3* g_chatlog_database;
|
||||
|
||||
static void _add_to_db(ProfMessage* message, char* type, const Jid* const from_jid, const Jid* const to_jid);
|
||||
static void _add_to_db(ProfMessage* message, const char* type, const Jid* const from_jid, const Jid* const to_jid);
|
||||
static char* _get_db_filename(ProfAccount* account);
|
||||
static prof_msg_type_t _get_message_type_type(const char* const type);
|
||||
static prof_enc_t _get_message_enc_type(const char* const encstr);
|
||||
@@ -147,22 +147,22 @@ _sqlite_init(ProfAccount* account)
|
||||
return TRUE;
|
||||
|
jabber.developer marked this conversation as resolved
|
||||
}
|
||||
|
||||
char* query = "CREATE TABLE IF NOT EXISTS `ChatLogs` ("
|
||||
"`id` INTEGER PRIMARY KEY AUTOINCREMENT, "
|
||||
"`from_jid` TEXT NOT NULL, "
|
||||
"`to_jid` TEXT NOT NULL, "
|
||||
"`from_resource` TEXT, "
|
||||
"`to_resource` TEXT, "
|
||||
"`message` TEXT, "
|
||||
"`timestamp` TEXT, "
|
||||
"`type` TEXT, "
|
||||
"`stanza_id` TEXT, "
|
||||
"`archive_id` TEXT, "
|
||||
"`encryption` TEXT, "
|
||||
"`marked_read` INTEGER, "
|
||||
"`replace_id` TEXT, "
|
||||
"`replaces_db_id` INTEGER, "
|
||||
"`replaced_by_db_id` INTEGER)";
|
||||
const char* query = "CREATE TABLE IF NOT EXISTS `ChatLogs` ("
|
||||
|
jabber.developer marked this conversation as resolved
Outdated
jabber.developer
commented
Here and in other places, can we return necessary documentation detailing DB fields, decisions, and other useful points? Here and in other places, can we return necessary documentation detailing DB fields, decisions, and other useful points?
jabber.developer2
commented
Corrected Corrected
|
||||
"`id` INTEGER PRIMARY KEY AUTOINCREMENT, "
|
||||
"`from_jid` TEXT NOT NULL, "
|
||||
"`to_jid` TEXT NOT NULL, "
|
||||
"`from_resource` TEXT, "
|
||||
"`to_resource` TEXT, "
|
||||
"`message` TEXT, "
|
||||
"`timestamp` TEXT, "
|
||||
"`type` TEXT, "
|
||||
"`stanza_id` TEXT, "
|
||||
"`archive_id` TEXT, "
|
||||
"`encryption` TEXT, "
|
||||
"`marked_read` INTEGER, "
|
||||
"`replace_id` TEXT, "
|
||||
"`replaces_db_id` INTEGER, "
|
||||
"`replaced_by_db_id` INTEGER)";
|
||||
if (SQLITE_OK != sqlite3_exec(g_chatlog_database, query, NULL, 0, &err_msg)) {
|
||||
goto out;
|
||||
}
|
||||
@@ -251,7 +251,7 @@ _sqlite_add_incoming(ProfMessage* message)
|
||||
}
|
||||
|
||||
static void
|
||||
_log_database_add_outgoing(char* type, const char* const id, const char* const barejid, const char* const message, const char* const replace_id, prof_enc_t enc)
|
||||
_log_database_add_outgoing(const char* type, const char* const id, const char* const barejid, const char* const message, const char* const replace_id, prof_enc_t enc)
|
||||
{
|
||||
ProfMessage* msg = message_init();
|
||||
|
||||
@@ -350,8 +350,8 @@ _sqlite_get_previous_chat(const gchar* const contact_barejid, const gchar* start
|
||||
return DB_RESPONSE_ERROR;
|
||||
}
|
||||
|
||||
gchar* sort1 = from_start ? "ASC" : "DESC";
|
||||
gchar* sort2 = !flip ? "ASC" : "DESC";
|
||||
const gchar* sort1 = from_start ? "ASC" : "DESC";
|
||||
const gchar* sort2 = !flip ? "ASC" : "DESC";
|
||||
GDateTime* now = g_date_time_new_now_local();
|
||||
auto_gchar gchar* end_date_fmt = end_time ? g_strdup(end_time) : g_date_time_format_iso8601(now);
|
||||
auto_sqlite gchar* query = sqlite3_mprintf("SELECT * FROM ("
|
||||
@@ -571,7 +571,7 @@ _get_message_enc_type(const char* const encstr)
|
||||
// --- Core write logic ---
|
||||
|
||||
static void
|
||||
_add_to_db(ProfMessage* message, char* type, const Jid* const from_jid, const Jid* const to_jid)
|
||||
_add_to_db(ProfMessage* message, const char* type, const Jid* const from_jid, const Jid* const to_jid)
|
||||
{
|
||||
auto_gchar gchar* pref_dblog = prefs_get_string(PREF_DBLOG);
|
||||
sqlite_int64 original_message_id = -1;
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
int group = 0; /* 0 = all groups */
|
||||
int group = 0; /* 0 = all groups */
|
||||
if (argc > 1) {
|
||||
group = atoi(argv[1]);
|
||||
if (group < 1 || group > 4) {
|
||||
@@ -79,7 +79,7 @@ main(int argc, char* argv[])
|
||||
char group_env[16];
|
||||
snprintf(group_env, sizeof(group_env), "%d", group);
|
||||
setenv("PROF_TEST_GROUP", group_env, 1);
|
||||
|
||||
|
||||
fprintf(stderr, "[PROF_TEST] Starting functional tests, group=%d\n", group);
|
||||
|
||||
/* ============================================================
|
||||
@@ -268,7 +268,8 @@ main(int argc, char* argv[])
|
||||
};
|
||||
|
||||
/* Test group registry for easy extension */
|
||||
struct {
|
||||
struct
|
||||
{
|
||||
const char* name;
|
||||
const struct CMUnitTest* tests;
|
||||
size_t count;
|
||||
|
||||
@@ -377,11 +377,6 @@ init_prof_test(void **state)
|
||||
"[notifications]\n"
|
||||
"message=false\n"
|
||||
"room=false\n");
|
||||
const char *flatfile_env = getenv("PROF_FLATFILE");
|
||||
if (flatfile_env && strcmp(flatfile_env, "1") == 0) {
|
||||
fprintf(prc, "[logging]\ndblog=flatfile\n");
|
||||
printf("[PROF_TEST] Wrote profrc with dblog=flatfile: %s\n", profrc_path);
|
||||
}
|
||||
fclose(prc);
|
||||
}
|
||||
|
||||
@@ -441,17 +436,33 @@ prof_stop(void)
|
||||
{
|
||||
if (fd > 0 && child_pid > 0) {
|
||||
prof_input("/quit");
|
||||
sleep(1);
|
||||
waitpid(child_pid, NULL, 0);
|
||||
sleep_ms(QUIT_GRACE_MS);
|
||||
close(fd);
|
||||
fd = 0;
|
||||
int exited = 0;
|
||||
for (int i = 0; i < SHUTDOWN_POLL_MAX; i++) {
|
||||
if (waitpid(child_pid, NULL, WNOHANG) != 0) {
|
||||
exited = 1;
|
||||
break;
|
||||
}
|
||||
sleep_ms(SHUTDOWN_POLL_MS);
|
||||
}
|
||||
if (!exited) {
|
||||
kill(child_pid, SIGTERM);
|
||||
for (int i = 0; i < SIGTERM_POLL_MAX; i++) {
|
||||
if (waitpid(child_pid, NULL, WNOHANG) != 0) { exited = 1; break; }
|
||||
sleep_ms(SHUTDOWN_POLL_MS);
|
||||
}
|
||||
if (!exited) {
|
||||
kill(child_pid, SIGKILL);
|
||||
waitpid(child_pid, NULL, 0);
|
||||
}
|
||||
}
|
||||
child_pid = 0;
|
||||
}
|
||||
/* Reset output buffer for clean restart */
|
||||
output_len = 0;
|
||||
output_buffer[0] = '\0';
|
||||
/* Brief delay to let stabber release old connection state */
|
||||
usleep(200000); /* 200ms */
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -11,17 +11,17 @@ extern char xdg_data_home[256];
|
||||
|
||||
extern int stub_port;
|
||||
|
||||
int init_prof_test(void **state);
|
||||
int close_prof_test(void **state);
|
||||
int init_prof_test(void** state);
|
||||
int close_prof_test(void** state);
|
||||
|
||||
void prof_start(void);
|
||||
void prof_stop(void);
|
||||
void prof_connect(void);
|
||||
void prof_connect_with_roster(const char *roster);
|
||||
void prof_input(const char *input);
|
||||
void prof_connect_with_roster(const char* roster);
|
||||
void prof_input(const char* input);
|
||||
|
||||
int prof_output_exact(const char *text);
|
||||
int prof_output_regex(const char *text);
|
||||
int prof_output_exact(const char* text);
|
||||
int prof_output_regex(const char* text);
|
||||
|
||||
void prof_timeout(int timeout);
|
||||
void prof_timeout_reset(void);
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
* it was persisted to and read back from the database
|
||||
*/
|
||||
void
|
||||
message_db_history_on_reopen(void **state)
|
||||
message_db_history_on_reopen(void** state)
|
||||
{
|
||||
prof_connect();
|
||||
|
||||
@@ -81,7 +81,7 @@ message_db_history_on_reopen(void **state)
|
||||
* we can reliably synchronise on each delivery before proceeding.
|
||||
*/
|
||||
void
|
||||
message_db_history_multiple(void **state)
|
||||
message_db_history_multiple(void** state)
|
||||
{
|
||||
prof_connect();
|
||||
|
||||
@@ -131,7 +131,7 @@ message_db_history_multiple(void **state)
|
||||
* 3. Open buddy1 → verify buddy1's body present, buddy2's body absent
|
||||
*/
|
||||
void
|
||||
message_db_history_contact_isolation(void **state)
|
||||
message_db_history_contact_isolation(void** state)
|
||||
{
|
||||
prof_connect();
|
||||
|
||||
@@ -177,7 +177,7 @@ message_db_history_contact_isolation(void **state)
|
||||
* characters and return them unchanged.
|
||||
*/
|
||||
void
|
||||
message_db_history_special_chars(void **state)
|
||||
message_db_history_special_chars(void** state)
|
||||
{
|
||||
prof_connect();
|
||||
|
||||
@@ -210,7 +210,7 @@ message_db_history_special_chars(void **state)
|
||||
* and catches crashes in the outgoing DB code.
|
||||
*/
|
||||
void
|
||||
message_db_history_outgoing(void **state)
|
||||
message_db_history_outgoing(void** state)
|
||||
{
|
||||
prof_connect();
|
||||
|
||||
@@ -238,7 +238,7 @@ message_db_history_outgoing(void **state)
|
||||
* and the outgoing write path completed without error.
|
||||
*/
|
||||
void
|
||||
message_db_history_dialog(void **state)
|
||||
message_db_history_dialog(void** state)
|
||||
{
|
||||
prof_connect();
|
||||
|
||||
@@ -279,7 +279,7 @@ message_db_history_dialog(void **state)
|
||||
* does not crash and the window is usable.
|
||||
*/
|
||||
void
|
||||
message_db_history_empty(void **state)
|
||||
message_db_history_empty(void** state)
|
||||
{
|
||||
prof_connect();
|
||||
|
||||
@@ -299,7 +299,7 @@ message_db_history_empty(void **state)
|
||||
* Test: a long message (1000+ characters) is not truncated by the DB.
|
||||
*/
|
||||
void
|
||||
message_db_history_long_message(void **state)
|
||||
message_db_history_long_message(void** state)
|
||||
{
|
||||
prof_connect();
|
||||
|
||||
@@ -313,10 +313,11 @@ message_db_history_long_message(void **state)
|
||||
|
||||
char xml[1500];
|
||||
snprintf(xml, sizeof(xml),
|
||||
"<message id='long1' to='stabber@localhost' "
|
||||
"from='buddy1@localhost/phone' type='chat'>"
|
||||
"<body>%s</body>"
|
||||
"</message>", body);
|
||||
"<message id='long1' to='stabber@localhost' "
|
||||
"from='buddy1@localhost/phone' type='chat'>"
|
||||
"<body>%s</body>"
|
||||
"</message>",
|
||||
body);
|
||||
stbbr_send(xml);
|
||||
|
||||
assert_true(prof_output_exact("<< chat message: Buddy1/phone (win 2)"));
|
||||
@@ -335,7 +336,7 @@ message_db_history_long_message(void **state)
|
||||
* Uses XML character reference for literal newline in body.
|
||||
*/
|
||||
void
|
||||
message_db_history_newline(void **state)
|
||||
message_db_history_newline(void** state)
|
||||
{
|
||||
prof_connect();
|
||||
|
||||
@@ -364,7 +365,7 @@ message_db_history_newline(void **state)
|
||||
* percent, braces, brackets, equals) survive DB round-trip.
|
||||
*/
|
||||
void
|
||||
message_db_history_service_chars(void **state)
|
||||
message_db_history_service_chars(void** state)
|
||||
{
|
||||
prof_connect();
|
||||
|
||||
@@ -389,7 +390,7 @@ message_db_history_service_chars(void **state)
|
||||
* Test: /history verify reports no issues after normal message writes.
|
||||
*/
|
||||
void
|
||||
message_db_history_verify(void **state)
|
||||
message_db_history_verify(void** state)
|
||||
{
|
||||
prof_connect();
|
||||
|
||||
@@ -425,7 +426,7 @@ message_db_history_verify(void **state)
|
||||
* text should appear — the original should be absent.
|
||||
*/
|
||||
void
|
||||
message_db_history_lmc(void **state)
|
||||
message_db_history_lmc(void** state)
|
||||
{
|
||||
prof_connect();
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
void message_db_history_on_reopen(void **state);
|
||||
void message_db_history_multiple(void **state);
|
||||
void message_db_history_contact_isolation(void **state);
|
||||
void message_db_history_special_chars(void **state);
|
||||
void message_db_history_outgoing(void **state);
|
||||
void message_db_history_dialog(void **state);
|
||||
void message_db_history_empty(void **state);
|
||||
void message_db_history_long_message(void **state);
|
||||
void message_db_history_newline(void **state);
|
||||
void message_db_history_service_chars(void **state);
|
||||
void message_db_history_verify(void **state);
|
||||
void message_db_history_lmc(void **state);
|
||||
void message_db_history_on_reopen(void** state);
|
||||
void message_db_history_multiple(void** state);
|
||||
void message_db_history_contact_isolation(void** state);
|
||||
void message_db_history_special_chars(void** state);
|
||||
void message_db_history_outgoing(void** state);
|
||||
void message_db_history_dialog(void** state);
|
||||
void message_db_history_empty(void** state);
|
||||
void message_db_history_long_message(void** state);
|
||||
void message_db_history_newline(void** state);
|
||||
void message_db_history_service_chars(void** state);
|
||||
void message_db_history_verify(void** state);
|
||||
void message_db_history_lmc(void** state);
|
||||
|
||||
Reference in New Issue
Block a user
We might want to also check integrity of the tables (whether they exist + maybe even their columns). But it would introduce further complexity and should be a subject of a separate issue.
Postponed