Start
[exim.git] / src / src / dbstuff.h
CommitLineData
059ec3d9
PH
1/* $Cambridge: exim/src/src/dbstuff.h,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */
2
3/*************************************************
4* Exim - an Internet mail transport agent *
5*************************************************/
6
7/* Copyright (c) University of Cambridge 1995 - 2004 */
8/* See the file NOTICE for conditions of use and distribution. */
9
10/* This header file contains macro definitions so that a variety of DBM
11libraries can be used by Exim. Nigel Metheringham provided the original set for
12Berkeley DB 1.x in native mode and ndbm. Subsequently, versions for Berkeley DB
132.x and 3.x were added. Later still, support for tdb was added, courtesy of
14James Antill. Most recently, support for native mode gdbm was added, with code
15from Pierre A. Humblet, so Exim could be made to work with Cygwin.
16
17For convenience, the definitions of the structures used in the various hints
18databases are also kept in this file, which is used by the maintenance
19utilities as well as the main Exim binary. */
20
21
22# ifdef USE_TDB
23
24/* ************************* tdb interface ************************ */
25
26#include <tdb.h>
27
28/* Basic DB type */
29#define EXIM_DB TDB_CONTEXT
30
31/* Cursor type: tdb uses the previous "key" in _nextkey() (really it wants
32tdb_traverse to be called) */
33#define EXIM_CURSOR TDB_DATA
34
35/* The datum type used for queries */
36#define EXIM_DATUM TDB_DATA
37
38/* Some text for messages */
39#define EXIM_DBTYPE "tdb"
40
41/* Access functions */
42
43/* EXIM_DBOPEN - sets *dbpp to point to an EXIM_DB, NULL if failed */
44#define EXIM_DBOPEN(name, flags, mode, dbpp) \
45 *(dbpp) = tdb_open(CS name, 0, TDB_DEFAULT, flags, mode)
46
47/* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
48#define EXIM_DBGET(db, key, data) \
49 (data = tdb_fetch(db, key), data.dptr != NULL)
50
51/* EXIM_DBPUT - returns nothing useful, assumes replace mode */
52#define EXIM_DBPUT(db, key, data) \
53 tdb_store(db, key, data, TDB_REPLACE)
54
55/* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
56#define EXIM_DBPUTB(db, key, data) \
57 tdb_store(db, key, data, TDB_INSERT)
58
59/* Returns from EXIM_DBPUTB */
60
61#define EXIM_DBPUTB_OK 0
62#define EXIM_DBPUTB_DUP (-1)
63
64/* EXIM_DBDEL */
65#define EXIM_DBDEL(db, key) tdb_delete(db, key)
66
67/* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
68#define EXIM_DBCREATE_CURSOR(db, cursor) { \
69 *(cursor) = malloc(sizeof(TDB_DATA)); (*(cursor))->dptr = NULL; }
70
71/* EXIM_DBSCAN - This is complicated because we have to free the last datum
72free() must not die when passed NULL */
73#define EXIM_DBSCAN(db, key, data, first, cursor) \
74 (key = (first ? tdb_firstkey(db) : tdb_nextkey(db, *(cursor))), \
75 free((cursor)->dptr), *(cursor) = key, \
76 key.dptr != NULL)
77
78/* EXIM_DBDELETE_CURSOR - terminate scanning operation. */
79#define EXIM_DBDELETE_CURSOR(cursor) free(cursor)
80
81/* EXIM_DBCLOSE */
82#define EXIM_DBCLOSE(db) tdb_close(db)
83
84/* Datum access types - these are intended to be assignable */
85
86#define EXIM_DATUM_SIZE(datum) (datum).dsize
87#define EXIM_DATUM_DATA(datum) (datum).dptr
88
89/* Free the stuff inside the datum. */
90
91#define EXIM_DATUM_FREE(datum) (free((datum).dptr), (datum).dptr = NULL)
92
93/* No initialization is needed. */
94
95#define EXIM_DATUM_INIT(datum)
96
97
98
99/********************* Berkeley db native definitions **********************/
100
101#elif defined USE_DB
102
103#include <db.h>
104
105
106/* We can distinguish between versions 1.x and 2.x/3.x by looking for a
107definition of DB_VERSION_STRING, which is present in versions 2.x onwards. */
108
109#ifdef DB_VERSION_STRING
110
111/* The API changed (again!) between the 2.x and 3.x versions */
112
113#if DB_VERSION_MAJOR >= 3
114
115/***************** Berkeley db 3.x/4.x native definitions ******************/
116
117/* Basic DB type */
118#define EXIM_DB DB
119
120/* Cursor type, for scanning */
121#define EXIM_CURSOR DBC
122
123/* The datum type used for queries */
124#define EXIM_DATUM DBT
125
126/* Some text for messages */
127#define EXIM_DBTYPE "db (v3/4)"
128
129/* Access functions */
130
131/* EXIM_DBOPEN - sets *dbpp to point to an EXIM_DB, NULL if failed. The
132API changed for DB 4.1. */
133
134#if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
135#define EXIM_DBOPEN(name, flags, mode, dbpp) \
136 if (db_create(dbpp, NULL, 0) != 0 || \
137 ((*dbpp)->set_errcall(*dbpp, dbfn_bdb_error_callback), \
138 (*dbpp)->open(*dbpp, NULL, CS name, NULL, \
139 ((flags) == O_RDONLY)? DB_UNKNOWN : DB_HASH, \
140 ((flags) == O_RDONLY)? DB_RDONLY : DB_CREATE, \
141 mode)) != 0) *(dbpp) = NULL
142#else
143#define EXIM_DBOPEN(name, flags, mode, dbpp) \
144 if (db_create(dbpp, NULL, 0) != 0 || \
145 ((*dbpp)->set_errcall(*dbpp, dbfn_bdb_error_callback), \
146 (*dbpp)->open(*dbpp, CS name, NULL, \
147 ((flags) == O_RDONLY)? DB_UNKNOWN : DB_HASH, \
148 ((flags) == O_RDONLY)? DB_RDONLY : DB_CREATE, \
149 mode)) != 0) *(dbpp) = NULL
150#endif
151
152/* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
153#define EXIM_DBGET(db, key, data) \
154 ((db)->get(db, NULL, &key, &data, 0) == 0)
155
156/* EXIM_DBPUT - returns nothing useful, assumes replace mode */
157#define EXIM_DBPUT(db, key, data) \
158 (db)->put(db, NULL, &key, &data, 0)
159
160/* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
161#define EXIM_DBPUTB(db, key, data) \
162 (db)->put(db, NULL, &key, &data, DB_NOOVERWRITE)
163
164/* Return values from EXIM_DBPUTB */
165
166#define EXIM_DBPUTB_OK 0
167#define EXIM_DBPUTB_DUP DB_KEYEXIST
168
169/* EXIM_DBDEL */
170#define EXIM_DBDEL(db, key) (db)->del(db, NULL, &key, 0)
171
172/* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
173
174#define EXIM_DBCREATE_CURSOR(db, cursor) \
175 (db)->cursor(db, NULL, cursor, 0)
176
177/* EXIM_DBSCAN - returns TRUE if data is returned, FALSE at end */
178#define EXIM_DBSCAN(db, key, data, first, cursor) \
179 ((cursor)->c_get(cursor, &key, &data, \
180 (first? DB_FIRST : DB_NEXT)) == 0)
181
182/* EXIM_DBDELETE_CURSOR - terminate scanning operation */
183#define EXIM_DBDELETE_CURSOR(cursor) \
184 (cursor)->c_close(cursor)
185
186/* EXIM_DBCLOSE */
187#define EXIM_DBCLOSE(db) (db)->close(db, 0)
188
189/* Datum access types - these are intended to be assignable. */
190
191#define EXIM_DATUM_SIZE(datum) (datum).size
192#define EXIM_DATUM_DATA(datum) (datum).data
193
194/* The whole datum structure contains other fields that must be cleared
195before use, but we don't have to free anything after reading data. */
196
197#define EXIM_DATUM_INIT(datum) memset(&datum, 0, sizeof(datum))
198#define EXIM_DATUM_FREE(datum)
199
200
201#else /* DB_VERSION_MAJOR >= 3 */
202
203/******************* Berkeley db 2.x native definitions ********************/
204
205/* Basic DB type */
206#define EXIM_DB DB
207
208/* Cursor type, for scanning */
209#define EXIM_CURSOR DBC
210
211/* The datum type used for queries */
212#define EXIM_DATUM DBT
213
214/* Some text for messages */
215#define EXIM_DBTYPE "db (v2)"
216
217/* Access functions */
218
219/* EXIM_DBOPEN - sets *dbpp to point to an EXIM_DB, NULL if failed */
220#define EXIM_DBOPEN(name, flags, mode, dbpp) \
221 if ((errno = db_open(CS name, DB_HASH, \
222 ((flags) == O_RDONLY)? DB_RDONLY : DB_CREATE, \
223 mode, NULL, NULL, dbpp)) != 0) *(dbpp) = NULL
224
225/* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
226#define EXIM_DBGET(db, key, data) \
227 ((db)->get(db, NULL, &key, &data, 0) == 0)
228
229/* EXIM_DBPUT - returns nothing useful, assumes replace mode */
230#define EXIM_DBPUT(db, key, data) \
231 (db)->put(db, NULL, &key, &data, 0)
232
233/* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
234#define EXIM_DBPUTB(db, key, data) \
235 (db)->put(db, NULL, &key, &data, DB_NOOVERWRITE)
236
237/* Return values from EXIM_DBPUTB */
238
239#define EXIM_DBPUTB_OK 0
240#define EXIM_DBPUTB_DUP DB_KEYEXIST
241
242/* EXIM_DBDEL */
243#define EXIM_DBDEL(db, key) (db)->del(db, NULL, &key, 0)
244
245/* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
246
247/* The API of this function was changed between releases 2.4.14 and 2.7.3. I do
248not know exactly where the change happened, but the Change Log for 2.5.9 lists
249the new option that is available, so I guess that it happened at 2.5.x. */
250
251#if DB_VERSION_MINOR >= 5
252#define EXIM_DBCREATE_CURSOR(db, cursor) \
253 (db)->cursor(db, NULL, cursor, 0)
254#else
255#define EXIM_DBCREATE_CURSOR(db, cursor) \
256 (db)->cursor(db, NULL, cursor)
257#endif
258
259/* EXIM_DBSCAN - returns TRUE if data is returned, FALSE at end */
260#define EXIM_DBSCAN(db, key, data, first, cursor) \
261 ((cursor)->c_get(cursor, &key, &data, \
262 (first? DB_FIRST : DB_NEXT)) == 0)
263
264/* EXIM_DBDELETE_CURSOR - terminate scanning operation */
265#define EXIM_DBDELETE_CURSOR(cursor) \
266 (cursor)->c_close(cursor)
267
268/* EXIM_DBCLOSE */
269#define EXIM_DBCLOSE(db) (db)->close(db, 0)
270
271/* Datum access types - these are intended to be assignable. */
272
273#define EXIM_DATUM_SIZE(datum) (datum).size
274#define EXIM_DATUM_DATA(datum) (datum).data
275
276/* The whole datum structure contains other fields that must be cleared
277before use, but we don't have to free anything after reading data. */
278
279#define EXIM_DATUM_INIT(datum) memset(&datum, 0, sizeof(datum))
280#define EXIM_DATUM_FREE(datum)
281
282#endif /* DB_VERSION_MAJOR >= 3 */
283
284
285/* If DB_VERSION_TYPE is not defined, we have version 1.x */
286
287#else /* DB_VERSION_TYPE */
288
289/******************* Berkeley db 1.x native definitions ********************/
290
291/* Basic DB type */
292#define EXIM_DB DB
293
294/* Cursor type, not used with DB 1.x: just set up a dummy */
295#define EXIM_CURSOR int
296
297/* The datum type used for queries */
298#define EXIM_DATUM DBT
299
300/* Some text for messages */
301#define EXIM_DBTYPE "db (v1)"
302
303/* Access functions */
304
305/* EXIM_DBOPEN - sets *dbpp to point to an EXIM_DB, NULL if failed */
306#define EXIM_DBOPEN(name, flags, mode, dbpp) \
307 *(dbpp) = dbopen(CS name, flags, mode, DB_HASH, NULL)
308
309/* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
310#define EXIM_DBGET(db, key, data) \
311 ((db)->get(db, &key, &data, 0) == 0)
312
313/* EXIM_DBPUT - returns nothing useful, assumes replace mode */
314#define EXIM_DBPUT(db, key, data) \
315 (db)->put(db, &key, &data, 0)
316
317/* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
318#define EXIM_DBPUTB(db, key, data) \
319 (db)->put(db, &key, &data, R_NOOVERWRITE)
320
321/* Returns from EXIM_DBPUTB */
322
323#define EXIM_DBPUTB_OK 0
324#define EXIM_DBPUTB_DUP 1
325
326/* EXIM_DBDEL */
327#define EXIM_DBDEL(db, key) (db)->del(db, &key, 0)
328
329/* EXIM_DBCREATE_CURSOR - initialize for scanning operation (null) */
330#define EXIM_DBCREATE_CURSOR(db, cursor) {}
331
332/* EXIM_DBSCAN - returns TRUE if data is returned, FALSE at end */
333#define EXIM_DBSCAN(db, key, data, first, cursor) \
334 ((db)->seq(db, &key, &data, (first? R_FIRST : 0)) == 0)
335
336/* EXIM_DBDELETE_CURSOR - terminate scanning operation (null). Make it
337refer to cursor, to keep picky compilers happy. */
338#define EXIM_DBDELETE_CURSOR(cursor) { cursor = cursor; }
339
340/* EXIM_DBCLOSE */
341#define EXIM_DBCLOSE(db) (db)->close(db)
342
343/* Datum access types - these are intended to be assignable */
344
345#define EXIM_DATUM_SIZE(datum) (datum).size
346#define EXIM_DATUM_DATA(datum) (datum).data
347
348/* There's no clearing required before use, and we don't have to free anything
349after reading data. */
350
351#define EXIM_DATUM_INIT(datum)
352#define EXIM_DATUM_FREE(datum)
353
354#endif /* DB_VERSION_STRING */
355
356
357
358/********************* gdbm interface definitions **********************/
359
360#elif defined USE_GDBM
361
362#include <gdbm.h>
363
364/* Basic DB type */
365typedef struct {
366 GDBM_FILE gdbm; /* Database */
367 datum lkey; /* Last key, for scans */
368} EXIM_DB;
369
370/* Cursor type, not used with gdbm: just set up a dummy */
371#define EXIM_CURSOR int
372
373/* The datum type used for queries */
374#define EXIM_DATUM datum
375
376/* Some text for messages */
377
378#define EXIM_DBTYPE "gdbm"
379
380/* Access functions */
381
382/* EXIM_DBOPEN - returns a EXIM_DB *, NULL if failed */
383#define EXIM_DBOPEN(name, flags, mode, dbpp) \
384 { (*(dbpp)) = (EXIM_DB *) malloc(sizeof(EXIM_DB));\
385 if (*(dbpp) != NULL) { \
386 (*(dbpp))->lkey.dptr = NULL;\
387 (*(dbpp))->gdbm = gdbm_open(CS name, 0, (((flags) & O_CREAT))?GDBM_WRCREAT:(((flags) & (O_RDWR|O_WRONLY))?GDBM_WRITER:GDBM_READER), mode, 0);\
388 if ((*(dbpp))->gdbm == NULL) {\
389 free(*(dbpp));\
390 *(dbpp) = NULL;\
391 }\
392 }\
393 }
394
395/* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
396#define EXIM_DBGET(db, key, data) \
397 (data = gdbm_fetch(db->gdbm, key), data.dptr != NULL)
398
399/* EXIM_DBPUT - returns nothing useful, assumes replace mode */
400#define EXIM_DBPUT(db, key, data) \
401 gdbm_store(db->gdbm, key, data, GDBM_REPLACE)
402
403/* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
404#define EXIM_DBPUTB(db, key, data) \
405 gdbm_store(db->gdbm, key, data, GDBM_INSERT)
406
407/* Returns from EXIM_DBPUTB */
408
409#define EXIM_DBPUTB_OK 0
410#define EXIM_DBPUTB_DUP 1
411
412/* EXIM_DBDEL */
413#define EXIM_DBDEL(db, key) gdbm_delete(db->gdbm, key)
414
415/* EXIM_DBCREATE_CURSOR - initialize for scanning operation (null) */
416#define EXIM_DBCREATE_CURSOR(db, cursor) {}
417
418/* EXIM_DBSCAN */
419#define EXIM_DBSCAN(db, key, data, first, cursor) \
420 ( key = ((first)? gdbm_firstkey(db->gdbm) : gdbm_nextkey(db->gdbm, db->lkey)), \
421 (((db)->lkey.dptr != NULL)? (free((db)->lkey.dptr),1) : 1),\
422 db->lkey = key, key.dptr != NULL)
423
424/* EXIM_DBDELETE_CURSOR - terminate scanning operation (null). Make it
425refer to cursor, to keep picky compilers happy. */
426#define EXIM_DBDELETE_CURSOR(cursor) { cursor = cursor; }
427
428/* EXIM_DBCLOSE */
429#define EXIM_DBCLOSE(db) \
430{ gdbm_close((db)->gdbm);\
431 if ((db)->lkey.dptr != NULL) free((db)->lkey.dptr);\
432 free(db); }
433
434/* Datum access types - these are intended to be assignable */
435
436#define EXIM_DATUM_SIZE(datum) (datum).dsize
437#define EXIM_DATUM_DATA(datum) (datum).dptr
438
439/* There's no clearing required before use, but we have to free the dptr
440after reading data. */
441
442#define EXIM_DATUM_INIT(datum)
443#define EXIM_DATUM_FREE(datum) free(datum.dptr)
444
445#else /* USE_GDBM */
446
447
448/* If none of USE_DB, USG_GDBM, or USE_TDB are set, the default is the NDBM
449interface */
450
451
452/********************* ndbm interface definitions **********************/
453
454#include <ndbm.h>
455
456/* Basic DB type */
457#define EXIM_DB DBM
458
459/* Cursor type, not used with ndbm: just set up a dummy */
460#define EXIM_CURSOR int
461
462/* The datum type used for queries */
463#define EXIM_DATUM datum
464
465/* Some text for messages */
466
467#define EXIM_DBTYPE "ndbm"
468
469/* Access functions */
470
471/* EXIM_DBOPEN - returns a EXIM_DB *, NULL if failed */
472#define EXIM_DBOPEN(name, flags, mode, dbpp) \
473 *(dbpp) = dbm_open(CS name, flags, mode)
474
475/* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
476#define EXIM_DBGET(db, key, data) \
477 (data = dbm_fetch(db, key), data.dptr != NULL)
478
479/* EXIM_DBPUT - returns nothing useful, assumes replace mode */
480#define EXIM_DBPUT(db, key, data) \
481 dbm_store(db, key, data, DBM_REPLACE)
482
483/* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
484#define EXIM_DBPUTB(db, key, data) \
485 dbm_store(db, key, data, DBM_INSERT)
486
487/* Returns from EXIM_DBPUTB */
488
489#define EXIM_DBPUTB_OK 0
490#define EXIM_DBPUTB_DUP 1
491
492/* EXIM_DBDEL */
493#define EXIM_DBDEL(db, key) dbm_delete(db, key)
494
495/* EXIM_DBCREATE_CURSOR - initialize for scanning operation (null) */
496#define EXIM_DBCREATE_CURSOR(db, cursor) {}
497
498/* EXIM_DBSCAN */
499#define EXIM_DBSCAN(db, key, data, first, cursor) \
500 (key = (first? dbm_firstkey(db) : dbm_nextkey(db)), key.dptr != NULL)
501
502/* EXIM_DBDELETE_CURSOR - terminate scanning operation (null). Make it
503refer to cursor, to keep picky compilers happy. */
504#define EXIM_DBDELETE_CURSOR(cursor) { cursor = cursor; }
505
506/* EXIM_DBCLOSE */
507#define EXIM_DBCLOSE(db) dbm_close(db)
508
509/* Datum access types - these are intended to be assignable */
510
511#define EXIM_DATUM_SIZE(datum) (datum).dsize
512#define EXIM_DATUM_DATA(datum) (datum).dptr
513
514/* There's no clearing required before use, and we don't have to free anything
515after reading data. */
516
517#define EXIM_DATUM_INIT(datum)
518#define EXIM_DATUM_FREE(datum)
519
520#endif /* USE_GDBM */
521
522/********************* End of dbm library definitions **********************/
523
524
525/* Structure for carrying around an open DBM file, and an open locking file
526that relates to it. */
527
528typedef struct {
529 EXIM_DB *dbptr;
530 int lockfd;
531} open_db;
532
533
534/* Structures for records stored in exim database dbm files. They all
535start with the same fields, described in the generic type. */
536
537
538typedef struct {
539 time_t time_stamp; /* Timestamp of writing */
540} dbdata_generic;
541
542
543/* This structure keeps track of retry information for a host or a local
544address. */
545
546typedef struct {
547 time_t time_stamp;
548 /*************/
549 time_t first_failed; /* Time of first failure */
550 time_t last_try; /* Time of last try */
551 time_t next_try; /* Time of next try */
552 BOOL expired; /* Retry time has expired */
553 int basic_errno; /* Errno of last failure */
554 int more_errno; /* Additional information */
555 uschar text[1]; /* Text message for last failure */
556} dbdata_retry;
557
558/* These structures keep track of addresses that have had callout verification
559performed on them. There are two groups of records:
560
5611. keyed by localpart@domain -
562 Full address was tested and record holds result
563
5642. keyed by domain -
565 Domain response upto MAIL FROM:<>, postmaster, random local part;
566
567If a record exists, the result field is either ccache_accept or ccache_reject.
568The other fields, however, (which are only relevant to domain records) may also
569contain ccache_unknown if that particular test has not been done.
570
571Originally, there was only one structure, used for both types. However, it got
572expanded for domain records, so it got split. To make it possible for Exim to
573handle the old type of record, we retain the old definition. The different
574kinds of record can be distinguised by their different lengths. */
575
576typedef struct {
577 time_t time_stamp;
578 /*************/
579 int result;
580 int postmaster_result; /* Postmaster is accepted */
581 int random_result; /* Random local part was accepted */
582} dbdata_callout_cache_obs;
583
584typedef struct {
585 time_t time_stamp; /* Timestamp of last address check */
586 /*************/
587 int result; /* accept or reject */
588} dbdata_callout_cache_address;
589
590/* For this new layout, we put the additional fields (the timestamps)
591last so that if somebody reverts to an older Exim, the new records will
592still make sense because they match the old layout. */
593
594typedef struct {
595 time_t time_stamp; /* Time stamp of last connection */
596 /*************/
597 int result; /* Domain reject or accept */
598 int postmaster_result; /* Postmaster result */
599 int random_result; /* Random result */
600 time_t postmaster_stamp; /* Timestamp of postmaster check */
601 time_t random_stamp; /* Timestamp of random check */
602} dbdata_callout_cache;
603
604/* This structure keeps track of messages that are waiting for a particular
605host for a particular transport. */
606
607typedef struct {
608 time_t time_stamp;
609 /*************/
610 int count; /* Count of message ids */
611 int sequence; /* Sequence for continued records */
612 uschar text[1]; /* One long character string */
613} dbdata_wait;
614
615
616/* The contents of the "misc" database are a mixture of different kinds of
617record, as defined below. The keys used for a specific type all start with a
618given string such as "etrn-" or "host-serialize-". */
619
620
621/* This structure records a connection to a particular host, for the
622purpose of serializing access to certain hosts. For possible future extension,
623a field is defined for holding the count of connections, but it is not
624at present in use. The same structure is used for recording a running ETRN
625process. */
626
627typedef struct {
628 time_t time_stamp;
629 /*************/
630 int count; /* Reserved for possible connection count */
631} dbdata_serialize;
632
633
634/* End of dbstuff.h */