Commit Graph

11 Commits

Author SHA1 Message Date
b9c3267aad refactor(flatfile): single-line file header with format-version marker
All checks were successful
CI Code / Check coding style (pull_request) Successful in 59s
CI Code / Check spelling (pull_request) Successful in 1m35s
CI Code / Linux (debian) (pull_request) Successful in 7m24s
CI Code / Linux (ubuntu) (pull_request) Successful in 7m24s
CI Code / Code Coverage (pull_request) Successful in 6m56s
CI Code / Linux (arch) (pull_request) Successful in 9m36s
2026-05-05 13:59:38 +03:00
024e4b2336 style(flatfile): drop vim modeline from log file header 2026-05-04 18:29:55 +03:00
48b89460b7 feat(flatfile): warn on missing or mismatched log format-version 2026-05-04 17:17:33 +03:00
352eb26f71 refactor(flatfile): drop dead cursor_offset, guard inverted range
Some checks failed
CI Code / Check spelling (pull_request) Successful in 1m25s
CI Code / Check coding style (pull_request) Successful in 2m11s
CI Code / Linux (ubuntu) (pull_request) Successful in 4m47s
CI Code / Linux (debian) (pull_request) Successful in 7m58s
CI Code / Code Coverage (pull_request) Failing after 11m18s
CI Code / Linux (arch) (pull_request) Failing after 11m32s
2026-05-04 15:30:45 +03:00
1fe3808b23 style(export): gchar*/g_free consistency + auto_char in read loop
All checks were successful
CI Code / Check spelling (pull_request) Successful in 2m12s
CI Code / Check coding style (pull_request) Successful in 2m23s
CI Code / Linux (arch) (pull_request) Successful in 5m35s
CI Code / Linux (debian) (pull_request) Successful in 6m59s
CI Code / Linux (ubuntu) (pull_request) Successful in 7m41s
CI Code / Code Coverage (pull_request) Successful in 6m59s
2026-05-02 16:18:48 +03:00
8868d58920 fix(review): address PR #94 review #37/#38 reviewer comments
Parser (src/database_flatfile_parser.c):
- ff_jid_to_dir: drop GString+step1, in-place mutate str_replace result
- ff_ensure_dir: g_file_test(G_FILE_TEST_IS_SYMLINK) instead of g_lstat
- ff_unescape_*: early-continue for non-escape branch (less nesting)
- ff_readline: strdup("") instead of malloc(1)+'\0' for skip-line return
- ff_write_line: auto_char safe_msg + single fprintf (drop GString full_line)
- ff_parse_line: early return on missing closing bracket;
  extract metadata-parts loop into _ff_parse_meta_parts helper

Verify (src/database_flatfile_verify.c):
- Split monolithic ff_verify_integrity into _collect_contact_dirs,
  _check_permissions, _first_pass, _lmc_pass, _verify_contact_dir
- _issue_new constructor; g_new0 throughout
- Separate seen_stanza_ids and seen_archive_ids tables (no cross-kind
  duplicate confusion)
- ff_skip_bom in second pass (drop manual fgetc x3)
- log_debug when skipping a contact dir without history.log
- Doc comment on ff_verify_integrity in header

SQLite (src/database_sqlite.c):
- Doc block on ChatLogs schema (replaces_db_id <-> replaced_by_db_id
  invariant maintained by AFTER INSERT trigger)
- log_error when _get_db_filename returns NULL during init

Flatfile dispatch (src/database_flatfile.c):
- Replace if/else with is_outgoing ternary for log-path contact pick

Tests:
- 6 new invalid-date parser tests: empty / partial ISO / garbage /
  impossible calendar / negative year / far future timestamp
- New functional test message_db_history_multi_resource verifying
  same-JID-different-resource history rehydration preserves resources
- test_database_stress.c LMC chain loop: auto_char buf, drop redundant
  comment/empty pre-filter (ff_parse_line handles those)
2026-04-30 10:53:03 +03:00
a96a4ad41e fix(review): address PR #94 reviewer comments
Blockers:
- SPDX/CProof copyright headers (7 files)
- stanza-id non-uniqueness: warn-only, don't skip (matches SQLite)
- fopen → open(O_EXCL|O_NOFOLLOW, 0600) + fdopen in export

Medium:
- log_info → log_warning for SQLite fallback
- remove prefs_save() auto-save from backend switch
- vtable null → log_warning in 4 dispatch functions
- log_debug → log_warning + null error handling in export
- rename failure → cons_show_error to user
- remove unused total_skipped variable
- LMC respects PREF_CORRECTION_ALLOW

Low nits:
- man page .SS fix + jabber.space URL
- profrc.example simplified
- show flatfile path on /logging flatfile
- EXPORT_PROGRESS_INTERVAL constant (magic 500)
- FF_META_PREFIX_ID/AID constants + FF_INDEX_STEP comment
- buffer overflow guard on close[1]/close[2]
- for-loop → memchr for JID resource scan
- BOM check extracted to ff_skip_bom() (DRY)
- index building extracted to _ff_maybe_index_line()
- O_APPEND+O_EXCL comment rewritten
- Makefile.am spaces → tabs
2026-03-28 12:38:39 +03:00
71f9ab5007 perf: O(1) dedup/LMC cache, g_slist_append → prepend+reverse
- Add archive_ids hash set and stanza_senders hash map to
  ff_contact_state_t, populated during index build/extend via
  lightweight _ff_cache_line_ids() (no full parse overhead).
- Replace O(n) file scans in _ff_has_archive_id() and
  _ff_find_original_sender() with O(1) hash table lookups.
- Replace g_slist_append with g_slist_prepend + g_slist_reverse
  in _ff_apply_lmc, _flatfile_get_previous_chat, and
  ff_verify_integrity to avoid O(n²) list building.
- Add db_sqlite_last_changes() declaration to database.h.
2026-03-12 18:52:00 +03:00
507ef91b5f feat: complete field parity, harden export/import, add tests
Export/Import improvements:
- Replace pagination with direct SQL query (db_sqlite_get_all_chat)
- Wrap import in SQL transaction with rollback on error
- Add fsync before fclose in export for data safety
- Sort merged output by timestamp with secondary key (stanza_id, from_jid)
- Export archive_id and marked_read from SQLite (lossless migration)
- Add progress indication every 500 messages during write/import
- Expand dedup key body prefix from 64 to 256 chars
- Fix g_slist_append O(n²) → g_slist_prepend + g_slist_reverse O(n)

Field parity (to_jid, to_resource, marked_read):
- Add fields to ff_parsed_line_t struct
- Write/parse to:|to_res:|read: metadata tags in flatfile format
- Pass to_resource through _ff_add_message and all callers
- Add marked_read to ProfMessage struct with -1 default (unset)
- Preserve fields across export/import round-trips

Tests (19 new: 11 unit + 8 functional):
- Unit: to_jid_and_marked_read, bracket_in_stanza_id, backslash_in_resource,
  mucpm_type, all_enc_types, crlf_handling, to_jid_special_chars,
  multiple_lines, parsed_line_free_null_safe, no_space_rejected,
  unclosed_bracket
- Functional: export_idempotent_no_duplicates, export_lmc_correction_survives,
  switch_preserves_old_backend_data, export_all_contacts,
  import_double_dedup, verify_after_export,
  switch_backends_independent_messages, export_empty_contact
- Rebalance test groups: move Chat Session from Group 3 to Group 4
  (25/33/30/27 instead of 25/33/36/21)
- Remove hardcoded test counts from group comments

Man page:
- Document /history switch sqlite|flatfile
2026-03-12 18:46:42 +03:00
16ae7fb85c database_flatfile: single-file storage with sparse index
Replace per-contact directory structure with a single flat file per contact.
Each file uses pipe-delimited records with a sparse byte-offset index
that is rebuilt on demand and cached in memory.

- Rewrite _ff_write_record / _ff_read_records for single-file format
- Add sparse index (every Nth record) for O(log N) seek on history read
- Cursor-based pagination: _ff_get_previous_chat uses saved byte offset
- LMC corrections applied in-place during read (_ff_apply_lmc)
- Newline escaping (\n) in message bodies for line-based storage
- Simplify verify: parse + timestamp order + LMC reference check
- Update parser helpers for new field layout
2026-03-12 18:46:42 +03:00
d25f90899c refactor: split database_flatfile.c into functional modules
Split the monolithic database_flatfile.c into:
- database_flatfile.h: internal header with shared types and prototypes
- database_flatfile_parser.c: parsing, escaping, IO helpers
- database_flatfile_verify.c: integrity verification logic
- database_flatfile.c: core backend (init, write, read, LMC, vtable)
2026-03-12 18:46:42 +03:00