Migrating from ADS
OpenADS is an open-source, ADS-compatible engine for applications built against
the Advantage Database Server (ADS) and the Advantage Client Engine (ACE) API.
If your data is DBF/ADT with CDX/NTX/ADI indexes and your app uses rddads,
the ACE C API, X#’s AXDBFCDX, or the PHP advantage extension, you can move
without rewriting it. This guide maps each piece of an Advantage install to its
OpenADS counterpart.
Concept map
| Advantage | OpenADS | Notes |
|---|---|---|
| Advantage Database Server (service) | openads_serverd |
TCP server; installs as a Windows Service / Linux systemd / macOS launchd. |
| Advantage Local Server | the engine DLL itself | ace64.dll runs the engine in-process; no separate adsloc DLL. |
ace32.dll / ace64.dll (client) |
ace64.dll / ace32.dll (drop-in) |
Same name, same C ABI. Also shipped as openace64.dll for side-by-side installs. |
| Advantage Data Architect (ARC) | Studio web console | Browser UI: tables, SQL, structure, data dictionary. Launch with openads-studio.bat/.sh. |
ads.cfg / server settings |
openads.ini |
Written by openads_serverd --setup, read with --config. |
Data dictionary .add / .ai |
same .add / .ai |
Opened and managed natively. |
Connection path \\srv\vol\data |
tcp://srv:6262/data |
Remote URI; local stays a filesystem path. |
| Default TCP port 6262 | 6262 | Identical, so keep it — unless ADS still runs on the same host (see below). |
Server side — install like the old setup did
The old ADS installer asked for a port, a data folder, a code page and whether to start as a service. OpenADS does the same through a console wizard:
openads_serverd --setup
It writes an openads.ini and, if you ask it to, registers the auto-start
service for your platform. Run it later straight from that file:
openads_serverd --config openads.ini
Running OpenADS and ADS on the same machine? Both default to TCP 6262. Either stop the Advantage service first, or give OpenADS another port (
port = 6263in the ini, or--port 6263). The server prints a clear hint if the bind clashes.
Code page. OpenADS serves UTF-8 / CP437 today; a selectable server code page (CP850, Windows-1252) is on the roadmap. If your DBFs are CP850, test a copy before going live.
Rollback to SAP ACE is not automatic. OpenADS writes CDX files in Harbour’s DBFCDX-compatible format (magic
RCHBat offset 0x14 in the structure-tag header). SAP ACE does not recognize this layout and returns error 7017 (Corrupt .ADI, .CDX, or .IDX index) on any table whose CDX has been touched by OpenADS. OpenADS reads SAP-built CDX files fine as long as you do not write through OpenADS.If you may need SAP ACE again later (rollback, mixed environment, or side-by-side benchmarking), either keep the original SAP-built
.cdxfiles backed up before pointing the app at OpenADS, or, after rolling back to SAP, delete the OpenADS-written.cdxfiles and rebuild all tags under SAP. NTX and ADI indexes follow the same one-way rule once OpenADS has written them.
Client side — point your app at OpenADS
You do not relink for the common case:
- Put
ace64.dll(32-bit app →ace32.dll) next to your.exe, or on thePATHahead of any existing copy. - Run the app.
rddads/ FiveWin / xBase++ binaries that load Advantage by the canonical name now use OpenADS unchanged.
If you link a fresh build, use the import lib for your compiler under lib/
(MSVC, MinGW, Borland). Ordinal-linked legacy binaries: see
ordinal-compat.md. RDD specifics:
rddads-compat.md.
Remote connections use a URI in place of a UNC path:
AdsConnect60("tcp://dbhost:6262/apps/sales/sales.add",
user, pass, ADS_REMOTE_SERVER, &hConn);
Legacy absolute paths (legacy_paths)
ERP apps that open tables by absolute local path — USE "E:\CLIENT\FILE.DBF"
in Harbour/xHarbour, or full paths from X#/xBase++ — can run unchanged
against a single server instance. Start the server with the legacy resolver:
openads_serverd --data E:\ --legacy-paths --port 6262
# or in openads.ini: legacy_paths = 1
With legacy_paths on, every client-supplied path (tables, indexes, memos,
the connect dir itself, and remote file functions) is resolved against the
--data roots case-insensitively and ignoring the drive letter:
- A path that starts with a data root is stripped and re-joined under that
root:
C:/TEMP/Sub/t.dbfwith--data C:\tempservesC:\temp\Sub\t.dbf. - Any other absolute path loses its drive letter and is joined under the
root:
E:\CREATIVE.RAM\C0000001\B5643DS1.dbfserves<root>\CREATIVE.RAM\C0000001\B5643DS1.dbf— so several client folders on the same disk are all served by one root, and the same app binary still runs against local DBFCDX.
Whole-filesystem access on a Windows server: list the drive roots,
--data "C:\;D:\;E:\" (ini: data = C:\;D:\;E:\). A drive-root entry
routes by its drive letter — E:\... lands under the E: root, D:\...
under D: — and files that exist are always opened verbatim first, so a
server with the same drive layout as the clients needs no folding at all.
When the data root itself is not writable (a drive root for a
non-elevated server process), connections still succeed — only
transaction journaling is disabled (a notice is logged); tables in
writable subfolders work normally. Point the error log at a
writable folder separately (error_log_path / --error-log-path);
it is not the same as the tx journal. Details:
Error log and journal paths.
Default is off (strict SAP-compatible resolution). This works for Windows clients against Windows, Linux, or macOS servers.
Client-side guard: OPENADS_REMOTE_ONLY_ACCESS
The mirror image of legacy_paths, on the client. In a remote-only
deployment a table opened by local path through ace64.dll/ace32.dll
means the app bypassed the server — usually a misconfiguration that
silently reads/writes a file next to the app instead of the shared data.
Set this on the client process to turn that silent drift into an error:
set OPENADS_REMOTE_ONLY_ACCESS=1
rem or, in an openads.ini next to ace64.dll/ace32.dll (or in the app
rem working directory, or pointed to by OPENADS_INI):
rem remote_only_access = 1
The environment variable wins over the ini key. The same dual
env/ini mechanism covers the other client settings —
resolve_verbose, log, log_file, trace, wire_trace,
arc_trace, tls_insecure, adi_v2, adt_cdx_index (see
openads.ini.sample).
With it on, any AdsOpenTable / AdsCreateTable that would hit the
local filesystem (in-process ADS_LOCAL_SERVER connection) fails
with AE_ACCESS_DENIED — rddads surfaces it as a Harbour runtime
error, so the offending USE is caught immediately instead of writing
a stray local .dbf. Remote (tcp:///tls://) and SQL-backend
(sqlite://, postgresql://, …) connections are unaffected, and so is
any local I/O done through another RDD (e.g. DBFCDX), which never goes
through this DLL.
Start with log mode. Deny mode raises the RTE wherever the first
local open happens — if your app’s error handler itself opens tables
via ADSCDX, the RTE inside the handler recurses and Harbour kills the
process (“recursive call” error). Set remote_only_access = log
(or 2) instead: every local open/create is written to the audit log
as a LOCALACCESS="OPEN|CREATE|OPENIDX" ASKED="..." VIA=LOCAL line (console,
or log_file / OPENADS_LOG_FILE) and allowed to proceed, so you get
the full inventory of offending paths in one run. Switch to 1 once
they are fixed.
Other clients: the PHP extension mirrors the old php_advantage API
(bindings/php_ext/), and a portable FFI binding is in bindings/php/.
Administering data — use Studio instead of ARC
Run openads-studio.bat (Windows) or ./openads-studio.sh (Linux/macOS) from
the release folder, or, on a running server, start it with
--http-port 6263 and open http://SERVER:6263/. Studio covers what you did in
ARC: browse and edit rows, run SQL, view/rebuild structure (reindex, pack, zap),
and create/edit data-dictionary objects (tables, users, indexes, RI rules).
Secure it with --http-user user:password; for public exposure put a TLS proxy
in front (see tls-deployment.md).
Checklist
- Install the server:
openads_serverd --setup→openads.ini. - Resolve the 6262 port if ADS still runs on the host.
- Drop
ace64.dll/ace32.dllnext to your app (or relink withlib/). - Back up SAP-built
.cdxfiles if you may need to roll back to SAP ACE. - Smoke-test reads/writes/index seeks against a copy of the data.
- App opens tables by absolute local path (
USE "E:\CLIENT\FILE.DBF")? Enablelegacy_paths = 1(see above) — no source changes needed. - Verify accented text (code-page caveat above).
- Use Studio (
openads-studio) for day-to-day admin. - Set up auto-start (wizard, or
service-deployment.md).
Advantage Database Server, the Advantage Client Engine and Advantage Data Architect are names of their respective owners, used here only to describe compatibility. OpenADS is an independent project and is not affiliated with or endorsed by them.