Main Page | Class Hierarchy | Data Structures | Directories | File List | Data Fields | Related Pages

tcl_db.h

00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 1999-2005
00005  *      Sleepycat Software.  All rights reserved.
00006  *
00007  * $Id: tcl_db.h,v 12.4 2005/08/08 14:52:30 bostic Exp $
00008  */
00009 
00010 #ifndef _DB_TCL_DB_H_
00011 #define _DB_TCL_DB_H_
00012 
00013 #define MSG_SIZE 100            /* Message size */
00014 
00015 enum INFOTYPE {
00016     I_ENV, I_DB, I_DBC, I_TXN, I_MP, I_PG, I_LOCK, I_LOGC, I_NDBM, I_SEQ};
00017 
00018 #define MAX_ID          8       /* Maximum number of sub-id's we need */
00019 #define DBTCL_PREP      64      /* Size of txn_recover preplist */
00020 
00021 #define DBTCL_DBM       1
00022 #define DBTCL_NDBM      2
00023 
00024 /*
00025  * Why use a home grown package over the Tcl_Hash functions?
00026  *
00027  * We could have implemented the stuff below without maintaining our
00028  * own list manipulation, efficiently hashing it with the available
00029  * Tcl functions (Tcl_CreateHashEntry, Tcl_GetHashValue, etc).  I chose
00030  * not to do so for these reasons:
00031  *
00032  * We still need the information below.  Using the hashing only removes
00033  * us from needing the next/prev pointers.  We still need the structure
00034  * itself because we need more than one value associated with a widget.
00035  * We need to keep track of parent pointers for sub-widgets (like cursors)
00036  * so we can correctly close.  We need to keep track of individual widget's
00037  * id counters for any sub-widgets they may have.  We need to be able to
00038  * associate the name/client data outside the scope of the widget.
00039  *
00040  * So, is it better to use the hashing rather than
00041  * the linear list we have now?  I decided against it for the simple reason
00042  * that to access the structure would require two calls.  The first is
00043  * Tcl_FindHashEntry(table, key) and then, once we have the entry, we'd
00044  * have to do Tcl_GetHashValue(entry) to get the pointer of the structure.
00045  *
00046  * I believe the number of simultaneous DB widgets in existence at one time
00047  * is not going to be that large (more than several dozen) such that
00048  * linearly searching the list is not going to impact performance in a
00049  * noticeable way.  Should performance be impacted due to the size of the
00050  * info list, then perhaps it is time to revisit this decision.
00051  */
00052 typedef struct dbtcl_info {
00053         LIST_ENTRY(dbtcl_info) entries;
00054         Tcl_Interp *i_interp;
00055         char *i_name;
00056         enum INFOTYPE i_type;
00057         union infop {
00058                 DB *dbp;
00059                 DBC *dbcp;
00060                 DB_ENV *envp;
00061                 DB_LOCK *lock;
00062                 DB_LOGC *logc;
00063                 DB_MPOOLFILE *mp;
00064                 DB_TXN *txnp;
00065                 void *anyp;
00066         } un;
00067         union data {
00068                 int anydata;
00069                 db_pgno_t pgno;
00070                 u_int32_t lockid;
00071         } und;
00072         union data2 {
00073                 int anydata;
00074                 int pagesz;
00075                 DB_COMPACT *c_data;
00076         } und2;
00077         DBT i_lockobj;
00078         FILE *i_err;
00079         char *i_errpfx;
00080 
00081         /* Callbacks--Tcl_Objs containing proc names */
00082         Tcl_Obj *i_btcompare;
00083         Tcl_Obj *i_dupcompare;
00084         Tcl_Obj *i_hashproc;
00085         Tcl_Obj *i_rep_send;
00086         Tcl_Obj *i_second_call;
00087 
00088         /* Environment ID for the i_rep_send callback. */
00089         Tcl_Obj *i_rep_eid;
00090 
00091         struct dbtcl_info *i_parent;
00092         int     i_otherid[MAX_ID];
00093 } DBTCL_INFO;
00094 
00095 #define i_anyp un.anyp
00096 #define i_pagep un.anyp
00097 #define i_envp un.envp
00098 #define i_dbp un.dbp
00099 #define i_dbcp un.dbcp
00100 #define i_txnp un.txnp
00101 #define i_mp un.mp
00102 #define i_lock un.lock
00103 #define i_logc un.logc
00104 
00105 #define i_data und.anydata
00106 #define i_pgno und.pgno
00107 #define i_locker und.lockid
00108 #define i_data2 und2.anydata
00109 #define i_pgsz und2.pagesz
00110 #define i_cdata und2.c_data
00111 
00112 #define i_envtxnid i_otherid[0]
00113 #define i_envmpid i_otherid[1]
00114 #define i_envlockid i_otherid[2]
00115 #define i_envlogcid i_otherid[3]
00116 
00117 #define i_mppgid  i_otherid[0]
00118 
00119 #define i_dbdbcid i_otherid[0]
00120 
00121 extern int __debug_on, __debug_print, __debug_stop, __debug_test;
00122 
00123 typedef struct dbtcl_global {
00124         LIST_HEAD(infohead, dbtcl_info) g_infohead;
00125 } DBTCL_GLOBAL;
00126 #define __db_infohead __dbtcl_global.g_infohead
00127 
00128 extern DBTCL_GLOBAL __dbtcl_global;
00129 
00130 /*
00131  * Tcl_NewStringObj takes an "int" length argument, when the typical use is to
00132  * call it with a size_t length (for example, returned by strlen).  Tcl is in
00133  * the wrong, but that doesn't help us much -- cast the argument.
00134  */
00135 #define NewStringObj(a, b)                                              \
00136         Tcl_NewStringObj(a, (int)b)
00137 
00138 #define NAME_TO_DB(name)        (DB *)_NameToPtr((name))
00139 #define NAME_TO_DBC(name)       (DBC *)_NameToPtr((name))
00140 #define NAME_TO_ENV(name)       (DB_ENV *)_NameToPtr((name))
00141 #define NAME_TO_LOCK(name)      (DB_LOCK *)_NameToPtr((name))
00142 #define NAME_TO_MP(name)        (DB_MPOOLFILE *)_NameToPtr((name))
00143 #define NAME_TO_TXN(name)       (DB_TXN *)_NameToPtr((name))
00144 #define NAME_TO_SEQUENCE(name)  (DB_SEQUENCE *)_NameToPtr((name))
00145 
00146 /*
00147  * MAKE_STAT_LIST appends a {name value} pair to a result list that MUST be
00148  * called 'res' that is a Tcl_Obj * in the local function.  This macro also
00149  * assumes a label "error" to go to in the event of a Tcl error.  For stat
00150  * functions this will typically go before the "free" function to free the
00151  * stat structure returned by DB.
00152  */
00153 #define MAKE_STAT_LIST(s, v) do {                                       \
00154         result = _SetListElemInt(interp, res, (s), (long)(v));          \
00155         if (result != TCL_OK)                                           \
00156                 goto error;                                             \
00157 } while (0)
00158 
00159 #define MAKE_WSTAT_LIST(s, v) do {                                      \
00160         result = _SetListElemWideInt(interp, res, (s), (int64_t)(v));   \
00161         if (result != TCL_OK)                                           \
00162                 goto error;                                             \
00163 } while (0)
00164 
00165 /*
00166  * MAKE_STAT_LSN appends a {name {LSNfile LSNoffset}} pair to a result list
00167  * that MUST be called 'res' that is a Tcl_Obj * in the local
00168  * function.  This macro also assumes a label "error" to go to
00169  * in the even of a Tcl error.  For stat functions this will
00170  * typically go before the "free" function to free the stat structure
00171  * returned by DB.
00172  */
00173 #define MAKE_STAT_LSN(s, lsn) do {                                      \
00174         myobjc = 2;                                                     \
00175         myobjv[0] = Tcl_NewLongObj((long)(lsn)->file);                  \
00176         myobjv[1] = Tcl_NewLongObj((long)(lsn)->offset);                \
00177         lsnlist = Tcl_NewListObj(myobjc, myobjv);                       \
00178         myobjc = 2;                                                     \
00179         myobjv[0] = Tcl_NewStringObj((s), (int)strlen(s));              \
00180         myobjv[1] = lsnlist;                                            \
00181         thislist = Tcl_NewListObj(myobjc, myobjv);                      \
00182         result = Tcl_ListObjAppendElement(interp, res, thislist);       \
00183         if (result != TCL_OK)                                           \
00184                 goto error;                                             \
00185 } while (0)
00186 
00187 /*
00188  * MAKE_STAT_STRLIST appends a {name string} pair to a result list
00189  * that MUST be called 'res' that is a Tcl_Obj * in the local
00190  * function.  This macro also assumes a label "error" to go to
00191  * in the even of a Tcl error.  For stat functions this will
00192  * typically go before the "free" function to free the stat structure
00193  * returned by DB.
00194  */
00195 #define MAKE_STAT_STRLIST(s,s1) do {                                    \
00196         result = _SetListElem(interp, res, (s), strlen(s),              \
00197             (s1), strlen(s1));                                          \
00198         if (result != TCL_OK)                                           \
00199                 goto error;                                             \
00200 } while (0)
00201 
00202 /*
00203  * FLAG_CHECK checks that the given flag is not set yet.
00204  * If it is, it sets up an error message.
00205  */
00206 #define FLAG_CHECK(flag) do {                                           \
00207         if ((flag) != 0) {                                              \
00208                 Tcl_SetResult(interp,                                   \
00209                     " Only 1 policy can be specified.\n",               \
00210                     TCL_STATIC);                                        \
00211                 result = TCL_ERROR;                                     \
00212                 break;                                                  \
00213         }                                                               \
00214 } while (0)
00215 
00216 /*
00217  * FLAG_CHECK2 checks that the given flag is not set yet or is
00218  * only set to the given allowed value.
00219  * If it is, it sets up an error message.
00220  */
00221 #define FLAG_CHECK2(flag, val) do {                                     \
00222         if (((flag) & ~(val)) != 0) {                                   \
00223                 Tcl_SetResult(interp,                                   \
00224                     " Only 1 policy can be specified.\n",               \
00225                     TCL_STATIC);                                        \
00226                 result = TCL_ERROR;                                     \
00227                 break;                                                  \
00228         }                                                               \
00229 } while (0)
00230 
00231 /*
00232  * IS_HELP checks whether the arg we bombed on is -?, which is a help option.
00233  * If it is, we return TCL_OK (but leave the result set to whatever
00234  * Tcl_GetIndexFromObj says, which lists all the valid options.  Otherwise
00235  * return TCL_ERROR.
00236  */
00237 #define IS_HELP(s)                                              \
00238     (strcmp(Tcl_GetStringFromObj(s,NULL), "-?") == 0) ? TCL_OK : TCL_ERROR
00239 
00240 #include "dbinc_auto/tcl_ext.h"
00241 #endif /* !_DB_TCL_DB_H_ */

Generated on Sun Dec 25 12:14:22 2005 for Berkeley DB 4.4.16 by  doxygen 1.4.2