Add a Services API (service_mgr) for the native client: server version, backup and restore with streamed verbose output - #174
Conversation
Implements the Firebird Services API - the administration channel that
gbak and the other command-line tools use - for the native client
(linking and dynamic_loading features).
rsfbclient-native:
* activate the isc_service_attach/start/query/detach bindings that
were already present (commented out) in ibase.rs
* new services module: NativeServiceManager, a thin safe wrapper
owning the service handle, with per-linkage constructors
(attach_dyn_link / attach_dyn_load) and detach-on-drop
rsfbclient:
* new services module (behind the native_client feature):
ServiceManager + builder (host/port/user/pass, optional
with_dyn_load), server_version(), backup/restore with typed
option structs (SvcBackupOptions, SvcRestoreOptions), and
_with_output variants that stream the verbose gbak log line by
line while the action runs. SPB construction handles the
version-2 attach block (one-byte lengths) and start-request
blocks (two-byte lengths) - the classic Services API trap -
in two small documented helpers.
* front-page doc chapter and full rustdoc on the module, stressing
that all action paths are SERVER paths
* examples/services.rs: version query + verbose backup + restore
tests (src/tests/services.rs, native + remote only):
* server_version returns a plausible version string
* backup/restore round trip: known table content -> verbose backup
(asserts the log actually streams) -> restore under a new name ->
content verified in the restored copy
* restore without replace over an existing database fails
(isc_spb_res_create semantics)
All three tests pass against Firebird 6.0 (LI-T6.0.0.2076); the full
suite shows no regressions (the five failures present on master
against Firebird 6 - boolean/execute_procedure/nowait/server_engine -
are unchanged).
The first version of this change added a second, live copy of isc_service_attach/detach/query/start near the top of parse_functions! while the original declarations stayed commented out further down. Uncomment the existing ones instead, so the diff is only the removal of the comment markers. parse_functions! maps each extern "C" block to a trait method plus its linking/dyn_loading impls, so the position inside the macro invocation makes no difference. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Verification after d7ed9cd (the in-place uncomment)Re-ran everything on a clean toolchain (rustup stable 1.97.1, x86_64-unknown-linux-gnu) against Firebird 6 on Build / format
Tests —
Identical failure set on both, so no regressions — all five are pre-existing FB6 incompatibilities: The three added tests are the whole of the +3: Example — Unrelated pre-existing issue spotted while doing this: |
This implements the missing Services API for the native client — the gap we hit hardest while porting 43 Firebird architecture-paper samples to rsfbclient (context): the backup sample had to shell out to
gbak, and the trace sample was the only twin across five language families that could not run its demonstration at all.Per CONTRIBUTING this is API-sized, so treat the PR as a concrete proposal — happy to reshape the API, split it, or move parts behind discussion in an issue if you prefer that flow.
What it adds
rsfbclient-nativeisc_service_attach/isc_service_start/isc_service_query/isc_service_detachbindings that were already present (commented out) inibase.rs.servicesmodule withNativeServiceManager<T: LinkageMarker>: a thin safe wrapper owning the service handle — per-linkage constructors (attach_dyn_link/attach_dyn_load),start/query/detach, detach-on-drop.rsfbclient(behind the existingnative_clientfeature)services::ServiceManagerwith a small builder (host/port/user/pass, optionalwith_dyn_load(path); runtime dispatch between linkages likeSimpleConnection, to avoid duplicating the connection builders' typestate).server_version(),backup/restorewith typed option structs (SvcBackupOptions: metadata_only, ignore_checksums, ignore_limbo, no_garbage_collect;SvcRestoreOptions: replace, page_size), and*_with_outputvariants that stream the verbosegbaklog line by line while the action runs — the sameisc_info_svc_linepolling loopgbak -seuses.pure_rustcannot reach the service manager (its wire implementation doesn't carry the service opcodes).examples/services.rsin the standard example shape.Tests
src/tests/services.rs(native + remote only, plain feature-gated rather thanmk_tests_default!since there is no per-backend matrix for services):server_versionreturns a plausible version string.backup_restore_roundtrip: creates a database with known rows, runs a verbose backup (asserting the log actually streams), restores under a new name, and verifies the rows in the restored copy, then drops it.restore_without_replace_fails_on_existing: theisc_spb_res_createsafety semantics.Verification
LI-T6.0.0.2076, Linux aarch64,linkingfeature):test result: ok. 3 passed(services filter); the example streams the real gbak log (gbak:readied database ... gbak:creating file ...).cargo test -- --test-threads 1shows the same five failures on this branch as on clean master against Firebird 6 (boolean×2,execute_procedure,select_readcommited_with_nowait,server_engine— all pre-existing FB6 incompatibilities, unrelated to this change), with my three tests added to the passing set (85 → 88 passed).cargo fmt --all -- --checkpasses;cargo build --examplesclean.Possible follow-ups (not in this PR to keep it reviewable)
The same
NativeServiceManagerprimitive can carry the rest of the service family — trace sessions (isc_action_svc_trace_start/stop), nbackup, database properties (sweep interval, shutdown), user management, and validation/sweep — each is just another SPB layout overstart+drain_output.🤖 Generated with Claude Code