Dump the active slots in the reader table.
* @return < 0 if a < b, 0 if a == b, > 0 if a > b
*/
int mdb_dcmp(MDB_txn *txn, MDB_dbi dbi, const MDB_val *a, const MDB_val *b);
+
+ /** @brief A callback function used to print a message from the library.
+ *
+ * @param[in] msg The string to be printed.
+ * @param[in] ctx An arbitrary context pointer for the callback.
+ * @return < 0 on failure, 0 on success.
+ */
+typedef int (MDB_msg_func)(const char *msg, void *ctx);
+
+ /** @brief Dump the entries in the reader lock table.
+ *
+ * @param[in] env An environment handle returned by #mdb_env_create()
+ * @param[in] func A #MDB_msg_func function
+ * @param[in] ctx Anything the message function needs
+ * @return < 0 on failure, 0 on success.
+ */
+int mdb_reader_list(MDB_env *env, MDB_msg_func *func, void *ctx);
/** @} */
#ifdef __cplusplus
return MDB_SUCCESS;
}
+int mdb_reader_list(MDB_env *env, MDB_msg_func *func, void *ctx)
+{
+ unsigned int i, rdrs;
+ MDB_reader *mr;
+ char buf[128];
+ int first = 1;
+
+ if (!env || !func)
+ return -1;
+ if (!env->me_txns) {
+ return func("No reader locks\n", ctx);
+ }
+ rdrs = env->me_numreaders;
+ mr = env->me_txns->mti_readers;
+ for (i=0; i<rdrs; i++) {
+ if (mr[i].mr_pid) {
+ size_t tid;
+ int rc;
+ tid = mr[i].mr_tid;
+ if (mr[i].mr_txnid == (txnid_t)-1) {
+ sprintf(buf, "%10d %zx -\n", mr[i].mr_pid, tid);
+ } else {
+ sprintf(buf, "%10d %zx %zu\n", mr[i].mr_pid, tid, mr[i].mr_txnid);
+ }
+ if (first) {
+ first = 0;
+ func(" pid thread txnid\n", ctx);
+ }
+ rc = func(buf, ctx);
+ if (rc < 0)
+ return rc;
+ }
+ }
+ return 0;
+}
/** @} */
[\c
.BR \-n ]
[\c
+.BR \-r ]
+[\c
.BR \-a \ |
.BI \-s \ subdb\fR]
.SH DESCRIPTION
.BR \-n
Display the status of an LMDB database which does not use subdirectories.
.TP
+.BR \-r
+Display information about the environment reader table.
+Shows the process ID, thread ID, and transaction ID for each active
+reader slot. The process ID and transaction ID are in decimal, the
+thread ID is in hexadecimal. The transaction ID is displayed as "-"
+if the reader does not currently have a read transaction open.
+.TP
.BR \-a
Display the status of all of the subdatabases in the environment.
.TP
static void usage(char *prog)
{
- fprintf(stderr, "usage: %s dbpath [-e] [-f[f[f]]] [-n] [-a|-s subdb]\n", prog);
+ fprintf(stderr, "usage: %s dbpath [-e] [-f[f[f]]] [-n] [-a|-s subdb] [-r]\n", prog);
exit(EXIT_FAILURE);
}
char *prog = argv[0];
char *envname;
char *subname = NULL;
- int alldbs = 0, envinfo = 0, envflags = 0, freinfo = 0;
+ int alldbs = 0, envinfo = 0, envflags = 0, freinfo = 0, rdrinfo = 0;
if (argc < 2) {
usage(prog);
* -n: use NOSUBDIR flag on env_open
* (default) print stat of only the main DB
*/
- while ((i = getopt(argc, argv, "aefns:")) != EOF) {
+ while ((i = getopt(argc, argv, "aefnrs:")) != EOF) {
switch(i) {
case 'a':
if (subname)
case 'n':
envflags |= MDB_NOSUBDIR;
break;
+ case 'r':
+ rdrinfo++;
+ break;
case 's':
if (alldbs)
usage(prog);
printf(" Number of readers used: %u\n", mei.me_numreaders);
}
+ if (rdrinfo) {
+ printf("Reader Table Status\n");
+ rc = mdb_reader_list(env, (MDB_msg_func *)fputs, stdout);
+ }
+
if (freinfo) {
MDB_cursor *cursor;
MDB_val key, data;