Skip to content

Latest commit

 

History

History
154 lines (114 loc) · 5.92 KB

File metadata and controls

154 lines (114 loc) · 5.92 KB

What's New

Audit: 10-byte padded alias in RESOLVED log lines (v1.8.99)

Every RESOLVED audit line now includes the table alias (filename stem) as a 10-byte right-padded field between the timestamp and the message. This makes it possible to identify which table a log entry refers to without cross-referencing the asked/resolved paths.

New log format:

CONN(6) ENTRY(8) SEQ(8) TIMESTAMP ALIAS(10) RESOLVED="..." ...

Example:

NMWIF0 00000004 00000005 2026-08-21 16:17:26.012 USER_CONFG RESOLVED="C:/data/USER_CONFG.dbf" JAILED ASKED="USER_CONFG" VIA=LOCAL

The alias is right-padded with spaces if shorter than 10 characters, and truncated from the left if longer. Both server-side (openads.ini log file) and client-side (_arc32/ace_calls.log) table opens emit the alias.


What's New

Fix: multi-user record count staleness (v1.8.30)

When multiple instances share a table via remote connection, Browse() and LastRec() showed only records visible at open time. Records appended by other connections were invisible — causing "phantom records" and stale record counts.

Root cause: Three-layer caching was never invalidated by external writes:

Layer Location Problem
Client rec_count_cached AdsGetRecordCount Cached forever; only cleared on local writes
AdsRefreshRecord ace_exports.cpp Only cleared row_valid, not rec_count_cached
Server rec_count_ GetRecordCount handler Returned stale in-memory value

Fix: AdsRefreshRecord now clears rec_count_cached. The server's GetRecordCount handler now re-reads the DBF header from disk before responding. New IDriver::refresh_record_count_from_disk() virtual method ensures all drivers (CDX, ADT, NTX, Cached) can refresh.

Impact: 30 concurrent instances each appending 5 records → all instances now see all 150 records after repositioning (GoTop/GoBottom/Browse).


What's New

CDX seek_key: 1,000x+ faster GOTO with active order (v1.8.29)

The seek_key function used a linear scan through decoded branch pages — O(N) per seek, degenerating to O(N²) for a full traversal of 20,000+ records. Replaced with a proper B-tree descent using binary search at each internal node and within leaf pages.

Operation Before After Speedup
Sequential seek_key 4,149 µs 3.2 µs 1,294x
Random seek_key 4,215 µs 3.6 µs 1,162x
Soft seek (miss) 8,318 µs 2.4 µs 3,518x

This fixes the extremely slow GOTO with active CDX order: 47 seconds for 20,000 records → under 0.05 seconds.

What's New

hbnetio Bridge for OpenADS (v1.8.28)

OpenADS can now transparently bridge to harbour's hbnetio virtual file system and RPC capabilities. This enables multi-client concurrent access to shared files on a remote hbnetio server (e.g. AWS EC2).

VFS Adapter — maps hb_vf*() operations over OpenADS ITransport:

hbnetio VFS Adapter Description
hb_vfOpen() VfsAdapter::open() Open/create file
hb_vfClose() VfsAdapter::close() Close file handle
hb_vfLock() VfsAdapter::lock() Byte-range lock
hb_vfUnlock() VfsAdapter::unlock() Release lock
hb_vfRead() VfsAdapter::read() Sequential read
hb_vfWrite() VfsAdapter::write() Sequential write
hb_vfReadAt() VfsAdapter::read_at() Positioned read
hb_vfWriteAt() VfsAdapter::write_at() Positioned write
hb_vfSeek() VfsAdapter::seek() Set file position
hb_vfTrunc() VfsAdapter::truncate() Truncate file
hb_vfSize() VfsAdapter::size() Get file size
hb_vfEof() VfsAdapter::eof() Test end-of-file

Distributed Lock Manager — implements the __isLocked() pattern:

  • Automatic .lck file creation and management
  • Configurable retry with backoff (mirrors hb_idleSleep(2))
  • Session-scoped lock tracking with RAII guards
  • Bulk release on session disconnect

RPC Bridge — maps hbnetio RPC to OpenADS session dispatch:

hbnetio Function RPC Bridge Description
netio_FuncExec() RpcClient::func_exec() Call function, get result
netio_ProcExec() RpcClient::proc_exec() Fire-and-forget
netio_ProcExecW() RpcClient::proc_exec_w() Wait for completion
netio_ProcExists() RpcClient::proc_exists() Check availability
netio_OpenDataStream() RpcClient::open_data_stream() Server push
netio_GetData() RpcClient::get_stream_data() Read stream
netio_CloseStream() RpcClient::close_stream() Close channel

Configuration

Enable: cmake -DOPENADS_WITH_HBNETIO_BRIDGE=ON ..

Wire opcodes 0xF0-0xFC (no conflict with existing opcodes).

Files

  • contrib/hbnetio_bridge/vfs_adapter.h/.cpp - VFS adapter
  • contrib/hbnetio_bridge/dist_lock_mgr.h/.cpp - Lock manager
  • contrib/hbnetio_bridge/rpc_bridge.h/.cpp - RPC bridge
  • contrib/hbnetio_bridge/CMakeLists.txt - Build option
  • contrib/hbnetio_bridge/README.md - Documentation
  • docs/en/hbnetio-bridge.md - Reference guide

HB_FUNC Wrappers for Harbour (contrib/oads_hb/)

HB_FUNC Wrappers for Harbour (contrib/oads_hb/)

Harbour PRG code can now call the oads_*() C functions directly:

Function Parameters Returns
OADS_FCreate (hConn, cFile, nAttr) hFile (0=fail)
OADS_FOpen (hConn, cFile, nMode) hFile (0=fail)
OADS_FClose (hFile) lOk
OADS_FWrite (hFile, cData) nBytesWritten
OADS_FRead (hFile, nLen) cData
OADS_FSeek (hFile, nOffset, nOrigin) nPosition

Comprehensive Tests

  • oads_imac_test — standalone test against iMac LAN server (all 6 functions)
  • abi_oads_file_funcs_test — doctest unit tests (local + remote)
  • test_oads_file.prg — Harbour PRG test

Test Results

Tested against iMac at 192.168.18.184:16262 — 34/36 passed.