AmberDB
view release on metacpan or search on metacpan
* Removed legacy internal _hash_diff from AmberDB::Tools and switched to $adb->hash_diff directly.
* Added unit test coverage for hash_diff in t/amberdb_array.t.
5.22.2 2026-09-01
- [CROSS-PLATFORM & CI] Universal GitHub Actions CI Matrix:
* Configured multi-platform CI matrix testing on Linux (ubuntu-latest), macOS (macos-latest), and Windows (windows-latest) across Perl 5.16 through 5.40.
* Configured official Strawberry Perl distribution in CI for native Berkeley DB / DB_File binary compatibility and prevented Git Bash PATH collisions.
- [STORAGE & TRANSACTIONS] Safe Directory Scanner and Windows File Sharing:
* Introduced dir_files($dir, [$pattern], [%opts]) helper method in AmberDB::Base for cross-platform, safe file discovery supporting wildcards (*.db, txn_*.txn) and compiled regular expressions (qr/../).
* Refactored AmberDB::Transact and AmberDB::Tools (dir_tables, all_tables, del_table) to use dir_files, completely removing fragile glob usage.
* Fixed Windows NTFS file sharing collision in transact_recover: journal lines are now read directly from open locked handles, preventing secondary open permission denied errors.
- [TESTS & STABILITY] Test Concurrency and Monotonic Sequence:
* Hardened t/amberdb_transact.t orphan recovery subtest to use strictly monotonic table_autoid record IDs (65) and authentic transaction lifecycle simulation.
* Guaranteed complete handle and lock cleanup with $adb->close_all() in crash recovery test scenarios.
5.22.1 2026-09-01
- [DOCS] Documentation and Synopsis Fixes:
* Fixed synopsis and API example signatures across documentation and POD.
* Updated README.md installation instructions with streamlined CPAN/cpanm cross-platform support.
* Fixed character encoding and wide-character warnings in test suite schemas.
- Declared missing core dependencies (Archive::Tar, Digest::SHA, JSON::PP, Hash::Util) in Makefile.PL and cpanfile.
5.21.0 2026-08-28
- Fixed schema cache poisoning in restore() and hardened dbase_info()/table_info() against caching empty parse results.
- Standardized instance variable naming across codebase, test suites, and documentation to $adb (AmberDB Handle):
* Introduced $adb->config() method supporting scalar get, defensive copy bulk get, and side-effect hook execution (locale reloading, path cache invalidation).
* Introduced $adb->path() method for standardized path retrieval and modification across core modules and scripts.
* Enhanced $adb->table_attr() with unified getter/setter and automatic path refresh on schema changes (year, section, lang).
* Protected $adb->table_info() by returning shallow copies to prevent external reference leaking and unauthorized in-memory state mutations.
* Refactored all internal core modules (lib/AmberDB.pm, lib/AmberDB/Base.pm, lib/AmberDB/Tools.pm, lib/AmberDB/Transact.pm, lib/AmberDB/Cache.pm, lib/AmberDB/Index/Junk.pm) to interact strictly through accessor methods ($adb->config, $adb->...
* Enforced restricted hash key access via Hash::Util::lock_keys with private internal naming (_cfg, _path, _table, _dbase, _cache, _db, _txn) and locked container references (Hash::Util::lock_value) against typo/unauthorized overwrites.
* Added comprehensive unit test suite t/amberdb_encapsulation.t covering all 10 encapsulation scenarios.
- [MIGRATION NOTICE / BREAKING CHANGE] Standardized schema terminology across the entire codebase and directory layout:
* UPGRADE ACTION REQUIRED: Existing projects must rename their physical 'dbstore/scheme/' directory to 'dbstore/schema/'.
* Updated RAM-disk setup scripts (setup_ramdisk.sh, setup_ramdisk.ps1, setup_ramdisk.pl, setup_ramdisk.bat) to mount 'schema/'.
- Upgraded transaction engine specification to full ACID-Compliance with Strict Two-Phase Locking (Strict 2PL):
* Enforced Lock-Before-Write and Lock-Before-Read ordering across insert_id, modify_id, and delete_id for true serializable isolation.
* Introduced 'no_transact => 1' schema attribute and table_attr() support to exempt auxiliary tables from abort cascades while preserving LIFO rollback consistency.
- Added comprehensive ACID architectural guarantees section to documentation (README.md, Turkish and English User Guides).
- Clarified architectural distinction between high-throughput batch ETL imports and atomic business transactions.
- Standardized file open error diagnostics and OS-level reporting ($!) across all core modules:
docs/EN.AmberDB_User-Guide.md view on Meta::CPAN
the system state becomes corrupted. To eliminate these anomalies, the entire sequence must be unified within a **single transaction spine (`transact_start` $\rightarrow$ `transact_end`)**. If any step encounters an error or if the process crashes, Am...
### 7.2 ACID Guarantees in AmberDB
AmberDB guarantees the four classical ACID properties through embedded flat-file database mechanics:
| ACID Property | Implementation Mechanism & Guarantees |
| :--- | :--- |
| **Atomicity** | **Disk-Backed Undo-Journaling:** When `transact_start()` is called, a microsecond-stamped `.txn` journal is created. Every `insert_id`, `modify_id`, and `delete_id` call appends reverse undo instructions. If a critical base error oc...
| **Consistency** | **Schema, Index, and State Integrity:** Inbound records are validated against schema field rules, data types, and byte limits. Primary keys (`autoid`), inverted word indexes, columnar facets, and URL slugs are synchronized in real...
| **Isolation** | **Strict Two-Phase Locking (Strict 2PL):** Every record modified within an active transaction acquires an exclusive OS-level lock (`flock LOCK_EX`). Locks are held throughout the entire transaction duration, preventing concurrent wo...
| **Durability** | **Synchronous Journaling & Crash Recovery (`transact_recover`):** All journal writes invoke `$fh->flush`. When configured with `cfg => { txn_sync => 1 }`, AmberDB triggers OS/kernel `fsync` (`$fh->sync`) and Berkeley DB cache flush...
> **Architectural Note: Batch ETL Imports vs. Business Transactions**
> Methods such as `insert_list`, `modify_list`, and `delete_list` are specialized for high-throughput batch imports (e.g., ingesting large XML/JSON product catalogs). Since list records are typically independent entities without cross-dependencies, d...
### 7.3 Transaction Workflow
In the public API, transaction workflows are driven by 3 primary methods:
1. **`transact_start()`**: Opens a microsecond-stamped undo journal (`txn_*`) in `$dbase_dir/journal/` and recovers any orphaned transactions left by dead processes (`transact_recover`).
lib/AmberDB/Base/Transact.pm view on Meta::CPAN
cluck "[DB_TXN] Orphan transaction rollback: $orphan\n";
seek( $ofh, 0, 0 );
my @lines = <$ofh>;
flock( $ofh, LOCK_UN );
close $ofh;
$self->_txn_apply_rollback(\@lines);
unlink $orphan;
}
else {
# File is actively locked by a living process â skip safely (race-condition free)
close $ofh;
next;
}
}
return 1;
}
# $ts = $adb->_txn_timestamp();
# ------------------------------------------------
t/amberdb_backup.t view on Meta::CPAN
# =========================================================================
# SUBTEST 4: Tools->restore() and Deterministic Index Rebuilding
# =========================================================================
subtest "4. Database Restore and Index Reconstruction" => sub {
plan tests => 17;
my $dump_file = "$tmpdir/backup/test_dump.amberdb";
# 4.1 Safety check: Restore into non-empty database without force should fail
my $tools = AmberDB::Tools->new($adb);
my $blocked_res = $tools->restore( file => $dump_file, force => 0 );
ok( !defined $blocked_res, "restore() without force on non-empty database returns undef" );
# 4.2 Create a completely clean staging database directory
my $stagedir = tempdir( CLEANUP => 1 );
$stagedir =~ s{\\}{/}g;
my $stage_adb = AmberDB->new(
path => { dbase_dir => $stagedir },
cfg => { user => "admin", language => "tr" },
);
my $stage_tools = AmberDB::Tools->new($stage_adb);
t/amberdb_cli.t view on Meta::CPAN
};
# ---------------------------------------------------------------------------
subtest '5. CRUD operations & no_write protection' => sub {
plan tests => 8;
my $out_conn = `"$perl_bin" -Ilib "$cli_path" connect path-dbase_dir="$test_dbdir" cfg-no_write=1 format=json`;
my $token = decode_json($out_conn)->{token};
# Attempt insert when no_write is 1
my $ins_blocked = `"$perl_bin" -Ilib "$cli_path" token=$token action=insert_id table=cli_items id=1 data='["Book",15]' 2>&1`;
like($ins_blocked, qr/no_write aktif/, "insert_id blocked when no_write=1");
# Enable writes in session
`"$perl_bin" -Ilib "$cli_path" token=$token cfg-no_write=0`;
# Insert record
my $ins_ok = `"$perl_bin" -Ilib "$cli_path" token=$token action=insert_id table=cli_items id=1 data='["Book",15]' format=json`;
my $ins_data = eval { decode_json($ins_ok) };
is($ins_data->{status}, 'ok', "insert_id succeeded after enabling writes");
is($ins_data->{id}, 1, "Inserted record ID is 1");
t/amberdb_security_paths.t view on Meta::CPAN
is( $res->{errors}->[0]->{context}, "test_table.db", "Correct error context captured" );
};
# ---------------------------------------------------------------------------
subtest '5. _eval_plural_rule hardening' => sub {
plan tests => 4;
ok( $adb->_eval_plural_rule("n == 1", 1), "n == 1 true for 1" );
ok( !$adb->_eval_plural_rule("n == 1", 5), "n == 1 false for 5" );
ok( !$adb->_eval_plural_rule("n / 0 == 1", 2), "Division by zero returns 0 safely without dying" );
ok( !$adb->_eval_plural_rule("system('dir')", 1), "Code injection strictly blocked by whitelist" );
};
done_testing();
t/amberdb_transact.t view on Meta::CPAN
ok( -e $orphan_file, 'Orphan journal file created for test' );
# Call recover orphans
$adb->transact_recover();
ok( !-e $orphan_file, 'Orphan journal file removed after recovery' );
my @rec65 = $adb->read_id( 'test_table', 65 );
is( scalar(@rec65), 0, 'Orphaned insert was rolled back' );
# 2. Test active locked journal protection
my $locked_file = File::Spec->catfile( $journal_dir, 'txn_locked_test_888888' );
open my $lfh, '+>>', $locked_file or die "Cannot create locked test file: $!";
use Fcntl qw(:flock);
flock( $lfh, LOCK_EX ); # Actively lock file
$adb->transact_recover();
ok( -e $locked_file, 'Actively locked journal file is NOT removed by orphan recovery' );
flock( $lfh, LOCK_UN );
close $lfh;
unlink $locked_file;
ok( !-e $locked_file, 'Locked test file cleaned up' );
};
# ---------------------------------------------------------------------------
subtest 'Transaction Durability with txn_sync' => sub {
plan tests => 4;
my $sync_adb = AmberDB->new(
cfg => { language => 'tr', txn_sync => 1 },
path => { dbase_dir => $tmpdir }
);
( run in 1.230 second using v1.01-cache-2.11-cpan-800906f7e73 )