<commit_before>/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
/*
COPYING CONDITIONS NOTICE:

  This program is free software; you can redistribute it and/or modify
  it under the terms of version 2 of the GNU General Public License as
  published by the Free Software Foundation, and provided that the
  following conditions are met:

      * Redistributions of source code must retain this COPYING
        CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
        DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
        PATENT MARKING NOTICE (below), and the PATENT RIGHTS
        GRANT (below).

      * Redistributions in binary form must reproduce this COPYING
        CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
        DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
        PATENT MARKING NOTICE (below), and the PATENT RIGHTS
        GRANT (below) in the documentation and/or other materials
        provided with the distribution.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  02110-1301, USA.

COPYRIGHT NOTICE:

  TokuFT, Tokutek Fractal Tree Indexing Library.
  Copyright (C) 2007-2013 Tokutek, Inc.

DISCLAIMER:

  This program is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  General Public License for more details.

UNIVERSITY PATENT NOTICE:

  The technology is licensed by the Massachusetts Institute of
  Technology, Rutgers State University of New Jersey, and the Research
  Foundation of State University of New York at Stony Brook under
  United States of America Serial No. 11/760379 and to the patents
  and/or patent applications resulting from it.

PATENT MARKING NOTICE:

  This software is covered by US Patent No. 8,185,551.
  This software is covered by US Patent No. 8,489,638.

PATENT RIGHTS GRANT:

  "THIS IMPLEMENTATION" means the copyrightable works distributed by
  Tokutek as part of the Fractal Tree project.

  "PATENT CLAIMS" means the claims of patents that are owned or
  licensable by Tokutek, both currently or in the future; and that in
  the absence of this license would be infringed by THIS
  IMPLEMENTATION or by using or running THIS IMPLEMENTATION.

  "PATENT CHALLENGE" shall mean a challenge to the validity,
  patentability, enforceability and/or non-infringement of any of the
  PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.

  Tokutek hereby grants to you, for the term and geographical scope of
  the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
  irrevocable (except as stated in this section) patent license to
  make, have made, use, offer to sell, sell, import, transfer, and
  otherwise run, modify, and propagate the contents of THIS
  IMPLEMENTATION, where such license applies only to the PATENT
  CLAIMS.  This grant does not include claims that would be infringed
  only as a consequence of further modifications of THIS
  IMPLEMENTATION.  If you or your agent or licensee institute or order
  or agree to the institution of patent litigation against any entity
  (including a cross-claim or counterclaim in a lawsuit) alleging that
  THIS IMPLEMENTATION constitutes direct or contributory patent
  infringement, or inducement of patent infringement, then any rights
  granted to you under this License shall terminate as of the date
  such litigation is filed.  If you or your agent or exclusive
  licensee institute or order or agree to the institution of a PATENT
  CHALLENGE, then Tokutek may terminate any rights granted to you
  under this License.
*/

#ident "Copyright (c) 2007-2013 Tokutek Inc.  All rights reserved."
#ident "$Id$"
/* LICENSE:  This file is licensed under the GPL or from Tokutek. */

/* Make a db.h that will be link-time compatible with Sleepycat's Berkeley DB. */


#include <stdio.h>
#include <stdlib.h>
// Don't include toku_assert.h.   Just use assert.h
#include <assert.h>
#include <string.h>
#include <sys/types.h>

#define VISIBLE "__attribute__((__visibility__(\"default\")))"

#define FIELD_LIMIT 100
struct fieldinfo {
    const char *decl_format_string;
    const char *name;
    size_t offset;
} fields[FIELD_LIMIT];
static int field_counter=0;

static int compare_fields (const void *av, const void *bv) {
    const struct fieldinfo *a = (const struct fieldinfo *) av;
    const struct fieldinfo *b = (const struct fieldinfo *) bv;
    if (a->offset< b->offset) return -1;
    if (a->offset==b->offset) return  0;
    return +1;
}				      

#define STRUCT_SETUP(typ, fname, fstring) ({            \
    assert(field_counter<FIELD_LIMIT);                  \
    fields[field_counter].decl_format_string = fstring; \
    fields[field_counter].name               = #fname;  \
    fields[field_counter].offset             = __builtin_offsetof(typ, fname); \
    field_counter++; })

static void sort_and_dump_fields (const char *structname, bool has_internal, const char *extra_decls[]) {
    int i;
    qsort(fields, field_counter, sizeof(fields[0]), compare_fields);
    printf("struct __toku_%s {\n", structname);
    if (has_internal) {
	printf("  struct __toku_%s_internal *i;\n", structname);
	printf("#define %s_struct_i(x) ((x)->i)\n", structname);
    }
    if (extra_decls) {
	while (*extra_decls) {
	    printf("  %s;\n", *extra_decls);
	    extra_decls++;
	}
    }
    for (i=0; i<field_counter; i++) {
	printf("  ");
	printf(fields[i].decl_format_string, fields[i].name);
	printf(";\n");
    }
    printf("};\n");
}

#include "db-4.6.19.h"

static void print_dbtype(void) {
    /* DBTYPE is mentioned by db_open.html */
    printf("typedef enum {\n");
    printf(" DB_BTREE=%d,\n", DB_BTREE);
    printf(" DB_UNKNOWN=%d\n", DB_UNKNOWN);
    printf("} DBTYPE;\n");
}


#define dodefine(name) printf("#define %s %d\n", #name, name)
#define dodefine_track(flags, name) ({ assert((flags & name) != name);	\
                                       flags |= (name);                \
                                       printf("#define %s %d\n", #name, name); })
#define dodefine_from_track(flags, name) ({\
    uint32_t which;                        \
    uint32_t bit;                          \
    for (which = 0; which < 32; which++) { \
        bit = 1U << which;                 \
        if (!(flags & bit)) break;         \
    }                                      \
    assert(which < 32);                    \
    printf("#define %s %u\n", #name, bit); \
    flags |= bit;                          \
    })

#define dodefine_track_enum(flags, name) ({ assert(name>=0 && name<256); \
                                            assert(!(flags[name])); \
                                            flags[name] = 1;        \
                                            printf("#define %s %d\n", #name, (int)(name)); })
#define dodefine_from_track_enum(flags, name) ({\
    uint32_t which;                             \
    /* don't use 0 */                           \
    for (which = 1; which < 256; which++) {     \
        if (!(flags[which])) break;             \
    }                                           \
    assert(which < 256);                        \
    flags[which] = 1;                           \
    printf("#define %s %u\n", #name, which);    \
    })

enum {
        TOKUDB_OUT_OF_LOCKS            = -100000,
        TOKUDB_SUCCEEDED_EARLY         = -100001,
        TOKUDB_FOUND_BUT_REJECTED      = -100002,
        TOKUDB_USER_CALLBACK_ERROR     = -100003,
        TOKUDB_DICTIONARY_TOO_OLD      = -100004,
        TOKUDB_DICTIONARY_TOO_NEW      = -100005,
        TOKUDB_DICTIONARY_NO_HEADER    = -100006,
        TOKUDB_CANCELED                = -100007,
        TOKUDB_NO_DATA                 = -100008,
        TOKUDB_ACCEPT                  = -100009,
        TOKUDB_MVCC_DICTIONARY_TOO_NEW = -100010,
        TOKUDB_UPGRADE_FAILURE         = -100011,
        TOKUDB_TRY_AGAIN               = -100012,
        TOKUDB_NEEDS_REPAIR            = -100013,
        TOKUDB_CURSOR_CONTINUE         = -100014,
        TOKUDB_BAD_CHECKSUM            = -100015,
        TOKUDB_HUGE_PAGES_ENABLED      = -100016,
        TOKUDB_OUT_OF_RANGE            = -100017,
        TOKUDB_INTERRUPTED             = -100018,
        DONTUSE_I_JUST_PUT_THIS_HERE_SO_I_COULD_HAVE_A_COMMA_AFTER_EACH_ITEM
};

static void print_defines (void) {
    dodefine(DB_VERB_DEADLOCK);
    dodefine(DB_VERB_RECOVERY);
    dodefine(DB_VERB_REPLICATION);
    dodefine(DB_VERB_WAITSFOR);

    dodefine(DB_ARCH_ABS);
    dodefine(DB_ARCH_LOG);

    dodefine(DB_CREATE);
    dodefine(DB_CXX_NO_EXCEPTIONS);
    dodefine(DB_EXCL);
    dodefine(DB_PRIVATE);
    dodefine(DB_RDONLY);
    dodefine(DB_RECOVER);
    dodefine(DB_RUNRECOVERY);
    dodefine(DB_THREAD);
    dodefine(DB_TXN_NOSYNC);

    /* according to BDB 4.6.19, this is the next unused flag in the set of
     * common flags plus private flags for DB->open */
#define	DB_BLACKHOLE 0x0080000
    dodefine(DB_BLACKHOLE);
#undef DB_BLACKHOLE

    dodefine(DB_LOCK_DEFAULT);
    dodefine(DB_LOCK_OLDEST);
    dodefine(DB_LOCK_RANDOM);

    //dodefine(DB_DUP);      No longer supported #2862
    //dodefine(DB_DUPSORT);  No longer supported #2862

    dodefine(DB_KEYFIRST);
    dodefine(DB_KEYLAST);
    {
        static uint8_t insert_flags[256];
        dodefine_track_enum(insert_flags, DB_NOOVERWRITE);
        dodefine_track_enum(insert_flags, DB_NODUPDATA);
        dodefine_from_track_enum(insert_flags, DB_NOOVERWRITE_NO_ERROR);
    }
    dodefine(DB_OPFLAGS_MASK);

    dodefine(DB_AUTO_COMMIT);

    dodefine(DB_INIT_LOCK);
    dodefine(DB_INIT_LOG);
    dodefine(DB_INIT_MPOOL);
    dodefine(DB_INIT_TXN);

    //dodefine(DB_KEYEMPTY);      /// KEYEMPTY is no longer used.  We just use DB_NOTFOUND
    dodefine(DB_KEYEXIST);
    dodefine(DB_LOCK_DEADLOCK);
    dodefine(DB_LOCK_NOTGRANTED);
    dodefine(DB_NOTFOUND);
    dodefine(DB_SECONDARY_BAD);
    dodefine(DB_DONOTINDEX);
#ifdef DB_BUFFER_SMALL
    dodefine(DB_BUFFER_SMALL);
#endif
    printf("#define DB_BADFORMAT -30500\n"); // private tokudb
    printf("#define DB_DELETE_ANY %d\n", 1<<16); // private tokudb

    dodefine(DB_FIRST);
    dodefine(DB_LAST);
    dodefine(DB_CURRENT);
    dodefine(DB_NEXT);
    dodefine(DB_PREV);
    dodefine(DB_SET);
    dodefine(DB_SET_RANGE);
    printf("#define DB_CURRENT_BINDING 253\n"); // private tokudb
    printf("#define DB_SET_RANGE_REVERSE 252\n"); // private tokudb
    //printf("#define DB_GET_BOTH_RANGE_REVERSE 251\n"); // private tokudb.  No longer supported #2862.
    dodefine(DB_RMW);
    printf("#define DB_IS_RESETTING_OP 0x01000000\n"); // private tokudb
    printf("#define DB_PRELOCKED 0x00800000\n"); // private tokudb
    printf("#define DB_PRELOCKED_WRITE 0x00400000\n"); // private tokudb
    //printf("#define DB_PRELOCKED_FILE_READ 0x00200000\n"); // private tokudb. No longer supported in #4472
    printf("#define DB_IS_HOT_INDEX 0x00100000\n"); // private tokudb
    printf("#define DBC_DISABLE_PREFETCHING 0x20000000\n"); // private tokudb
    printf("#define DB_UPDATE_CMP_DESCRIPTOR 0x40000000\n"); // private tokudb
    printf("#define TOKUFT_DIRTY_SHUTDOWN %x\n", 1<<31);

    {
        //dbt flags
        uint32_t dbt_flags = 0;
        dodefine_track(dbt_flags, DB_DBT_APPMALLOC);
        dodefine_track(dbt_flags, DB_DBT_DUPOK);
        dodefine_track(dbt_flags, DB_DBT_MALLOC);
#ifdef DB_DBT_MULTIPLE
        dodefine_track(dbt_flags, DB_DBT_MULTIPLE);
#endif
        dodefine_track(dbt_flags, DB_DBT_REALLOC);
        dodefine_track(dbt_flags, DB_DBT_USERMEM);
    }

    // flags for the env->set_flags function
#if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3
    dodefine(DB_LOG_AUTOREMOVE);
#endif

    {
    //Txn begin/commit flags
        uint32_t txn_flags = 0;
        dodefine_track(txn_flags, DB_TXN_WRITE_NOSYNC);
        dodefine_track(txn_flags, DB_TXN_NOWAIT);
        dodefine_track(txn_flags, DB_TXN_SYNC);
#ifdef DB_TXN_SNAPSHOT
        dodefine_track(txn_flags, DB_TXN_SNAPSHOT);
#endif
#ifdef DB_READ_UNCOMMITTED
        dodefine_track(txn_flags, DB_READ_UNCOMMITTED);
#endif
#ifdef DB_READ_COMMITTED
        dodefine_track(txn_flags, DB_READ_COMMITTED);
#endif
        //Add them if they didn't exist
#ifndef DB_TXN_SNAPSHOT
        dodefine_from_track(txn_flags, DB_TXN_SNAPSHOT);
#endif
#ifndef DB_READ_UNCOMMITTED
        dodefine_from_track(txn_flags, DB_READ_UNCOMMITTED);
#endif
#ifndef DB_READ_COMMITTED
        dodefine_from_track(txn_flags, DB_READ_COMMITTED);
#endif
        dodefine_from_track(txn_flags, DB_INHERIT_ISOLATION);
        dodefine_from_track(txn_flags, DB_SERIALIZABLE);
        dodefine_from_track(txn_flags, DB_TXN_READ_ONLY);
    }
    
    /* TokuFT specific error codes*/
    printf("/* TokuFT specific error codes */\n");
    dodefine(TOKUDB_OUT_OF_LOCKS);
    dodefine(TOKUDB_SUCCEEDED_EARLY);
    dodefine(TOKUDB_FOUND_BUT_REJECTED);
    dodefine(TOKUDB_USER_CALLBACK_ERROR);
    dodefine(TOKUDB_DICTIONARY_TOO_OLD);
    dodefine(TOKUDB_DICTIONARY_TOO_NEW);
    dodefine(TOKUDB_DICTIONARY_NO_HEADER);
    dodefine(TOKUDB_CANCELED);
    dodefine(TOKUDB_NO_DATA);
    dodefine(TOKUDB_ACCEPT);
    dodefine(TOKUDB_MVCC_DICTIONARY_TOO_NEW);
    dodefine(TOKUDB_UPGRADE_FAILURE);
    dodefine(TOKUDB_TRY_AGAIN);
    dodefine(TOKUDB_NEEDS_REPAIR);
    dodefine(TOKUDB_CURSOR_CONTINUE);
    dodefine(TOKUDB_BAD_CHECKSUM);
    dodefine(TOKUDB_HUGE_PAGES_ENABLED);
    dodefine(TOKUDB_OUT_OF_RANGE);
    dodefine(TOKUDB_INTERRUPTED);

    /* LOADER flags */
    printf("/* LOADER flags */\n");
    {
        uint32_t loader_flags = 0;
        dodefine_from_track(loader_flags, LOADER_DISALLOW_PUTS); // Loader is only used for side effects.
        dodefine_from_track(loader_flags, LOADER_COMPRESS_INTERMEDIATES);
    }
}

static void print_db_env_struct (void) {
    field_counter=0;
    STRUCT_SETUP(DB_ENV, api1_internal,   "void *%s"); /* Used for C++ hacking. */
    STRUCT_SETUP(DB_ENV, app_private, "void *%s");
    STRUCT_SETUP(DB_ENV, close, "int  (*%s) (DB_ENV *, uint32_t)");
    STRUCT_SETUP(DB_ENV, err, "void (*%s) (const DB_ENV *, int, const char *, ...) __attribute__ (( format (printf, 3, 4) ))");
#if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3
    STRUCT_SETUP(DB_ENV, get_cachesize, "int  (*%s) (DB_ENV *, uint32_t *, uint32_t *, int *)");
    STRUCT_SETUP(DB_ENV, get_flags, "int  (*%s) (DB_ENV *, uint32_t *)");
    STRUCT_SETUP(DB_ENV, get_lg_max, "int  (*%s) (DB_ENV *, uint32_t*)");
#endif
    STRUCT_SETUP(DB_ENV, log_archive, "int  (*%s) (DB_ENV *, char **[], uint32_t)");
    STRUCT_SETUP(DB_ENV, log_flush, "int  (*%s) (DB_ENV *, const DB_LSN *)");
    STRUCT_SETUP(DB_ENV, open, "int  (*%s) (DB_ENV *, const char *, uint32_t, int)");
    STRUCT_SETUP(DB_ENV, set_cachesize, "int  (*%s) (DB_ENV *, uint32_t, uint32_t, int)");
    STRUCT_SETUP(DB_ENV, set_data_dir, "int  (*%s) (DB_ENV *, const char *)");
#if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1
    STRUCT_SETUP(DB_ENV, set_errcall, "void (*%s) (DB_ENV *, void (*)(const char *, char *))");
#endif
#if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3
    STRUCT_SETUP(DB_ENV, set_errcall, "void (*%s) (DB_ENV *, void (*)(const DB_ENV *, const char *, const char *))");
#endif
    STRUCT_SETUP(DB_ENV, set_errfile, "void (*%s) (DB_ENV *, FILE*)");
    STRUCT_SETUP(DB_ENV, set_errpfx, "void (*%s) (DB_ENV *, const char *)");
    STRUCT_SETUP(DB_ENV, set_flags, "int  (*%s) (DB_ENV *, uint32_t, int)");
    STRUCT_SETUP(DB_ENV, set_lg_bsize, "int  (*%s) (DB_ENV *, uint32_t)");
    STRUCT_SETUP(DB_ENV, set_lg_dir, "int  (*%s) (DB_ENV *, const char *)");
    STRUCT_SETUP(DB_ENV, set_lg_max, "int  (*%s) (DB_ENV *, uint32_t)");
    STRUCT_SETUP(DB_ENV, set_lk_detect, "int  (*%s) (DB_ENV *, uint32_t)");
#if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR <= 4
    STRUCT_SETUP(DB_ENV, set_lk_max, "int  (*%s) (DB_ENV *, uint32_t)");
#endif
    //STRUCT_SETUP(DB_ENV, set_noticecall, "void (*%s) (DB_ENV *, void (*)(DB_ENV *, db_notices))");
    STRUCT_SETUP(DB_ENV, set_tmp_dir, "int  (*%s) (DB_ENV *, const char *)");
    STRUCT_SETUP(DB_ENV, set_verbose, "int  (*%s) (DB_ENV *, uint32_t, int)");
    STRUCT_SETUP(DB_ENV, txn_checkpoint, "int  (*%s) (DB_ENV *, uint32_t, uint32_t, uint32_t)");
    STRUCT_SETUP(DB_ENV, txn_stat,    "int  (*%s) (DB_ENV *, DB_TXN_STAT **, uint32_t)");
    STRUCT_SETUP(DB_ENV, txn_begin,   "int  (*%s) (DB_ENV *, DB_TXN *, DB_TXN **, uint32_t)");
    STRUCT_SETUP(DB_ENV, txn_recover, "int  (*%s) (DB_ENV *, DB_PREPLIST preplist[/*count*/], long count, /*out*/ long *retp, uint32_t flags)");
    STRUCT_SETUP(DB_ENV, dbremove,    "int  (*%s) (DB_ENV *, DB_TXN *, const char *, const char *, uint32_t)");
    STRUCT_SETUP(DB_ENV, dbrename,    "int  (*%s) (DB_ENV *, DB_TXN *, const char *, const char *, const char *, uint32_t)");

        const char *extra[]={
                             "int (*checkpointing_set_period)             (DB_ENV*, uint32_t) /* Change the delay between automatic checkpoints.  0 means disabled. */",
                             "int (*checkpointing_get_period)             (DB_ENV*, uint32_t*) /* Retrieve the delay between automatic checkpoints.  0 means disabled. */",
                             "int (*cleaner_set_period)                   (DB_ENV*, uint32_t) /* Change the delay between automatic cleaner attempts.  0 means disabled. */",
                             "int (*cleaner_get_period)                   (DB_ENV*, uint32_t*) /* Retrieve the delay between automatic cleaner attempts.  0 means disabled. */",
                             "int (*cleaner_set_iterations)               (DB_ENV*, uint32_t) /* Change the number of attempts on each cleaner invokation.  0 means disabled. */",
                             "int (*cleaner_get_iterations)               (DB_ENV*, uint32_t*) /* Retrieve the number of attempts on each cleaner invokation.  0 means disabled. */",
                             "int (*checkpointing_postpone)               (DB_ENV*) /* Use for 'rename table' or any other operation that must be disjoint from a checkpoint */",
                             "int (*checkpointing_resume)                 (DB_ENV*) /* Alert tokuft that 'postpone' is no longer necessary */",
                             "int (*checkpointing_begin_atomic_operation) (DB_ENV*) /* Begin a set of operations (that must be atomic as far as checkpoints are concerned). i.e. inserting into every index in one table */",
                             "int (*checkpointing_end_atomic_operation)   (DB_ENV*) /* End   a set of operations (that must be atomic as far as checkpoints are concerned). */",
                             "int (*set_default_bt_compare)               (DB_ENV*,int (*bt_compare) (DB *, const DBT *, const DBT *)) /* Set default (key) comparison function for all DBs in this environment.  Required for RECOVERY since you cannot open the DBs manually. */",
                             "int (*get_engine_status_num_rows)           (DB_ENV*, uint64_t*)  /* return number of rows in engine status */",
                             "int (*get_engine_status)                    (DB_ENV*, TOKU_ENGINE_STATUS_ROW, uint64_t, uint64_t*, fs_redzone_state*, uint64_t*, char*, int, toku_engine_status_include_type) /* Fill in status struct and redzone state, possibly env panic string */",
                             "int (*get_engine_status_text)               (DB_ENV*, char*, int)     /* Fill in status text */",
                             "int (*crash)                                (DB_ENV*, const char*/*expr_as_string*/,const char */*fun*/,const char*/*file*/,int/*line*/, int/*errno*/)",
                             "int (*get_iname)                            (DB_ENV* env, DBT* dname_dbt, DBT* iname_dbt) /* FOR TEST ONLY: lookup existing iname */",
                             "int (*create_loader)                        (DB_ENV *env, DB_TXN *txn, DB_LOADER **blp,    DB *src_db, int N, DB *dbs[/*N*/], uint32_t db_flags[/*N*/], uint32_t dbt_flags[/*N*/], uint32_t loader_flags)",
                             "int (*create_indexer)                       (DB_ENV *env, DB_TXN *txn, DB_INDEXER **idxrp, DB *src_db, int N, DB *dbs[/*N*/], uint32_t db_flags[/*N*/], uint32_t indexer_flags)",
                             "int (*put_multiple)                         (DB_ENV *env, DB *src_db, DB_TXN *txn,\n"
                             "                                               const DBT *src_key, const DBT *src_val,\n"
                             "                                               uint32_t num_dbs, DB **db_array, DBT_ARRAY *keys, DBT_ARRAY *vals, uint32_t *flags_array) /* insert into multiple DBs */",
                             "int (*set_generate_row_callback_for_put)    (DB_ENV *env, generate_row_for_put_func generate_row_for_put)",
                             "int (*del_multiple)                         (DB_ENV *env, DB *src_db, DB_TXN *txn,\n"
                             "                                               const DBT *src_key, const DBT *src_val,\n"
                             "                                               uint32_t num_dbs, DB **db_array, DBT_ARRAY *keys, uint32_t *flags_array) /* delete from multiple DBs */",
                             "int (*set_generate_row_callback_for_del)    (DB_ENV *env, generate_row_for_del_func generate_row_for_del)",
                             "int (*update_multiple)                      (DB_ENV *env, DB *src_db, DB_TXN *txn,\n"
                             "                                               DBT *old_src_key, DBT *old_src_data,\n"
                             "                                               DBT *new_src_key, DBT *new_src_data,\n"
                             "                                               uint32_t num_dbs, DB **db_array, uint32_t *flags_array,\n"
                             "                                               uint32_t num_keys, DBT_ARRAY *keys,\n"
                             "                                               uint32_t num_vals, DBT_ARRAY *vals) /* update multiple DBs */",
                             "int (*get_redzone)                          (DB_ENV *env, int *redzone) /* get the redzone limit */",
                             "int (*set_redzone)                          (DB_ENV *env, int redzone) /* set the redzone limit in percent of total space */",
                             "int (*set_lk_max_memory)                    (DB_ENV *env, uint64_t max)",
                             "int (*get_lk_max_memory)                    (DB_ENV *env, uint64_t *max)",
                             "void (*set_update)                          (DB_ENV *env, int (*update_function)(DB *, const DBT *key, const DBT *old_val, const DBT *extra, void (*set_val)(const DBT *new_val, void *set_extra), void *set_extra))",
                             "int (*set_lock_timeout)                     (DB_ENV *env, uint64_t default_lock_wait_time_msec, uint64_t (*get_lock_wait_time_cb)(uint64_t default_lock_wait_time))",
                             "int (*get_lock_timeout)                     (DB_ENV *env, uint64_t *lock_wait_time_msec)",
                             "int (*set_lock_timeout_callback)            (DB_ENV *env, lock_timeout_callback callback)",
                             "int (*txn_xa_recover)                       (DB_ENV*, TOKU_XA_XID list[/*count*/], long count, /*out*/ long *retp, uint32_t flags)",
                             "int (*get_txn_from_xid)                     (DB_ENV*, /*in*/ TOKU_XA_XID *, /*out*/ DB_TXN **)",
                             "int (*get_cursor_for_directory)             (DB_ENV*, /*in*/ DB_TXN *, /*out*/ DBC **)",
                             "int (*get_cursor_for_persistent_environment)(DB_ENV*, /*in*/ DB_TXN *, /*out*/ DBC **)",
                             "void (*change_fsync_log_period)             (DB_ENV*, uint32_t)",
                             "int (*iterate_live_transactions)            (DB_ENV *env, iterate_transactions_callback callback, void *extra)",
                             "int (*iterate_pending_lock_requests)        (DB_ENV *env, iterate_requests_callback callback, void *extra)",
                             "void (*set_loader_memory_size)(DB_ENV *env, uint64_t (*get_loader_memory_size_callback)(void))",
                             "uint64_t (*get_loader_memory_size)(DB_ENV *env)",
                             "void (*set_killed_callback)(DB_ENV *env, uint64_t default_killed_time_msec, uint64_t (*get_killed_time_callback)(uint64_t default_killed_time_msec), int (*killed_callback)(void))",
                             "void (*do_backtrace)                        (DB_ENV *env)",
                             NULL};

        sort_and_dump_fields("db_env", true, extra);
}

static void print_db_key_range_struct (void) {
    field_counter=0;
    STRUCT_SETUP(DB_KEY_RANGE, less, "double %s");
    STRUCT_SETUP(DB_KEY_RANGE, equal, "double %s");
    STRUCT_SETUP(DB_KEY_RANGE, greater, "double %s");
    sort_and_dump_fields("db_key_range", false, NULL);
}

static void print_db_lsn_struct (void) {
    field_counter=0;
    sort_and_dump_fields("db_lsn", false, NULL);
}

static void print_dbt_struct (void) {
    field_counter=0;
#if 0 && DB_VERSION_MAJOR==4 && DB_VERSION_MINOR==1<commit_msg>MDEV-7526: TokuDB doesn't build on OS X<commit_after>/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
/*
COPYING CONDITIONS NOTICE:

  This program is free software; you can redistribute it and/or modify
  it under the terms of version 2 of the GNU General Public License as
  published by the Free Software Foundation, and provided that the
  following conditions are met:

      * Redistributions of source code must retain this COPYING
        CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
        DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
        PATENT MARKING NOTICE (below), and the PATENT RIGHTS
        GRANT (below).

      * Redistributions in binary form must reproduce this COPYING
        CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
        DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
        PATENT MARKING NOTICE (below), and the PATENT RIGHTS
        GRANT (below) in the documentation and/or other materials
        provided with the distribution.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  02110-1301, USA.

COPYRIGHT NOTICE:

  TokuFT, Tokutek Fractal Tree Indexing Library.
  Copyright (C) 2007-2013 Tokutek, Inc.

DISCLAIMER:

  This program is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  General Public License for more details.

UNIVERSITY PATENT NOTICE:

  The technology is licensed by the Massachusetts Institute of
  Technology, Rutgers State University of New Jersey, and the Research
  Foundation of State University of New York at Stony Brook under
  United States of America Serial No. 11/760379 and to the patents
  and/or patent applications resulting from it.

PATENT MARKING NOTICE:

  This software is covered by US Patent No. 8,185,551.
  This software is covered by US Patent No. 8,489,638.

PATENT RIGHTS GRANT:

  "THIS IMPLEMENTATION" means the copyrightable works distributed by
  Tokutek as part of the Fractal Tree project.

  "PATENT CLAIMS" means the claims of patents that are owned or
  licensable by Tokutek, both currently or in the future; and that in
  the absence of this license would be infringed by THIS
  IMPLEMENTATION or by using or running THIS IMPLEMENTATION.

  "PATENT CHALLENGE" shall mean a challenge to the validity,
  patentability, enforceability and/or non-infringement of any of the
  PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.

  Tokutek hereby grants to you, for the term and geographical scope of
  the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
  irrevocable (except as stated in this section) patent license to
  make, have made, use, offer to sell, sell, import, transfer, and
  otherwise run, modify, and propagate the contents of THIS
  IMPLEMENTATION, where such license applies only to the PATENT
  CLAIMS.  This grant does not include claims that would be infringed
  only as a consequence of further modifications of THIS
  IMPLEMENTATION.  If you or your agent or licensee institute or order
  or agree to the institution of patent litigation against any entity
  (including a cross-claim or counterclaim in a lawsuit) alleging that
  THIS IMPLEMENTATION constitutes direct or contributory patent
  infringement, or inducement of patent infringement, then any rights
  granted to you under this License shall terminate as of the date
  such litigation is filed.  If you or your agent or exclusive
  licensee institute or order or agree to the institution of a PATENT
  CHALLENGE, then Tokutek may terminate any rights granted to you
  under this License.
*/

#ident "Copyright (c) 2007-2013 Tokutek Inc.  All rights reserved."
#ident "$Id$"
/* LICENSE:  This file is licensed under the GPL or from Tokutek. */

/* Make a db.h that will be link-time compatible with Sleepycat's Berkeley DB. */


#include <stdio.h>
#include <stdlib.h>
// Don't include toku_assert.h.   Just use assert.h
#include <assert.h>
#include <string.h>
#include <sys/types.h>

#define VISIBLE "__attribute__((__visibility__(\"default\")))"

#define FIELD_LIMIT 100
struct fieldinfo {
    const char *decl_format_string;
    const char *name;
    size_t offset;
} fields[FIELD_LIMIT];
static int field_counter=0;

static int compare_fields (const void *av, const void *bv) {
    const struct fieldinfo *a = (const struct fieldinfo *) av;
    const struct fieldinfo *b = (const struct fieldinfo *) bv;
    if (a->offset< b->offset) return -1;
    if (a->offset==b->offset) return  0;
    return +1;
}				      

#define STRUCT_SETUP(typ, fname, fstring) ({            \
    assert(field_counter<FIELD_LIMIT);                  \
    fields[field_counter].decl_format_string = fstring; \
    fields[field_counter].name               = #fname;  \
    fields[field_counter].offset             = __builtin_offsetof(typ, fname); \
    field_counter++; })

static void sort_and_dump_fields (const char *structname, bool has_internal, const char *extra_decls[]) {
    int i;
    qsort(fields, field_counter, sizeof(fields[0]), compare_fields);
    printf("struct __toku_%s {\n", structname);
    if (has_internal) {
	printf("  struct __toku_%s_internal *i;\n", structname);
	printf("#define %s_struct_i(x) ((x)->i)\n", structname);
    }
    if (extra_decls) {
	while (*extra_decls) {
	    printf("  %s;\n", *extra_decls);
	    extra_decls++;
	}
    }
    for (i=0; i<field_counter; i++) {
	printf("  ");
	printf(fields[i].decl_format_string, fields[i].name);
	printf(";\n");
    }
    printf("};\n");
}

#include "db-4.6.19.h"

static void print_dbtype(void) {
    /* DBTYPE is mentioned by db_open.html */
    printf("typedef enum {\n");
    printf(" DB_BTREE=%d,\n", DB_BTREE);
    printf(" DB_UNKNOWN=%d\n", DB_UNKNOWN);
    printf("} DBTYPE;\n");
}


#define dodefine(name) printf("#define %s %d\n", #name, name)
#define dodefine_track(flags, name) ({ assert((flags & name) != name);	\
                                       flags |= (name);                \
                                       printf("#define %s %d\n", #name, name); })
#define dodefine_from_track(flags, name) ({\
    uint32_t which;                        \
    uint32_t bit;                          \
    for (which = 0; which < 32; which++) { \
        bit = 1U << which;                 \
        if (!(flags & bit)) break;         \
    }                                      \
    assert(which < 32);                    \
    printf("#define %s %u\n", #name, bit); \
    flags |= bit;                          \
    })

#define dodefine_track_enum(flags, name) ({ assert(name>=0 && name<256); \
                                            assert(!(flags[name])); \
                                            flags[name] = 1;        \
                                            printf("#define %s %d\n", #name, (int)(name)); })
#define dodefine_from_track_enum(flags, name) ({\
    uint32_t which;                             \
    /* don't use 0 */                           \
    for (which = 1; which < 256; which++) {     \
        if (!(flags[which])) break;             \
    }                                           \
    assert(which < 256);                        \
    flags[which] = 1;                           \
    printf("#define %s %u\n", #name, which);    \
    })

enum {
        TOKUDB_OUT_OF_LOCKS            = -100000,
        TOKUDB_SUCCEEDED_EARLY         = -100001,
        TOKUDB_FOUND_BUT_REJECTED      = -100002,
        TOKUDB_USER_CALLBACK_ERROR     = -100003,
        TOKUDB_DICTIONARY_TOO_OLD      = -100004,
        TOKUDB_DICTIONARY_TOO_NEW      = -100005,
        TOKUDB_DICTIONARY_NO_HEADER    = -100006,
        TOKUDB_CANCELED                = -100007,
        TOKUDB_NO_DATA                 = -100008,
        TOKUDB_ACCEPT                  = -100009,
        TOKUDB_MVCC_DICTIONARY_TOO_NEW = -100010,
        TOKUDB_UPGRADE_FAILURE         = -100011,
        TOKUDB_TRY_AGAIN               = -100012,
        TOKUDB_NEEDS_REPAIR            = -100013,
        TOKUDB_CURSOR_CONTINUE         = -100014,
        TOKUDB_BAD_CHECKSUM            = -100015,
        TOKUDB_HUGE_PAGES_ENABLED      = -100016,
        TOKUDB_OUT_OF_RANGE            = -100017,
        TOKUDB_INTERRUPTED             = -100018,
        DONTUSE_I_JUST_PUT_THIS_HERE_SO_I_COULD_HAVE_A_COMMA_AFTER_EACH_ITEM
};

static void print_defines (void) {
    dodefine(DB_VERB_DEADLOCK);
    dodefine(DB_VERB_RECOVERY);
    dodefine(DB_VERB_REPLICATION);
    dodefine(DB_VERB_WAITSFOR);

    dodefine(DB_ARCH_ABS);
    dodefine(DB_ARCH_LOG);

    dodefine(DB_CREATE);
    dodefine(DB_CXX_NO_EXCEPTIONS);
    dodefine(DB_EXCL);
    dodefine(DB_PRIVATE);
    dodefine(DB_RDONLY);
    dodefine(DB_RECOVER);
    dodefine(DB_RUNRECOVERY);
    dodefine(DB_THREAD);
    dodefine(DB_TXN_NOSYNC);

    /* according to BDB 4.6.19, this is the next unused flag in the set of
     * common flags plus private flags for DB->open */
#define	DB_BLACKHOLE 0x0080000
    dodefine(DB_BLACKHOLE);
#undef DB_BLACKHOLE

    dodefine(DB_LOCK_DEFAULT);
    dodefine(DB_LOCK_OLDEST);
    dodefine(DB_LOCK_RANDOM);

    //dodefine(DB_DUP);      No longer supported #2862
    //dodefine(DB_DUPSORT);  No longer supported #2862

    dodefine(DB_KEYFIRST);
    dodefine(DB_KEYLAST);
    {
        static uint8_t insert_flags[256];
        dodefine_track_enum(insert_flags, DB_NOOVERWRITE);
        dodefine_track_enum(insert_flags, DB_NODUPDATA);
        dodefine_from_track_enum(insert_flags, DB_NOOVERWRITE_NO_ERROR);
    }
    dodefine(DB_OPFLAGS_MASK);

    dodefine(DB_AUTO_COMMIT);

    dodefine(DB_INIT_LOCK);
    dodefine(DB_INIT_LOG);
    dodefine(DB_INIT_MPOOL);
    dodefine(DB_INIT_TXN);

    //dodefine(DB_KEYEMPTY);      /// KEYEMPTY is no longer used.  We just use DB_NOTFOUND
    dodefine(DB_KEYEXIST);
    dodefine(DB_LOCK_DEADLOCK);
    dodefine(DB_LOCK_NOTGRANTED);
    dodefine(DB_NOTFOUND);
    dodefine(DB_SECONDARY_BAD);
    dodefine(DB_DONOTINDEX);
#ifdef DB_BUFFER_SMALL
    dodefine(DB_BUFFER_SMALL);
#endif
    printf("#define DB_BADFORMAT -30500\n"); // private tokudb
    printf("#define DB_DELETE_ANY %d\n", 1<<16); // private tokudb

    dodefine(DB_FIRST);
    dodefine(DB_LAST);
    dodefine(DB_CURRENT);
    dodefine(DB_NEXT);
    dodefine(DB_PREV);
    dodefine(DB_SET);
    dodefine(DB_SET_RANGE);
    printf("#define DB_CURRENT_BINDING 253\n"); // private tokudb
    printf("#define DB_SET_RANGE_REVERSE 252\n"); // private tokudb
    //printf("#define DB_GET_BOTH_RANGE_REVERSE 251\n"); // private tokudb.  No longer supported #2862.
    dodefine(DB_RMW);
    printf("#define DB_IS_RESETTING_OP 0x01000000\n"); // private tokudb
    printf("#define DB_PRELOCKED 0x00800000\n"); // private tokudb
    printf("#define DB_PRELOCKED_WRITE 0x00400000\n"); // private tokudb
    //printf("#define DB_PRELOCKED_FILE_READ 0x00200000\n"); // private tokudb. No longer supported in #4472
    printf("#define DB_IS_HOT_INDEX 0x00100000\n"); // private tokudb
    printf("#define DBC_DISABLE_PREFETCHING 0x20000000\n"); // private tokudb
    printf("#define DB_UPDATE_CMP_DESCRIPTOR 0x40000000\n"); // private tokudb
    printf("#define TOKUFT_DIRTY_SHUTDOWN %x\n", 1<<31);

    {
        //dbt flags
        uint32_t dbt_flags = 0;
        dodefine_track(dbt_flags, DB_DBT_APPMALLOC);
        dodefine_track(dbt_flags, DB_DBT_DUPOK);
        dodefine_track(dbt_flags, DB_DBT_MALLOC);
#ifdef DB_DBT_MULTIPLE
        dodefine_track(dbt_flags, DB_DBT_MULTIPLE);
#endif
        dodefine_track(dbt_flags, DB_DBT_REALLOC);
        dodefine_track(dbt_flags, DB_DBT_USERMEM);
    }

    // flags for the env->set_flags function
#if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3
    dodefine(DB_LOG_AUTOREMOVE);
#endif

    {
    //Txn begin/commit flags
        uint32_t txn_flags = 0;
        dodefine_track(txn_flags, DB_TXN_WRITE_NOSYNC);
        dodefine_track(txn_flags, DB_TXN_NOWAIT);
        dodefine_track(txn_flags, DB_TXN_SYNC);
#ifdef DB_TXN_SNAPSHOT
        dodefine_track(txn_flags, DB_TXN_SNAPSHOT);
#endif
#ifdef DB_READ_UNCOMMITTED
        dodefine_track(txn_flags, DB_READ_UNCOMMITTED);
#endif
#ifdef DB_READ_COMMITTED
        dodefine_track(txn_flags, DB_READ_COMMITTED);
#endif
        //Add them if they didn't exist
#ifndef DB_TXN_SNAPSHOT
        dodefine_from_track(txn_flags, DB_TXN_SNAPSHOT);
#endif
#ifndef DB_READ_UNCOMMITTED
        dodefine_from_track(txn_flags, DB_READ_UNCOMMITTED);
#endif
#ifndef DB_READ_COMMITTED
        dodefine_from_track(txn_flags, DB_READ_COMMITTED);
#endif
        dodefine_from_track(txn_flags, DB_INHERIT_ISOLATION);
        dodefine_from_track(txn_flags, DB_SERIALIZABLE);
        dodefine_from_track(txn_flags, DB_TXN_READ_ONLY);
    }
    
    /* TokuFT specific error codes*/
    printf("/* TokuFT specific error codes */\n");
    dodefine(TOKUDB_OUT_OF_LOCKS);
    dodefine(TOKUDB_SUCCEEDED_EARLY);
    dodefine(TOKUDB_FOUND_BUT_REJECTED);
    dodefine(TOKUDB_USER_CALLBACK_ERROR);
    dodefine(TOKUDB_DICTIONARY_TOO_OLD);
    dodefine(TOKUDB_DICTIONARY_TOO_NEW);
    dodefine(TOKUDB_DICTIONARY_NO_HEADER);
    dodefine(TOKUDB_CANCELED);
    dodefine(TOKUDB_NO_DATA);
    dodefine(TOKUDB_ACCEPT);
    dodefine(TOKUDB_MVCC_DICTIONARY_TOO_NEW);
    dodefine(TOKUDB_UPGRADE_FAILURE);
    dodefine(TOKUDB_TRY_AGAIN);
    dodefine(TOKUDB_NEEDS_REPAIR);
    dodefine(TOKUDB_CURSOR_CONTINUE);
    dodefine(TOKUDB_BAD_CHECKSUM);
    dodefine(TOKUDB_HUGE_PAGES_ENABLED);
    dodefine(TOKUDB_OUT_OF_RANGE);
    dodefine(TOKUDB_INTERRUPTED);

    /* LOADER flags */
    printf("/* LOADER flags */\n");
    {
        uint32_t loader_flags = 0;
        dodefine_from_track(loader_flags, LOADER_DISALLOW_PUTS); // Loader is only used for side effects.
        dodefine_from_track(loader_flags, LOADER_COMPRESS_INTERMEDIATES);
    }
}

static void print_db_env_struct (void) {
    field_counter=0;
    STRUCT_SETUP(DB_ENV, api1_internal,   "void *%s"); /* Used for C++ hacking. */
    STRUCT_SETUP(DB_ENV, app_private, "void *%s");
    STRUCT_SETUP(DB_ENV, close, "int  (*%s) (DB_ENV *, uint32_t)");
    STRUCT_SETUP(DB_ENV, err, "void (*%s) (const DB_ENV *, int, const char *, ...) __attribute__ (( format (printf, 3, 4) ))");
#if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3
    STRUCT_SETUP(DB_ENV, get_cachesize, "int  (*%s) (DB_ENV *, uint32_t *, uint32_t *, int *)");
    STRUCT_SETUP(DB_ENV, get_flags, "int  (*%s) (DB_ENV *, uint32_t *)");
    STRUCT_SETUP(DB_ENV, get_lg_max, "int  (*%s) (DB_ENV *, uint32_t*)");
#endif
    STRUCT_SETUP(DB_ENV, log_archive, "int  (*%s) (DB_ENV *, char **[], uint32_t)");
    STRUCT_SETUP(DB_ENV, log_flush, "int  (*%s) (DB_ENV *, const DB_LSN *)");
    STRUCT_SETUP(DB_ENV, open, "int  (*%s) (DB_ENV *, const char *, uint32_t, int)");
    STRUCT_SETUP(DB_ENV, set_cachesize, "int  (*%s) (DB_ENV *, uint32_t, uint32_t, int)");
    STRUCT_SETUP(DB_ENV, set_data_dir, "int  (*%s) (DB_ENV *, const char *)");
#if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1
    STRUCT_SETUP(DB_ENV, set_errcall, "void (*%s) (DB_ENV *, void (*)(const char *, char *))");
#endif
#if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3
    STRUCT_SETUP(DB_ENV, set_errcall, "void (*%s) (DB_ENV *, void (*)(const DB_ENV *, const char *, const char *))");
#endif
    STRUCT_SETUP(DB_ENV, set_errfile, "void (*%s) (DB_ENV *, FILE*)");
    STRUCT_SETUP(DB_ENV, set_errpfx, "void (*%s) (DB_ENV *, const char *)");
    STRUCT_SETUP(DB_ENV, set_flags, "int  (*%s) (DB_ENV *, uint32_t, int)");
    STRUCT_SETUP(DB_ENV, set_lg_bsize, "int  (*%s) (DB_ENV *, uint32_t)");
    STRUCT_SETUP(DB_ENV, set_lg_dir, "int  (*%s) (DB_ENV *, const char *)");
    STRUCT_SETUP(DB_ENV, set_lg_max, "int  (*%s) (DB_ENV *, uint32_t)");
    STRUCT_SETUP(DB_ENV, set_lk_detect, "int  (*%s) (DB_ENV *, uint32_t)");
#if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR <= 4
    STRUCT_SETUP(DB_ENV, set_lk_max, "int  (*%s) (DB_ENV *, uint32_t)");
#endif
    //STRUCT_SETUP(DB_ENV, set_noticecall, "void (*%s) (DB_ENV *, void (*)(DB_ENV *, db_notices))");
    STRUCT_SETUP(DB_ENV, set_tmp_dir, "int  (*%s) (DB_ENV *, const char *)");
    STRUCT_SETUP(DB_ENV, set_verbose, "int  (*%s) (DB_ENV *, uint32_t, int)");
    STRUCT_SETUP(DB_ENV, txn_checkpoint, "int  (*%s) (DB_ENV *, uint32_t, uint32_t, uint32_t)");
    STRUCT_SETUP(DB_ENV, txn_stat,    "int  (*%s) (DB_ENV *, DB_TXN_STAT **, uint32_t)");
    STRUCT_SETUP(DB_ENV, txn_begin,   "int  (*%s) (DB_ENV *, DB_TXN *, DB_TXN **, uint32_t)");
    STRUCT_SETUP(DB_ENV, txn_recover, "int  (*%s) (DB_ENV *, DB_PREPLIST preplist[/*count*/], long count, /*out*/ long *retp, uint32_t flags)");
    STRUCT_SETUP(DB_ENV, dbremove,    "int  (*%s) (DB_ENV *, DB_TXN *, const char *, const char *, uint32_t)");
    STRUCT_SETUP(DB_ENV, dbrename,    "int  (*%s) (DB_ENV *, DB_TXN *, const char *, const char *, const char *, uint32_t)");

        const char *extra[]={
                             "int (*checkpointing_set_period)             (DB_ENV*, uint32_t) /* Change the delay between automatic checkpoints.  0 means disabled. */",
                             "int (*checkpointing_get_period)             (DB_ENV*, uint32_t*) /* Retrieve the delay between automatic checkpoints.  0 means disabled. */",
                             "int (*cleaner_set_period)                   (DB_ENV*, uint32_t) /* Change the delay between automatic cleaner attempts.  0 means disabled. */",
                             "int (*cleaner_get_period)                   (DB_ENV*, uint32_t*) /* Retrieve the delay between automatic cleaner attempts.  0 means disabled. */",
                             "int (*cleaner_set_iterations)               (DB_ENV*, uint32_t) /* Change the number of attempts on each cleaner invokation.  0 means disabled. */",
                             "int (*cleaner_get_iterations)               (DB_ENV*, uint32_t*) /* Retrieve the number of attempts on each cleaner invokation.  0 means disabled. */",
                             "int (*checkpointing_postpone)               (DB_ENV*) /* Use for 'rename table' or any other operation that must be disjoint from a checkpoint */",
                             "int (*checkpointing_resume)                 (DB_ENV*) /* Alert tokuft that 'postpone' is no longer necessary */",
                             "int (*checkpointing_begin_atomic_operation) (DB_ENV*) /* Begin a set of operations (that must be atomic as far as checkpoints are concerned). i.e. inserting into every index in one table */",
                             "int (*checkpointing_end_atomic_operation)   (DB_ENV*) /* End   a set of operations (that must be atomic as far as checkpoints are concerned). */",
                             "int (*set_default_bt_compare)               (DB_ENV*,int (*bt_compare) (DB *, const DBT *, const DBT *)) /* Set default (key) comparison function for all DBs in this environment.  Required for RECOVERY since you cannot open the DBs manually. */",
                             "int (*get_engine_status_num_rows)           (DB_ENV*, uint64_t*)  /* return number of rows in engine status */",
                             "int (*get_engine_status)                    (DB_ENV*, TOKU_ENGINE_STATUS_ROW, uint64_t, uint64_t*, fs_redzone_state*, uint64_t*, char*, int, toku_engine_status_include_type) /* Fill in status struct and redzone state, possibly env panic string */",
                             "int (*get_engine_status_text)               (DB_ENV*, char*, int)     /* Fill in status text */",
                             "int (*crash)                                (DB_ENV*, const char*/*expr_as_string*/,const char */*fun*/,const char*/*file*/,int/*line*/, int/*errno*/)",
                             "int (*get_iname)                            (DB_ENV* env, DBT* dname_dbt, DBT* iname_dbt) /* FOR TEST ONLY: lookup existing iname */",
                             "int (*create_loader)                        (DB_ENV *env, DB_TXN *txn, DB_LOADER **blp,    DB *src_db, int N, DB *dbs[/*N*/], uint32_t db_flags[/*N*/], uint32_t dbt_flags[/*N*/], uint32_t loader_flags)",
                             "int (*create_indexer)                       (DB_ENV *env, DB_TXN *txn, DB_INDEXER **idxrp, DB *src_db, int N, DB *dbs[/*N*/], uint32_t db_flags[/*N*/], uint32_t indexer_flags)",
                             "int (*put_multiple)                         (DB_ENV *env, DB *src_db, DB_TXN *txn,\n"
                             "                                               const DBT *src_key, const DBT *src_val,\n"
                             "                                               uint32_t num_dbs, DB **db_array, DBT_ARRAY *keys, DBT_ARRAY *vals, uint32_t *flags_array) /* insert into multiple DBs */",
                             "int (*set_generate_row_callback_for_put)    (DB_ENV *env, generate_row_for_put_func generate_row_for_put)",
                             "int (*del_multiple)                         (DB_ENV *env, DB *src_db, DB_TXN *txn,\n"
                             "                                               const DBT *src_key, const DBT *src_val,\n"
                             "                                               uint32_t num_dbs, DB **db_array, DBT_ARRAY *keys, uint32_t *flags_array) /* delete from multiple DBs */",
                             "int (*set_generate_row_callback_for_del)    (DB_ENV *env, generate_row_for_del_func generate_row_for_del)",
                             "int (*update_multiple)                      (DB_ENV *env, DB *src_db, DB_TXN *txn,\n"
                             "                                               DBT *old_src_key, DBT *old_src_data,\n"
                             "                                               DBT *new_src_key, DBT *new_src_data,\n"
                             "                                               uint32_t num_dbs, DB **db_array, uint32_t *flags_array,\n"
                             "                                               uint32_t num_keys, DBT_ARRAY *keys,\n"
                             "                                               uint32_t num_vals, DBT_ARRAY *vals) /* update multiple DBs */",
                             "int (*get_redzone)                          (DB_ENV *env, int *redzone) /* get the redzone limit */",
                             "int (*set_redzone)                          (DB_ENV *env, int redzone) /* set the redzone limit in percent of total space */",
                             "int (*set_lk_max_memory)                    (DB_ENV *env, uint64_t max)",
                             "int (*get_lk_max_memory)                    (DB_ENV *env, uint64_t *max)",
                             "void (*set_update)                          (DB_ENV *env, int (*update_function)(DB *, const DBT *key, const DBT *old_val, const DBT *extra, void (*set_val)(const DBT *new_val, void *set_extra), void *set_extra))",
                             "int (*set_lock_timeout)                     (DB_ENV *env, uint64_t default_lock_wait_time_msec, uint64_t (*get_lock_wait_time_cb)(uint64_t default_lock_wait_time))",
                             "int (*get_lock_timeout)                     (DB_ENV *env, uint64_t *lock_wait_time_msec)",
                             "int (*set_lock_timeout_callback)            (DB_ENV *env, lock_timeout_callback callback)",
                             "int (*txn_xa_recover)                       (DB_ENV*, TOKU_XA_XID list[/*count*/], long count, /*out*/ long *retp, uint32_t flags)",
                             "int (*get_txn_from_xid)                     (DB_ENV*, /*in*/ TOKU_XA_XID *, /*out*/ DB_TXN **)",
                             "int (*get_cursor_for_directory)             (DB_ENV*, /*in*/ DB_TXN *, /*out*/ DBC **)",
                             "int (*get_cursor_for_persistent_environment)(DB_ENV*, /*in*/ DB_TXN *, /*out*/ DBC **)",
                             "void (*change_fsync_log_period)             (DB_ENV*, uint32_t)",
                             "int (*iterate_live_transactions)            (DB_ENV *env, iterate_transactions_callback callback, void *extra)",
                             "int (*iterate_pending_lock_requests)        (DB_ENV *env, iterate_requests_callback callback, void *extra)",
                             "void (*set_loader_memory_size)(DB_ENV *env, uint64_t (*get_loader_memory_size_callback)(void))",
                             "uint64_t (*get_loader_memory_size)(DB_ENV *env)",
                             "void (*set_killed_callback)(DB_ENV *env, uint64_t default_killed_time_msec, uint64_t (*get_killed_time_callback)(uint64_t default_killed_time_msec), int (*killed_callback)(void))",
                             "void (*do_backtrace)                        (DB_ENV *env)",
                             NULL};

        sort_and_dump_fields("db_env", true, extra);
}

static void print_db_key_range_struct (void) {
    field_counter=0;
    STRUCT_SETUP(DB_KEY_RANGE, less, "double %s");
    STRUCT_SETUP(DB_KEY_RANGE, equal, "double %s");
    STRUCT_SETUP(DB_KEY_RANGE, greater, "double %s");
    sort_and_dump_fields("db_key_range", false, NULL);
}

static void print_db_lsn_struct (void) {
    field_counter=0;
    /* A dummy field to make sizeof(DB_LSN) equal in C and C++ */
    const char *extra[] = { "char dummy", NULL };
    sort_and_dump_fields("db_lsn", false, extra);
}

static void print_dbt_struct (void) {
    field_counter=0;
#if 0 && DB_VERSION_MAJOR==4 && DB_VERSION_MINOR==1
{'fraction_non_alphanumeric': 0.1099315001658828, 'fraction_numerical': 0.0186179036318573, 'mean_word_length': 2.408407609418651, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 4, 'word_list_counts': {'cursed_substrings.json': 76, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3426776', 'n_tokens_mistral': 17943, 'n_tokens_neox': 16963, 'n_words': 4102}