/* * $Source$ * $Header$ */ /************************************************************************ * * gdb.h * * Includes for the global database facility (gdb) * * Author: Noah Mendelsohn * Copyright: 1986 MIT Project Athena * ************************************************************************/ /* * Note: following include may safely be done redundantly, so it doesn't * matter if caller does it too. We need it for fd_set. */ #include #include #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif #ifndef max #define max(a,b) ((a)>(b)?(a):(b)) #endif #ifndef min #define min(a,b) ((a)<(b)?(a):(b)) #endif #ifndef NFDBITS #define NFDBITS 32 #endif #ifndef howmany #define howmany(x, y) (((x)+((y)-1))/(y)) #endif #ifndef FD_SET #define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) #define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) #define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) #define FD_ZERO(p) bzero(p, sizeof(*(p))) #endif /*----------------------------------------------------------* * * GDB_GIVEUP * * This macro is called with a string argument whenever a * fatal error is encounterd. If you re-define this * macro, you can control the disposition of fatal gdb * errors. * * The gdb library must be recompiled for the change to * take effect. That will have to be fixed sometime. * *----------------------------------------------------------*/ #define GDB_GIVEUP(errormsg) g_givup(errormsg); /*----------------------------------------------------------* * * GDB_ROUNDUP * * Round a number up to the next specified boundary. * *----------------------------------------------------------*/ #define GDB_ROUNDUP(n,b) ((((n)+(b)-1)/(b))*(b)) extern int gdb_Debug; /* debugging flags are */ /* stored here */ extern FILE *gdb_log; /* file descriptor for */ /* logging gdb output */ /* * connection failure indicator * * This variable is used to communicate between gdb_move_data and * g_con_progress without passing an extra parameter through lots * of procedure calls. When set to FALSE, it indicates that the * connection currently being processed has encountered a fatal error * and should be severed. */ extern int gdb_conok; /************************************************************************ * * USER IDENTIFICATION * * gdb_init puts the user's i.d. and hostname as strings here. * ************************************************************************/ extern char *gdb_uname; /* user's string name */ extern char *gdb_host; /* name of local host */ /* goes here */ /************************************************************************ * * * TYPE MANAGEMENT * * Declarations used to control the definition and use of 'types' * as supported by the global database system. Most of the * declarations for 'System Defined Types' will not be of concern * to typical users, with the exception of the type names like * INTEGER_T which are defined below. * * In this implementation, user defined types are added * dynamically during execution by calling the appropriate * functions. The define GDB_MAX_TYPES below sets the maximum * total number of types, including both system and user defined, * which the system can support for any one application. When * GDB_MAX_TYPES is changed, the libary must be re-built. Space * for a two dimensional array, with one word for each property * of each possible type, is allocated statically in the library. * ************************************************************************/ /* * Maximum number of types we can support, including both system and * user defined. */ #define GDB_MAX_TYPES 50 typedef int FIELD_TYPE; /* data needed to repre- */ /* sent a system or user */ /* defined data type */ /* This is actualy just */ /* a row index in the type */ /* definition table */ /*---------------------------------------------------------- * * System defined types * * WARNING: Any changes to these type definitions must be * carefully matched with the initializations in the * gdb_i_stype routine in gdb_stype.c. Mistakes in these * tables may be VERY difficult to debug. Be careful! * *----------------------------------------------------------*/ /* * Primitive types for ingres data */ #define INTEGER_T (0) #define STRING_T (1) #define REAL_T (2) #define DATE_T (3) /* * Structured types */ #define TUPLE_DESCRIPTOR_T (4) #define TUPLE_T (5) #define TUPLE_DATA_T (6) #define RELATION_T (7) /* * Number of system defined types * * This will always be equal to one more than index of last system type */ #define SYSTEM_TYPE_COUNT 8 /*---------------------------------------------------------- * * Type descriptor tables * *----------------------------------------------------------*/ /* * gdb_prop_union * * Each entry in the type definition table is a union of this form, * which allows us to store a choice of an integer, a function * pointer, or a pointer to a character string. */ union gdb_prop_union { int i; /* when we want as an */ /* integer */ int (*f)(); /* as a function pointer */ char *cp; /* character pointer */ }; #define TYPE_PROPERTY_COUNT 8 /* number of properties */ /* for each type*/ /* * Uses of the type properties. Each type has a set of properties. * Some are integers, some are functions. The defines below descrive * respectively the 0'th,1'st, 2'nd, etc. properties of EACH type. * * Note: TYPE_PROPERTY_COUNT (above) must be changed when new properties * are added. For system defined types, bindings for the properties * are done in gdb_i_stype in the gdb_stype.c source file. */ #define LENGTH_PROPERTY 0 /* integer */ #define ALIGNMENT_PROPERTY 1 /* integer */ #define NULL_PROPERTY 2 /* function */ #define CODED_LENGTH_PROPERTY 3 /* function */ #define ENCODE_PROPERTY 4 /* function */ #define DECODE_PROPERTY 5 /* function */ #define FORMAT_PROPERTY 6 /* function */ #define NAME_PROPERTY 7 /* char pointer */ /* * gdb_type_def * * Information to describe a single type */ typedef union gdb_prop_union gdb_type_def[TYPE_PROPERTY_COUNT]; /* * g_type_table * * This is the table where the actual definitions for the types are * kept. */ extern gdb_type_def g_type_table[GDB_MAX_TYPES]; extern int gdb_n_types; /* number of entries in */ /* table */ /*---------------------------------------------------------- * * Macros for accessing properties * *----------------------------------------------------------*/ #define INT_PROPERTY(type, prop) (g_type_table[type][prop].i) #define STR_PROPERTY(type, prop) (g_type_table[type][prop].cp) #define FCN_PROPERTY(type, prop) (*g_type_table[type][prop].f) /************************************************************************ * * STRUCTURED DATA * * Stuff needed to declare and manage TUPLES, TUPLE_DESCRIPTORS * and RELATIONS. * ************************************************************************/ /*---------------------------------------------------------- * * TUPLE_DESCRIPTOR * *----------------------------------------------------------*/ #define GDB_DESC_ID 0x54504400 /* "TPD" */ struct tupld_var { /* the variable length */ /* stuff in a tuple */ /* descriptor*/ char *name; /* string name of field */ FIELD_TYPE type; /* type of this field */ int offset; /* byte offset of this field */ /* relative to first byte of */ /* data (not start of whole */ /* tuple) */ int length; /* Length of the actual data */ /* for this field. Note that */ /* alignment requirements of */ /* following field are NOT */ /* included in this length */ }; struct tupl_desc { long id; /* this should say TPD\0 */ int ref_count; /* when this goes to zero, */ /* the descriptor may really */ /* be reclaimed */ int field_count; /* number of fields in */ /* the tuple*/ int data_len; /* length of the data in */ /* the actual tuple */ int str_len; /* length of the strings */ /* stored off the end of */ /* this descriptor*/ struct tupld_var var[1]; /* one of these for each */ /* field, but the C compiler */ /* won't accept the[] decl, */ /* because it's afraid of */ /* uncertain length*/ }; typedef struct tupl_desc *TUPLE_DESCRIPTOR; /* use this to declare a */ /* tuple descriptor anchor */ #define gdb_descriptor_length(num_flds) (sizeof(struct tupl_desc) + ((num_flds)-1) * sizeof(struct tupld_var)) /*---------------------------------------------------------- * * TUPLE * * tuple_dat is allocated by the create_tuple routine. * * TUPLE may be used in user code to declare a handle * on a tuple. * *----------------------------------------------------------*/ #define GDB_TUP_ID 0x54555000 typedef struct tuple_dat *TUPLE; /* handle on a tuple */ struct tuple_dat { TUPLE next, prev; /* chain pointers when */ /* tuples are linked, as in */ /* a relation. Convention is*/ /* double linked, circular.*/ long id; /* should say TUP\0 */ TUPLE_DESCRIPTOR desc; /* pointer to the descriptor */ char data[1]; /* data goes here, word */ /* aligned. Should be [] */ /* if compiler would allow */ }; /*---------------------------------------------------------- * * RELATION * * rel_dat is allocated by the create_relation * routine. * * RELATION may be used in user code to declare a handle * on a relation. * *----------------------------------------------------------*/ #define GDB_REL_ID 0x52454c00 struct rel_dat { TUPLE first, last; /* chain pointers to tuples */ /* note that first->prev and */ /* last->next are both == */ /* &rel-dat. Maintenance is */ /* simplified by keeping */ /* as the first fields in */ /* both rel_dat and tuple_dat*/ /* a minor non-portability */ long id; /* should contain REL\0 */ TUPLE_DESCRIPTOR desc; /* descriptor for the tuples */ /* in this relation. Should */ /* == that in each tuple */ }; typedef struct rel_dat *RELATION; /* handle on a relation */ /************************************************************************ * * transport LAYER DECLARATIONS * * Declares the state maintenance structures for full duplex * connections with asynchronous transmission capability. Most * users need only know that the type CONNECTION is defined, and * that it may be treated as a pointer for most purposes (i.e. it * is compact, and copying it does not actually copy the connection * state.) * ************************************************************************/ #define GDB_PROTOCOL_VERSION 0x01 /* version of the gdb */ /* protocols that we're */ /* observing */ #define GDB_STREAM_BUFFER_SIZE 4096 /* amount to read in */ /* one chunk from tcp stream*/ #define GDB_PORT htons(9425) /* temporary until we use */ /* services properly */ #define GDB_BIND_RETRY_COUNT 5 /* number of times to */ /* retry a bind before */ /* giving up. Used when */ /* accepting connections */ #define GDB_BIND_RETRY_INTERVAL 10 /* Number of seconds to wait */ /* between attempts to bind */ /* the listening socket */ #define GDB_MAX_CONNECTIONS 25 /* maximum number of */ /* connections that */ /* any one process can */ /* control simultaneously */ /* * Circumvent bug in ACIS 4.2 socket support */ #ifdef ibm032 #define GDB_MAX_SOCK_WRITE 2047 /* rt can't do socket */ /* writes longer than this */ /* gives errno 40*/ #else #define GDB_MAX_SOCK_WRITE 0x00ffffff #endif /*---------------------------------------------------------- * * Declarations for HALF_CONNECTIONS * * Each full duplex connection has associated with it * two simplex half-connections, each of which * has its own queue of pending operations. The * following describes the state of a half-connection. * *----------------------------------------------------------*/ struct half_con_data { /* * these two must be first to match position in OPERATION */ struct oper_data *op_q_first; /* first item in q of pending*/ /* operations for this */ /* half-connection. (chained */ /* circularly to half con, */ /* NOT the con. */ struct oper_data *op_q_last; /* last item in q of pending*/ /* operations for this */ /* half-connection*/ int status; /* values are of type */ /* OPSTATUS. tells whether */ /* transmit/receive is */ /* pending.*/ long flags; /* bit flags */ #define HCON_PROGRESS 0x00000001 /* used by selection */ /* routines to detect */ /* progress */ #define HCON_LISTEN 0x00000002 /* indicates that this is */ /* a special half connection */ /* used only for listenting */ /* to incoming connection */ /* requests */ #define HCON_UNUSED 0x00000004 /* on a one-way connection, */ /* this flag marks an unused */ /* half */ #define HCON_PENDING_LISTEN 0x00000008 /* a queued op on this half */ /* connection is actually */ /* trying to listen */ #define HCON_BUSY 0x00000010 /* we are currently making */ /* progress on this half */ /* connection. Used to */ /* detect re-entrance of */ /* hcon_progress */ int fd; /* main half duplex file */ /* descriptor for this h_conn*/ int oob_fd; /* file descriptor for */ /* out of band signals*/ char *next_byte; /* next byte to send/recv */ int remaining; /* number of bytes remaining */ /* to send/receive */ char *stream_buffer; /* points to a buffer */ /* used to pre-read/write */ /* the stream to avoid */ /* window thrashing */ int stream_buffer_length; /* length of the stream */ /* buffer */ char *stream_buffer_next; /* next byte to read in */ /* stream buffer */ int stream_buffer_remaining; /* number of bytes currently */ /* in use in stream buffer*/ int *accepted_fdp; /* used only for listening */ /* connections. latest */ /* accepted fd is put where*/ /* this points */ int *accepted_len; /* ptr to length of 'from' */ /* data on accept */ }; typedef struct half_con_data *HALF_CONNECTION; /*---------------------------------------------------------- * * Declarations for CONNECTIONS * *----------------------------------------------------------*/ #define GDB_CON_ID 0x434f4e00 /*"CON"*/ struct con_data { long id; /* should contain CON\0 */ int status; /* See definitions below. */ /* Do not confuse with */ /* the status sub-fields of */ /* in and out half-cons. */ int version; /* the version of the */ /* protocol being observed */ /* on this connection */ int errno; /* the real errno gets */ /* copied here if it causes */ /* the connection to die */ int (*oob_fcn)(); /* pointer to function to */ /* call when something */ /* arrives on the out of */ /* band channel */ struct half_con_data in, out; /* states of the inbound */ /* and outbound half */ /* sessions.*/ }; typedef struct con_data *CONNECTION; /* the only externally */ /* visible handle on a */ /* connection*/ /* * Definitions of status fields. * * WARNING: If you change any of the following, there are coordinated * changes to be made in gdb_debug.c */ #define CON_STOPPED 1 /* never started, terminated */ #define CON_UP 2 /* ready to use */ #define CON_STARTING 3 /* trying to start */ #define CON_STOPPING 4 /* trying to stop */ /* * The following are used as keywords when distinguishing input from output * half connections. */ #define CON_INPUT 1 /* this is an input half */ /* session*/ #define CON_OUTPUT 2 /* this is an output half */ /* session*/ /*---------------------------------------------------------- * * gdb_cons * * This is the array of connection control data * structures for gdb. Every connection has its * structure stored here, but they are in no * particular order. Because the connection data * itself cannot be moved (due to possible dangling * pointers), there may be some unused connections * in the middle of this array. gdb_mcons is the * 1 based number of the highest connection which is * actually in use at this time. This is a considerable * optimization for the typical case where very few * are in use, and turnover is low. * * These are externs for globals defined in gdb_lib.h * and included by gdb.c. * *----------------------------------------------------------*/ extern int gdb_mcons; /* one based number of the */ /* highest connection */ /* descriptor we're using */ /* at the moment */ extern int gdb_mfd; /* number of the highest */ /* file descriptor in use */ /* for a connection */ extern struct con_data gdb_cons[GDB_MAX_CONNECTIONS]; /* actual connection data */ /* is stored here */ extern fd_set gdb_crfds, gdb_cwfds, gdb_cefds; /* connection related file */ /* descriptor maps to be */ /* used in select */ fd_set last_crfds, last_cwfds, last_cefds; /* these file desc. bit */ /* masks are set up */ /* for each select call */ /* to include the user */ /* supplied and the */ /* connection related */ /* fd's */ /*---------------------------------------------------------- * * OPERATIONS * *----------------------------------------------------------*/ #define GDB_OP_ID 0x4f505200 struct oper_data { struct oper_data *next, *prev; /* forward and back chain */ long id; /* should contain OPR\0 */ int tag; /* unique identifier for */ /* this operation */ int status; /* current state of this */ /* oaperation*/ int flags; #define OPF_MARKED_COMPLETE 0x00000001 /* operation was already */ /* complete when opsel was */ /* called*/ #define OPF_MARKED_CANCELLED 0x00000002 /* operation was already */ /* cancelled when opsel was */ /* called*/ int result; /* when the operation */ /* completes, this field is */ /* set to reflect its dispos-*/ /* ition. Contents of this */ /* field will depend on the */ /* operation being performed */ HALF_CONNECTION halfcon; /* the half connection on */ /* which this operation is */ /* queued */ /* May be meaningless if not */ /* queued..*/ char *arg; /* pointer to user data */ union fcn { int (*init)(); /* pointer to routine to */ /* call to start this */ /* operation*/ int (*cont)(); /* pointer to function to */ /* be called when this */ /* logical operation */ /* continues*/ } fcn; int (*cancel)(); /* this routine gets called */ /* to handle a cancel request*/ /* this field is normally */ /* set to NULL when the */ /* operation is queued and */ /* updated as required by */ /* the init and cont funcs. */ }; typedef struct oper_data OPERATION_DATA; /* an actual operation */ /* descritor, creator is */ /* responsible for making */ /* sure that memory is not */ /* freed while in use */ typedef OPERATION_DATA *OPERATION; /* a handle on an operation */ /* this is what most */ /* applications will use */ /*---------------------------------------------------------- * * STATES OF AN OPERATION * * These represent the state of an asynchronous, queued * operation. For convenience of the application programmer, * some of these are folded together when queried through the * operation_status routine. In particular, operation status * returns only one of: * * OP_NOT_RUNNING, OP_RUNNING, OP_COMPLETE, or * OP_CANCELLED. * * Any other status is reported as OP_RUNNING. This is * done on the assumption that it makes correct coding * of applications less error-prone, as there are fewer * cases to check, and most of them would not be of * interest anyway. * * Note that OP_CANCELLED may be generated by the system * even when no explicit request for cancellation has been * issued. For example, this may occur when a connection * is severed unexpectedly. * * WARNING: If you change any of the following, be sure * to make the equivalent changes to gdb_debug.c. * * We also define here certain standard values of OP_RESULT, * since some return conventions presume that op_status * and op_result values are orthogonal. * *----------------------------------------------------------*/ #define OP_SUCCESS 0 /* this value is actually */ /* used only in result */ /* fields, but it is */ /* sometimes convenient to */ /* have status and result */ /* have orthogonal values */ #define OP_NOT_STARTED 1 /* this operation has been */ /* initialized but is not on */ /* any connection's queue */ #define OP_QUEUED 2 /* this operation is on */ /* some connection's queue */ /* but it has not yet */ /* reached the head of the q */ #define OP_RUNNING 3 /* op is at head of q trying */ /* to progress */ #define OP_COMPLETE 4 /* operation has run to */ /* completion. result field */ /* is now valid */ #define OP_CANCELLING 5 /* we are in the process of */ /* (trying to) cancel this */ /* operation */ #define OP_CANCELLED 6 /* operation was prematurely */ /* terminated. result field */ /* is NOT valid. */ #define OP_MARKED 7 /* used by op_select_all */ #define OP_REQUEUED 8 /* returned by an init or */ /* continuation routine to */ /* indicate that the */ /* operation has requeued */ /* itself */ #define OP_PREEMPTED 9 /* returned by an init or */ /* continuation routine to */ /* indicate that the op has */ /* preempted itself by */ /* queueing a new operation */ /* ahead of itself */ /*---------------------------------------------------------- * * LIST_OF_OPERATIONS * *----------------------------------------------------------*/ struct oper_list { int count; /* number of operations */ /* in the list */ OPERATION op[1]; /* really op[n], but */ /* structs must have a */ /* definite length */ }; typedef struct oper_list *LIST_OF_OPERATIONS; /* handle on a list */ #define size_of_list_of_operations(n) \ (sizeof(struct oper_list) + (n-1)*sizeof(OPERATION)) /*---------------------------------------------------------- * * gdb_notime * * Pass this to select when doing a poll. * *----------------------------------------------------------*/ extern struct timeval gdb_notime; /************************************************************************ * * CHECKING ROUTINES IMPLEMENTED AS MACROS * ************************************************************************/ extern char g_errstr[150]; /* build emsgs here */ #define GDB_INIT_CHECK g_chk_init(); /* make sure gdb_init */ /* was called */ #define GDB_CHECK_CON(con, where) if ((con)->id != GDB_CON_ID) \ { (void) sprintf(g_errstr, "Invalid connection descriptor passed to \"%s\"\n", where); \ GDB_GIVEUP(g_errstr) } #define GDB_CHECK_TUP(tup, where) if ((tup)->id != GDB_TUP_ID) \ { (void) sprintf(g_errstr, "Invalid tuple passed to \"%s\"\n", where); \ GDB_GIVEUP(g_errstr) } #define GDB_CHECK_TPD(tpd, where) if ((tpd)->id != GDB_DESC_ID) \ { (void) sprintf(g_errstr, "Invalid tuple descriptor passed to \"%s\"\n", where); \ GDB_GIVEUP(g_errstr) } #define GDB_CHECK_REL(rel, where) if ((rel)->id != GDB_REL_ID) \ { (void) sprintf(g_errstr, "Invalid relation passed to \"%s\"\n", where); \ GDB_GIVEUP(g_errstr) } #define GDB_CHECK_OP(op, where) if ((op)->id != GDB_OP_ID) \ { (void) sprintf(g_errstr, "Invalid operation passed to \"%s\"\n", where); \ GDB_GIVEUP(g_errstr) } #define GDB_CHECK_DB(db, where) if (db->id != GDB_DB_ID) \ { (void) sprintf(g_errstr, "Invalid database handle passed to \"%s\"\n", where); \ GDB_GIVEUP(g_errstr) } /************************************************************************ * * TRANSPORT ROUTINES IMPLEMENTED AS MACROS * ************************************************************************/ /*---------------------------------------------------------- * * connection_status * * Returns the status of the indicated connection. * Possible return values are: * * CON_STOPPED never started or terminated * CON_UP currently usable * CON_STARTING transient state on way up * CON_STOPPING transient state on way down * *----------------------------------------------------------*/ #define connection_status(con) ((con)->status) /*---------------------------------------------------------- * * connection_errno * * When a connection dies due to an error on a system * call, the corresponding errno is recorded in the * connection descriptor. This macro returns that value. * *----------------------------------------------------------*/ #define connection_errno(con) ((con)->errno) /************************************************************************ * * SERVER/CLIENT MANAGEMENT * * Definitions used in starting and maintaining communication * between servers and clients (as opposed to peers.) * ************************************************************************/ #define GDB_MAX_SERVER_RETRIES 3 /* maximum number of times */ /* clients will accept */ /* forwarding requests from */ /* a given server */ extern TUPLE_DESCRIPTOR gdb_tosrv; /* descriptor for request */ /* tuples sent to the */ /* server during negotiation*/ extern TUPLE_DESCRIPTOR gdb_fmsrv; /* descriptor for request */ /* tuples sent from the */ /* server during negotiation*/ #define GDB_MAX_SERVER_ID_SIZE 255 /* longest name of a server */ /* that we can handle */ #define GDB_MAX_SERVER_PARMS_SIZE 1023 /* longest parm string we */ /* can exchange between */ /* server and client*/ /*---------------------------------------------------------- * * The following are values returned in the disposition * field of the response tuple to indicate what the * server has decided to do about the connection * request. * *----------------------------------------------------------*/ #define GDB_ACCEPTED 1 #define GDB_REFUSED 2 #define GDB_FORWARDED 3 /*---------------------------------------------------------- * * Global variables inherited by a child from a server * parent. * *----------------------------------------------------------*/ extern TUPLE gdb_client_tuple; /* request tuple sent from */ /* the client */ extern char gdb_sockaddr_of_client[100]; /* this should really be */ /* sockaddr_in, but I don't */ /* want everyone to have */ /* to include all those */ /* big .h files */ extern int gdb_socklen; /* length of above */ /************************************************************************ * * DATABASE MANAGEMENT * * This layer of GDB provides access to the services of a relational * database from anywhere in a GDB network. * ************************************************************************/ /*---------------------------------------------------------- * * GDB_DB_SERVICE * * The name of the service, as found in /etc/services, * for GDB database servers. * *----------------------------------------------------------*/ #define GDB_DB_SERVICE "#9420" /*---------------------------------------------------------- * * DATABASE * * Describes a client's active connection to a database. * *----------------------------------------------------------*/ #define GDB_DB_ID 0x44420000 /* eye catcher */ struct db_struct { long id; /* eye catcher */ CONNECTION connection; /* the GDB connection */ /* used to get at this */ /* database */ int status; /* status of this */ /* database connection */ #define DB_OPEN 1 /* database opened */ /* successfully */ #define DB_CLOSED 2 /* not open */ char *name; /* pointer to string name */ /* of the database, for */ /* debugging */ char *server; /* pointer to the i.d. */ /* of the server, for */ /* debugging */ }; typedef struct db_struct *DATABASE; /*---------------------------------------------------------- * * Return codes from DB operations * *----------------------------------------------------------*/ #define DB_NO_SUCH_OP 3 /*---------------------------------------------------------- * * Parameters which limit sizes of things * *----------------------------------------------------------*/ #define GDB_MAX_QUERY_SIZE 2048 /* length of the longest */ /* substituted query */ /* string we can make */ #define GDB_MAX_QUERY_FIELDS 100 /* maximum number of fields */ /* we can retrieve in one */ /* query */ #define GDB_SIZE_OF_INGRES_TEXT 2001 /* number of chars in */ /* largest ingres text */ /* field */ #define GDB_MAX_RETRIEVED_TEXT_FIELDS 60 /* maximum number of text */ /* type fields we can */ /* retrieve in a single */ /* query. we hold this */ /* down because stack space */ /* is taken for max size of */ /* each during query. */ /*---------------------------------------------------------- * * Return codes from database operations * *----------------------------------------------------------*/ #define DB_PARSE_FAIL (-3) /* couldn't parse */ /* the request string*/ /************************************************************************ * * DATABASE OPERATIONS IMPLEMENTED * AS MACROS * ************************************************************************/ /*---------------------------------------------------------- * * DB_STATUS * *----------------------------------------------------------*/ #define DB_STATUS(dbhandle) ((dbhandle)->status) /************************************************************************ * * STRING MANAGEMENT * * To allow dynamic manipulation of strings in gdb without * excessive memory re-allocation, we define a string as a * counted byte space. Though this space will frequently be used * to store a standard null terminated string, that is not * required. * * Current representation for a string is a pointer followed by * an integer length. A null pointer indicates a null string, in * which case the length is arbitrary. Any other pointer is to * memory which was allocated by db_alloc in which must be free'd * eventually with db_free. * ************************************************************************/ typedef struct str_dat { char *ptr; /* pointer to the data */ int length; /* length of the allocated */ /* memory (not necessarily */ /* length of null-term'd */ /* string stored there) */ } STRING; /*---------------------------------------------------------- * * Macros for manipulating strings. These return * the actual data from the string and the size of * the data space respectively. To get the length of * the null terminated string which might be stored * there, use strlen(STRING_DATA(string)). * *----------------------------------------------------------*/ #define STRING_DATA(str) ((str).ptr) #define MAX_STRING_SIZE(str) ((str).length) /************************************************************************ * * MEMORY ALLOCATION * * db_alloc and db_free are the externally visible names of * the memory allocation services. These actually call the * routines pointed to by the vectors gdb_amv and gdb_fmv, which * default to the supplied routines gdb_am and gdb_fm. Users * may supply their own memory allocation by storing over the * vectors. This may be done prior to calling gdb_init to * insure that all dynamic memory is controlled by the user. * ************************************************************************/ #define db_alloc (*gdb_amv) #define db_free (*gdb_fmv) extern char *gdb_am(); extern int gdb_fm(); extern char *((*gdb_amv)()); extern int (*gdb_fmv)(); /************************************************************************ * * STRUCTURED DATA ROUTINES IMPLEMENTED AS MACROS * ************************************************************************/ /*---------------------------------------------------------- * * ADD_TUPLE_TO_RELATION * *----------------------------------------------------------*/ #define ADD_TUPLE_TO_RELATION(relation, tuple) \ { \ (tuple)->prev = (relation)->last; \ (tuple)->next = (TUPLE)(relation); \ (relation)->last = tuple; \ (tuple)->prev->next = tuple; \ } /*---------------------------------------------------------- * * ADD_TUPLE_AFTER_TUPLE * *----------------------------------------------------------*/ #define ADD_TUPLE_AFTER_TUPLE(relation, tuple, prev_tuple) \ { \ (tuple)->prev = (prev_tuple)->next->prev; \ (tuple)->next = (prev_tuple)->next; \ (tuple)->next->prev = tuple; \ (prev_tuple)->next = tuple; \ } /*---------------------------------------------------------- * * REMOVE_TUPLE_FROM_RELATION * *----------------------------------------------------------*/ #define REMOVE_TUPLE_FROM_RELATION(relation, tuple) \ { \ (tuple)->prev->next = (tuple)->next; \ (tuple)->next->prev = (tuple)->prev; \ } /*---------------------------------------------------------- * * DESCRIPTOR_FROM_TUPLE * *----------------------------------------------------------*/ #define DESCRIPTOR_FROM_TUPLE(tuple) ((tuple)->desc) /*---------------------------------------------------------- * * DESCRIPTOR_FROM_RELATION * *----------------------------------------------------------*/ #define DESCRIPTOR_FROM_RELATION(relation) ((relation)->desc) /*---------------------------------------------------------- * * REFERENCE_TUPLE_DESCRIPTOR * * Bumps the reference count for a tuple descriptor. * Intended only for internal use of GDB. * *----------------------------------------------------------*/ #define REFERENCE_TUPLE_DESCRIPTOR(tpd) (++((tpd)->ref_count)) /*---------------------------------------------------------- * * UNREFERENCE_TUPLE_DESCRIPTOR * * Decrements the reference count for a tuple descriptor. * Intended only for internal use of GDB. Warning: it * is the user's responsibility to use delete_tuple_descriptor * instead of this macro in any situation in which the * reference count might go to zero. * *----------------------------------------------------------*/ #define UNREFERENCE_TUPLE_DESCRIPTOR(tpd) (--((tpd)->ref_count)) /*---------------------------------------------------------- * * FIELD_FROM_TUPLE * *----------------------------------------------------------*/ #define FIELD_FROM_TUPLE(tuple, field_index) \ (((tuple)->data) + (((tuple)->desc)->var[field_index].offset)) /*---------------------------------------------------------- * * FIELD_OFFSET_IN_TUPLE * *----------------------------------------------------------*/ #define FIELD_OFFSET_IN_TUPLE(tuple_descriptor, field_index) \ ((tuple_descriptor)->var[field_index].offset) /*---------------------------------------------------------- * * FIELD_TYPE_IN_TUPLE * *----------------------------------------------------------*/ #define FIELD_TYPE_IN_TUPLE(tuple_descriptor, field_index) \ ((tuple_descriptor)->var[field_index].type) /*---------------------------------------------------------- * * FIRST_TUPLE_IN_RELATION * *----------------------------------------------------------*/ #define FIRST_TUPLE_IN_RELATION(relation) \ (((relation)->first) == (TUPLE)relation ? NULL : (relation)-> first) /*---------------------------------------------------------- * * NEXT_TUPLE_IN_RELATION * *----------------------------------------------------------*/ #define NEXT_TUPLE_IN_RELATION(relation, prev) \ (((prev)->next) == (TUPLE)relation ? NULL : prev->next ) /*---------------------------------------------------------- * * PREV_TUPLE_IN_RELATION * *----------------------------------------------------------*/ #define PREV_TUPLE_IN_RELATION(relation, next) \ (((next)->prev) == (TUPLE) relation ? NULL : next->prev) /************************************************************************ * * TRANSPORT and OPERATION SERVICES IMPLEMENTED AS MACROS * ************************************************************************/ /*---------------------------------------------------------- * * OPERATION_FROM_DATA * * Given OPERATION_DATA, return the corresponding handle * of type OPERATION. Currently, OPERATION is just * implemented as a pointer to OPERATION_DATA. * *----------------------------------------------------------*/ #define OPERATION_FROM_DATA(op_data) \ ((OPERATION)&(op_data)) /*---------------------------------------------------------- * * OP_TAG * * Return the tag for a given operation. * *----------------------------------------------------------*/ #define OP_TAG(operation) ((operation)->tag) /*---------------------------------------------------------- * * OP_STATUS * * Return the status of a given operation. Note that * status describes an operations progress through * execution. It has the same values for all operations. * Result describes the final outcome of an operation. * It's values depend on the particular operation which * was attempted. * *----------------------------------------------------------*/ #define OP_STATUS(operation) ((operation)->status) /*---------------------------------------------------------- * * OP_DONE * * True iff the operation is either OP_COMPLETE or * OP_CANCELLED. * *----------------------------------------------------------*/ #define OP_DONE(op) ((op)->status == OP_COMPLETE || (op)->status == OP_CANCELLED) /*---------------------------------------------------------- * * OP_RESULT * * Return the result of a given operation. Note that * status describes an operations progress through * execution. It has the same values for all operations. * Result describes the final outcome of an operation. * It's values depend on the particular operation which * was attempted. The special result value -1 is used * to indicate an invalid value for result. Generally, * -1 is returned when result is accidently queried at * a time when OP_STATUS != OPERATION_COMPLETE. * *----------------------------------------------------------*/ #define OP_RESULT(operation) ((operation)->result) /************************************************************************ * * Debugging Interfaces * ************************************************************************/ /*---------------------------------------------------------- * * The following operation codes my be passed to * gdb_debug to set special debugging modes of operation. * * Note that most of these are toggles * *----------------------------------------------------------*/ #define GDB_LOG 0x00000001 /* turn on tracing to */ /* log file */ #define GDB_NOFORK 0x00000002 /* don't fork forking */ /* servers */ /************************************************************************ * * Things which have to be at the end because they require * the various types to be defined first. * ************************************************************************/ #ifdef DUMB_7_CHAR_LOADER /*---------------------------------------------------------- * * Long Names for Routines * * External names in Unix must generally be unique * within the first 7 characters or so, at least for * some versions of ld. To account for this without * making all our routine names terribly short and * cryptic, we use the following defines. * *----------------------------------------------------------*/ #define string_alloc gdb_sta #define string_free gdb_stf #define create_tuple_descriptor gdb_ctd #define delete_tuple_descriptor gdb_dtd #define field_index gdb_fi #define create_tuple gdb_ctup #define delete_tuple gdb_dtup #define initialize_tuple gdb_itup #define null_tuple_strings gdb_ntps #define create_relation gdb_crel #define delete_relation gdb_drel #define tuples_in_relation gdb_trel /* * Transport layer */ #define create_operation gdb_crop #define delete_operation gdb_dop #define initialize_operation gdb_inop #define reset_operation gdb_rsop #define cancel_operation gdb_cnop #define create_list_of_operations gdb_clop #define delete_list_of_operations gdb_dlop #define op_select gdb_opsel #define op_select_any gdb_opsel #define op_select_all gdb_aopsel #define con_select gdb_cnsel #define gdb_receive_data gdb_rcdat #define gdb_send_data gdb_sndat #define gdb_start_listening gdb_stl #define start_accepting_client gdb_stac #define gdb_listen gdb_lis /* * Connection management */ #define start_peer_connection gdb_spconn #define sever_connection gdb_svconn #define start_server_connection gdb_stsrv #define create_listening_connection gdb_clc #define start_replying_to_client gdb_strtc #define create_forking_server gdb_cfs /* * Asynchronous operations */ #define start_sending_object gdb_snobj #define start_receiving_object gdb_rcobj #define preempt_and_start_receiving_object gdb_prcobj #define queue_operation gdb_qop #define requeue_operation g_req_op #define complete_operation gdb_cmpo /* * Synchronous operations */ #define send_object gdb_sobj #define receive_object gdb_robj /* * Database operations */ #define access_db gdb_adb #define start_accessing_db gdb_sadb #define perform_db_operation gdb_pdbo #define db_query gdb_dbq #define start_performing_db_operation gdb_spdb #define start_db_query gdb_sdbq #else #define op_select_any op_select #endif DUMB_7_CHAR_LOADER extern char *string_alloc(); extern int string_free(); extern TUPLE_DESCRIPTOR create_tuple_descriptor(); extern int delete_tuple_descriptor(); extern int field_index(); extern TUPLE create_tuple(); extern int delete_tuple(); extern int initialize_tuple(); extern int null_tuple_strings(); extern RELATION create_relation(); extern int delete_relation(); extern OPERATION create_operation(); extern LIST_OF_OPERATIONS create_list_of_operations(); extern OPERATION g_op_newhead(); extern CONNECTION start_peer_connection(); extern CONNECTION sever_connection(); extern CONNECTION start_server_connection(); extern CONNECTION create_listening_connection(); extern CONNECTION create_forking_server(); extern int start_sending_object(); extern int start_receiving_object(); extern int preempt_and_start_receiving_object(); extern int queue_operation(); extern int requeue_operation(); extern int complete_operation(); extern int send_object(); extern int receive_object(); /*---------------------------------------------------------- * * Other routines requiring extern to avoid forward * reference to non integer type functions. * *----------------------------------------------------------*/ extern CONNECTION g_make_con();