diff --git a/docs-src/PLAN.md b/docs-src/PLAN.md index 8e3177c05..3e4c0a161 100644 --- a/docs-src/PLAN.md +++ b/docs-src/PLAN.md @@ -116,14 +116,54 @@ the site (and can attach to GitHub releases). ## Execution phases -1. **Scaffold**: `docs-src/` skeleton, `site.toml` (version from `dist/RELEASE`), - templates, `build.py` (HTML first), one hand-migrated sample page end-to-end. -2. **Extractor**: `extract.py` on the API-reference C tree; diff-verify; iterate - the cleanup until content matches. Then C++/STL, then the guides. -3. **Man pages**: per-API `*.3` + the `libdb.3` overview; `mandoc -Tlint` clean. -4. **PDF**: pandoc per book (programmer_reference, the GSGs, api_reference). -5. **CI**: `docs.yml` with all validators + the completeness gate. -6. **Publish**: wire gh-pages to the generated HTML; update the landing page. +1. **Scaffold** (DONE, PR #119): `docs-src/` skeleton, `site.toml` (version from + `dist/RELEASE`), templates, `build.py` (HTML first). +2. **Extractor + trees** (DONE): `extract.py` + `verify.py` no-loss gate on the + C API tree (100.00%), then STL (100.00%) and every guide tree. See the + retention table below. `migrate_tree.py` drives chaptered guides (order from + the index TOC, image copy); `fix_xrefs.py` remaps cross-tree links to the new + `docs-src/` layout. +3. **Man pages** (DONE): `build_man()` -> 787 `*.3` (785 C+STL refentry pages + + `libdb.3` overview + utilities), `mandoc -Tlint` = 0 errors. `man_coverage.py` + reports API coverage (measure-only; the CI gate is phase 5). +4. **PDF** (TODO): pandoc per book (programmer_reference, the GSGs, api_reference) + with a shared LaTeX header. `build.py build_pdf()` is the stubbed seam. +5. **CI** (TODO): `docs.yml` with all validators + the completeness gate (wire + `verify.py` per tree + `man_coverage.py` as hard gates). +6. **Publish** (TODO): wire gh-pages to the generated HTML; update the landing + page. + +### Phase 2 retention (verify.py, mean word retention; 0 hard drops on all) + +| tree | pages | retention | +|-------------------------|-------|-----------| +| api/c | 470 | 100.00% | +| api/stl | 322 | 100.00% | +| guides/programmer_reference | 203 | 99.98% | +| guides/upgrading | 180 | 100.00% | +| guides/installation | 101 | 99.99% | +| guides/porting | 16 | 100.00% | +| guides/gsg (C) | 37 | 100.00% | +| guides/gsg_txn (C) | 38 | 100.00% | +| guides/gsg_db_rep (C) | 26 | 100.00% | +| guides/collections | 37 | 99.98% | +| guides/bdb-sql | 30 | 100.00% | +| guides/articles | 2 | 100.00% | + +### Deferred: docs/csharp (38 MB) and docs/java (12 MB) + +These are LANGUAGE-BINDING docs and are NOT DocBook, so the reverse-DocBook +extractor does not apply: +- **csharp** — a compiled Sandcastle/MS-Help-Viewer tree (`.chm` + `.aspx` + + JS/PNG, 2457 files, only 1 real `.html`). Would need a bespoke extractor. +- **java** — standard Javadoc HTML (525 files: allclasses-frame, package-frame, + index-all). Different structure; the `refentry`/`chapter` isolation is moot. + +Both are enormous and lower-value for the core C engine. Deferred to a future +phase (regenerate from the C#/Java sources with their native doc tools, or write +a per-format extractor) rather than sink budget reverse-engineering rendered +help output. The gsg/gsg_txn/gsg_db_rep CXX/JAVA sub-variants are likewise +deferred; the C variants are migrated. ## Non-negotiables diff --git a/docs-src/_data/site.toml b/docs-src/_data/site.toml index 3b19b312f..aea64a736 100644 --- a/docs-src/_data/site.toml +++ b/docs-src/_data/site.toml @@ -8,3 +8,7 @@ short_name = "libdb" base_url = "https://libdb.org/docs/" copyright = "Copyright (c) 1990, 2013 Oracle and/or its affiliates. All rights reserved." tagline = "The Berkeley DB reference documentation" +# Man-page .TH date field (the DocBook source is dated 9/9/2013). Use the +# `Month D, YYYY` form so mandoc parses it (hyphenated ISO gets roff-escaped by +# pandoc into `2013\-09\-09`, which mandoc then can't read). Single source. +man_date = "September 9, 2013" diff --git a/docs-src/_migrate/extract.py b/docs-src/_migrate/extract.py index 7d32e518f..f83f9e9b5 100644 --- a/docs-src/_migrate/extract.py +++ b/docs-src/_migrate/extract.py @@ -20,6 +20,14 @@ Usage: extract.py [SRC_HTML_DIR] [OUT_MD_DIR] Defaults: docs/api_reference/C -> docs-src/api/c Requires: pandoc on PATH (run under `nix shell nixpkgs#pandoc`). + +Works for both the flat `refentry` API trees (C, STL) and the chaptered +`chapter`/`sect1` guide trees (programmer_reference, gsg, ...): every page has a +single top-level content div in CONTENT_CLASSES. A few auxiliary guide pages +(embedded.html, witold.html) put prose straight under
with no content +div — for those a body-level fallback captures everything except the stable +boilerplate divs. The C API tree never hits the fallback (its only div-less +pages are frameset stubs with no prose), so it is regression-safe. """ import html.parser import re @@ -30,6 +38,11 @@ REPO = Path(__file__).resolve().parents[2] SRC = Path(sys.argv[1]) if len(sys.argv) > 1 else REPO / "docs/api_reference/C" OUT = Path(sys.argv[2]) if len(sys.argv) > 2 else REPO / "docs-src/api/c" +# source: path shown in front-matter; derived from SRC relative to the repo. +try: + SRC_REL = str(SRC.resolve().relative_to(REPO)) +except ValueError: + SRC_REL = str(SRC) # DocBook classes whose top-level| Access Method | +Description | +
|---|---|
| BTree | +Data is stored in a sorted, balanced tree structure. Both the key and the data for BTree records can be arbitrarily complex. That is, they can contain single values such as an integer or a string, or complex types such as a structure. Also, although not the default behavior, it is possible for two records to use keys that compare as equals. When this occurs, the records are considered to be duplicates of one another. |
+
| Hash | +Data is stored in an extended linear hash table. Like BTree, the key and the data used for Hash records can be of arbitrarily complex data. Also, like BTree, duplicate records are optionally supported. |
+
| Queue | +Data is stored in a queue as fixed-length records. Each record uses a logical record number as its key. This access method is designed for fast inserts at the tail of the queue, and it has a special operation that deletes and returns a record from the head of the queue. +This access method is unusual in that it provides record level locking. This can provide beneficial performance improvements in applications requiring concurrent access to the queue. |
+
| Recno | +Data is stored in either fixed or variable-length records. Like Queue, Recno records use logical record numbers as keys. |
+
DB_CREATE flag on the `open()` method.
+
+The following code fragment illustrates a database open:
+
+``` c
+#include | Flag | +Description | +
|---|---|
DB_REP_MASTER |
+The application starts up and declares the environment to be a master without calling for an election. It is an error for more than one environment to start up using this flag, or for an environment to use this flag when a master already exists. +Note that no replication group should ever operate with more than one master. +In the event that a environment attempts to become a master when a master already exists, the replication code will resolve the problem by holding an election. Note, however, that there is always a possibility of data loss in the face of duplicate masters, because once a master is selected, the environment that loses the election will have to roll back any transactions committed until it is in sync with the "real" master. |
+
DB_REP_CLIENT |
+The application starts up and declares the environment to be a replica without calling for an election. Note that the environment can still become a master if a subsequent application starts up, calls for an election, and this environment is elected master. |
+
DB_REP_ELECTION |
+As described above, the application starts up, looks for a master, and if one is not found calls for an election. |
+
| File Type | +To Override | +
|---|---|
| database files | +You can cause database files to be created in a directory other than the environment home by using the This method modifies the directory used for database files created and managed by a single environment handle; it does not configure the entire environment. This method may not be called after the environment has been opened. +You can also set a default data location that is used by the entire environment by using the |
+
| Log files | +You can cause log files to be created in a directory other than the environment home directory by using the This method modifies the directory used for database files created and managed by a single environment handle; it does not configure the entire environment. This method may not be called after the environment has been opened. +You can also set a default log file location that is used by the entire environment by using the |
+
| Temporary files | +You can cause temporary files required by the environment to be created in a directory other than the environment home directory by using the You can also set a temporary file location by using the |
+
| Metadata files | +You can cause persistent metadata files required by the replicated applications to be created in a directory other than the environment home directory by using the You can also set a metadata directory location by using the |
+
| Region files | +If backed by the filesystem, region files are always placed in the environment home directory. | +
| Degree | +ANSI Term | +Definition | +
|---|---|---|
| 1 | +READ UNCOMMITTED | +Uncommitted reads means that one transaction will never overwrite another transaction's dirty data. Dirty data is data that a transaction has modified but not yet committed to the underlying data store. However, uncommitted reads allows a transaction to see data dirtied by another transaction. In addition, a transaction may read data dirtied by another transaction, but which subsequently is aborted by that other transaction. In this latter case, the reading transaction may be reading data that never really existed in the database. | +
| 2 | +READ COMMITTED | +Committed read isolation means that degree 1 is observed, except that dirty data is never read. +In addition, this isolation level guarantees that data will never change so long as it is addressed by the cursor, but the data may change before the reading cursor is closed. In the case of a transaction, data at the current cursor position will not change, but once the cursor moves, the previous referenced data can change. This means that readers release read locks before the cursor is closed, and therefore, before the transaction completes. Note that this level of isolation causes the cursor to operate in exactly the same way as it does in the absence of a transaction. |
+
| 3 | +SERIALIZABLE | +Committed read is observed, plus the data read by a transaction, T, will never be dirtied by another transaction before T completes. This means that both read and write locks are not released until the transaction completes. +In addition, no transactions will see phantoms. Phantoms are records returned as a result of a search, but which were not seen by the same transaction when the identical search criteria was previously used. +This is DB's default isolation guarantee. |
+
db_deadlock reference documentation.
+
+### Resolving Deadlocks
+
+When DB determines that a deadlock has occurred, it will select a thread of control to resolve the deadlock and then return `DB_LOCK_DEADLOCK` to that thread. If a deadlock is detected, the thread must:
+
+1. Cease all read and write operations.
+
+2. Close all open cursors.
+
+3. Abort the transaction.
+
+4. Optionally retry the operation. If your application retries deadlocked operations, the new attempt must be made using a new transaction.
+
+### Note
+
+If a thread has deadlocked, it may not make any additional database calls using the handle that has deadlocked.
+
+For example:
+
+``` c
+retry:
+ ret = envp->txn_begin(envp, NULL, &txn, 0);
+ if (ret != 0) {
+ envp->err(envp, ret, "txn_begin failed");
+ return (EXIT_FAILURE);
+ }
+ ...
+ /* key and data are Dbts. Their usage is omitted for brevity. */
+ ...
+ switch (ret = dbp->put(dbp, txn, &key, &data, 0)) {
+ case 0:
+ break;
+ /* Deadlock handling goes here */
+ case DB_LOCK_DEADLOCK:
+ /* Abort the transaction */
+ (void)txn->abort(txn);
+
+ /*
+ * retry_count is a counter used to identify how many times
+ * we've retried this operation. To avoid the potential for
+ * endless looping, we won't retry more than
+ * MAX_DEADLOCK_RETRIES times.
+ */
+ if (retry_count < MAX_DEADLOCK_RETRIES) {
+ printf("Got DB_LOCK_DEADLOCK.\n");
+ printf("Retrying write operation.\n");
+ retry_count++;
+ goto retry;
+ }
+ printf("Got DB_LOCK_DEADLOCK and out of retries.");
+ printf("Giving up.\n");
+ return (EXIT_FAILURE);
+ default:
+ /* If some random database error occurs, we just give up */
+ envp->err(envp, ret, "db put failed");
+ ret = txn->abort(txn);
+ if (ret != 0) {
+ envp->err(envp, ret, "txn abort failed");
+ return (EXIT_FAILURE);
+ }
+ }
+ /* If all goes well, commit the transaction */
+ ret = txn->commit(txn, 0);
+ if (ret != 0) {
+ envp->err(envp, ret, "txn commit failed");
+ return (EXIT_FAILURE);
+ }
+
+ return (EXIT_SUCCESS);
+```
+
+### Setting Transaction Priorities
+
+Normally when a thread of control must be selected to resolve a deadlock, DB decides which thread will perform the resolution; you have no way of knowing in advance which thread will be selected to resolve the deadlock.
+
+However, there may be situations where you know it is better for one thread to resolve a deadlock over another thread. As an example, if you have a background thread running data management activities, and another thread responding to user requests, you might want deadlock resolution to occur in the background thread because you can better afford the throughput costs there. Under these circumstances, you can identify which thread of control will be selected for resolved deadlocks by setting a transaction priorities.
+
+When two transactions are deadlocked, DB will abort the transaction with the lowest priority. By default, every transaction is given a priority of 100. However, you can set a different priority on a transaction-by-transaction basis by using the `DB_TXN->set_priority()` method.
+
+When two or more transactions are tied for the lowest priority, the tie is broken based on the policy provided to the `DB_ENV->lock_detect()` method's `atype` parameter.
+
+A transaction's priority can be changed at any time after the transaction handle has been created and before the transaction has been resolved (committed or aborted). For example:
+
+``` c
+#include POSIX Functions |
+Internal Function Name |
+Source File |
+
|---|---|---|
abort() is required if diagnostic build is used or if snprintf is not provided by the platform |
+__os_abort() |
+os_abort.c |
+
freeaddrinfo() +getaddrinfo(), htonl(), htons(), inet_addr(), and gethostbyname() are required for Replication Manager |
+__os_getaddrinfo(), __os_freeaddrinfo() |
+os_addrinfo.c | +
malloc(), realloc(), strdup(), free(), memcpy(), memset(), strlen() |
+__os_umalloc(), __os_urealloc(), __os_ufree(), __os_strdup(), __os_calloc(), __os_malloc(), __os_realloc(), __os_free(), __os_guard(), __ua_memcpy() | +os_alloc.c |
+
clock_gettime(), time(), gettimeofday() |
+__os_gettime() |
+os_clock.c |
+
sysconf() |
+__os_cpu_count() |
+os_cpu.c |
+
ctime(), ctime_r() |
+__os_ctime() |
+os_ctime.c |
+
opendir(), closdir(), readdir(), stat() |
+__os_dirlist(), __os_dirfree() |
+os_dir.c |
+
strncpy() |
+__os_get_errno_ret_zero(), __os_get_errno(), __os_get_syserr(), __os_set_errno(), __os_strerror(), __os_posix_err() |
+os_errno.c |
+
fcntl() is required for DB_REGISTER |
+__os_fdlock() |
+os_flock.c |
+
fsync(), fdatasync() |
+__vx_fsync(), __os_fsync() |
+os_fsync.c |
+
getenv() and strcpy() are required when environment variables are used to configure the database |
+__os_getenv() |
+os_getenv.c |
+
close(), open() |
+__os_openhandle(), __os_closehandle() |
+os_handle.c |
+
getpid() +pthread_self() is required for replication and failchk functionality |
+__os_id() |
+os_pid.c |
+
shmget(), shmdt(), shmctl(), and shmat() are required when envrionment uses share memory for regions +munmap() is required when envrionment uses memory mapped files for regions or read-only databases +munlock() is required when environment is configured with DB_LOCKDOWN |
+__os_attach(), __os_detach(), __os_mapfile(), __os_unmapfile(), __os_map(), __shm_mode(), __no_system_mem() |
+os_map.c |
+
mkdir(), chmod() |
+__os_mkdir() |
+os_mkdir.c |
+
fchmod() +directio() is required when explicitly enabling DIRECTIO_ON |
+__os_open() |
+os_open.c |
+
rename() |
+__os_rename() |
+os_rename.c |
+
getuid() is required when environment variables are used to configure the database |
+__os_isroot() |
+os_root.c |
+
read(), write(), pread(), pwrite() |
+__os_io(), __os_read(), __os_write(), __os_physwrite() |
+os_rw.c |
+
lseek() |
+__os_seek() |
+os_seek.c |
+
stat(), fstat() |
+__os_exists(), __os_ioinfo() |
+os_stat.c |
+
ftruncate() is required when using truncate |
+__os_truncate() |
+os_truncate.c |
+
unlink() |
+__os_unlink() |
+os_unlink.c |
+
yield(), sched_yield() |
+__os_yield(), __os_sleep() |
+os.yield.c |
+