Project

General

Profile

Statistics
| Branch: | Tag: | Revision:

gdp / gdp / gdp_priv.h @ master

History | View | Annotate | Download (33 KB)

1
/* vim: set ai sw=4 sts=4 ts=4 : */
2

    
3
/*
4
**  ----- BEGIN LICENSE BLOCK -----
5
**        GDP: Global Data Plane Support Library
6
**        From the Ubiquitous Swarm Lab, 490 Cory Hall, U.C. Berkeley.
7
**
8
**        Copyright (c) 2015-2019, Regents of the University of California.
9
**        All rights reserved.
10
**
11
**        Permission is hereby granted, without written agreement and without
12
**        license or royalty fees, to use, copy, modify, and distribute this
13
**        software and its documentation for any purpose, provided that the above
14
**        copyright notice and the following two paragraphs appear in all copies
15
**        of this software.
16
**
17
**        IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
18
**        SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST
19
**        PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
20
**        EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21
**
22
**        REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
23
**        LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24
**        FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION,
25
**        IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO
26
**        OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
27
**        OR MODIFICATIONS.
28
**  ----- END LICENSE BLOCK -----
29
*/
30

    
31
/*
32
**        These headers are not intended for external use.
33
*/
34

    
35
#ifndef _GDP_PRIV_H_
36
#define _GDP_PRIV_H_
37

    
38
#include <ep/ep.h>
39
#include <ep/ep_assert.h>
40
#include <ep/ep_crypto.h>
41
#include <ep/ep_thr.h>
42

    
43
#include <event2/buffer.h>
44

    
45
#include "gdp.pb-c.h"
46

    
47
#if EP_OSCF_USE_VALGRIND
48
# include <valgrind/helgrind.h>
49
#else
50
# define VALGRIND_HG_CLEAN_MEMORY(a, b)
51
#endif
52

    
53
#ifndef GDP_COMPAT_OLD_LOG_NAMES
54
# define GDP_COMPAT_OLD_LOG_NAMES                1        // assume old style SHA(human) names
55
#endif
56
#ifndef GDP_COMPAT_OLD_PUBKEYS
57
# define GDP_COMPAT_OLD_PUBKEYS                        1        // try old public key metadata name
58
#endif
59
#ifndef GDP_DEFAULT_CREATION_SERVICE
60
//# define GDP_DEFAULT_CREATION_SERVICE        "edu.berkeley.eecs.gdp.service.creation"
61
#endif
62
#ifndef GDP_DEFAULT_DATA_ROOT
63
# define GDP_DEFAULT_DATA_ROOT                        "/var/swarm/gdp"
64
#endif
65

    
66
typedef struct gdp_chan                gdp_chan_t;                // should be in gdp_chan.h?
67
typedef uint16_t                        gdp_seqno_t;        // should be in gdp_chan.h?
68
typedef struct gdp_req                gdp_req_t;
69
typedef struct gdp_gob                gdp_gob_t;
70
typedef struct gdp_gin                gdp_gin_t;
71
typedef struct gdp_pdu                gdp_pdu_t;                // should be in gdp_pdu.h?
72
typedef GdpMessage                        gdp_msg_t;
73
typedef GdpMsgCode                        gdp_cmd_t;
74
typedef struct event_base        event_base_t;
75
TAILQ_HEAD(gev_list, gdp_event);
76

    
77
#include "gdp_pdu.h"
78

    
79
extern EP_THR                _GdpIoEventLoopThread;
80
extern event_base_t        *_GdpIoEventBase;        // for all I/O events
81
extern gdp_chan_t        *_GdpChannel;                // our primary app-level protocol port
82
extern gdp_name_t        _GdpMyRoutingName;        // source name for PDUs
83
extern int                        _GdpInitState;                // initialization state, see below
84

    
85
#define GDP_INIT_NONE                0        // uninitialized
86
#define GDP_INIT_PHASE_0        10        // phase 0 complete
87
#define GDP_INIT_LIB                20        // gdp_init_lib done
88
#define GDP_INIT_COMPLETE        99        // all initialization complete
89

    
90
#define GDP_CHECK_INITIALIZED                                                                                        \
91
                                        ((_GdpInitState >= GDP_INIT_COMPLETE)                                \
92
                                                                                ? EP_STAT_OK                                        \
93
                                                                                : gdp_init(NULL))
94

    
95
#ifndef GDP_OPT_EXTENDED_CACHE_CHECK                //XXX DEBUG TEMPORARY
96
# define GDP_OPT_EXTENDED_CACHE_CHECK        1        //XXX DEBUG TEMPORARY
97
#endif                                                                                //XXX DEBUG TEMPORARY
98
#if GDP_OPT_EXTENDED_CACHE_CHECK
99
#define IF_LIST_CHECK_OK(list, item, chain, type)                                                \
100
        type *_x_ ## item;                                                                                                        \
101
        if (ep_dbg_test(Dbg, 10))                                                                                        \
102
        {                                                                                                                                        \
103
                LIST_FOREACH(_x_ ## item, list, chain)                                                        \
104
                {                                                                                                                                \
105
                        EP_ASSERT_ELSE(_x_ ## item != item, break);                                        \
106
                }                                                                                                                                \
107
        }                                                                                                                                        \
108
        else                                                                                                                                \
109
                _x_ ## item = NULL;                                                                                                \
110
        if (_x_ ## item == NULL)
111
#else
112
#define IF_LIST_CHECK_OK(list, item, chain, type)                                                \
113
        if (true)
114
#endif
115

    
116
// helper to do sanity checks
117
#define GDP_MSG_CHECK(pdu, recovery)                                                                                \
118
                        EP_ASSERT_ELSE(pdu != NULL, recovery);                                                        \
119
                        EP_ASSERT_ELSE(pdu->msg != NULL, recovery);
120

    
121
// declare the type of the gdp_req linked list (used multiple places)
122
LIST_HEAD(req_head, gdp_req);
123

    
124

    
125
/*
126
**  Some generic constants
127
*/
128

    
129
// "dump" routine detail parameters (XXX should these be public?)
130
#define GDP_PR_PRETTY                0                // suitable for end users
131
#define GDP_PR_BASIC                8                // basic debug information
132
#define GDP_PR_DETAILED                16                // detailed information
133
#define GDP_PR_RECURSE                32                // recurse into substructures
134
                                                                        // add N to recurse N+1 levels deep
135

    
136

    
137
/*
138
**  Basic data types
139
*/
140

    
141
// hashes
142
//struct gdp_hash
143
//{
144
//        int                                        alg;                // hash algorithm to use
145
//        gdp_buf_t                        *buf;                // the hash value itself
146
//};
147
gdp_buf_t                *_gdp_hash_getbuf(gdp_hash_t *hash);
148

    
149

    
150
// signatures
151
//struct gdp_sig
152
//{
153
//        XXX;
154
//};
155
gdp_buf_t                *_gdp_sig_getbuf(gdp_sig_t *sig);
156

    
157

    
158
/*
159
**         Datums
160
**                These are the underlying data unit that is passed through a GOB.
161
**
162
**                The timestamp here is the database commit timestamp; any sample
163
**                timestamp must be added by the sensor itself as part of the data.
164
**
165
**                dhash = H(dbuf)
166
**                datum hash = H(recno || ts || prevhash || dhash)
167
**                prevhash = hash of previous datum
168
*/
169

    
170
struct gdp_datum
171
{
172
        EP_THR_MUTEX                mutex;                        // locking mutex (mostly for dbuf)
173
        struct gdp_datum        *next;                        // next in free list
174
        uint32_t                        flags;                        // see below
175
        gdp_recno_t                        recno;                        // the record number
176
        EP_TIME_SPEC                ts;                                // commit timestamp
177
        gdp_buf_t                        *dbuf;                        // data buffer
178
        gdp_sig_t                        *sig;                        // signature (may be NULL)
179
        gdp_hash_t                        *prevhash;                // hash of previous datum
180
};
181

    
182
#define GDP_DF_INUSE                0x00000001        // datum is in use
183
#define GDP_DF_GOODSIG                0x00000002        // signature is good
184

    
185
#define GDP_DATUM_ISGOOD(datum)                                                                                        \
186
                                ((datum) != NULL &&                                                                                \
187
                                 (datum)->dbuf != NULL &&                                                                        \
188
                                 EP_UT_BITSET(GDP_DF_INUSE, (datum)->flags))
189

    
190
gdp_datum_t                *_gdp_datum_new_gob(        // generate new datum from GOB
191
                                                void);
192

    
193
gdp_datum_t                *gdp_datum_dup(                        // duplicate a datum
194
                                                const gdp_datum_t *datum);
195

    
196
void                        _gdp_datum_dump(                // dump data record (for debugging)
197
                                                const gdp_datum_t *datum,        // message to print
198
                                                FILE *fp);                                        // file to print it to
199

    
200
gdp_hash_t                *_gdp_datum_hash(                // compute hash of datum
201
                                                gdp_datum_t *datum,
202
                                                gdp_gob_t *gob);                        // enclosing GOB
203

    
204
bool                        _gdp_datum_hash_equal(        // check that a hash matches the datum
205
                                                gdp_datum_t *datum,                        // the datum to check
206
                                                gdp_gob_t *gob,                                // enclosing GOB
207
                                                const gdp_hash_t *hash);        // the hash to check against
208

    
209
EP_STAT                        _gdp_datum_digest(                // add datum to existing digest
210
                                                gdp_datum_t *datum,                        // the datum to include
211
                                                EP_CRYPTO_MD *md);                        // the existing digest
212

    
213
void                        _gdp_datum_to_pb(                // convert datum to protobuf form
214
                                                const gdp_datum_t *datum,
215
                                                GdpMessage *msg,
216
                                                GdpDatum *pb);
217

    
218
void                        _gdp_datum_from_pb(                // convert protobuf form to datum
219
                                                gdp_datum_t *datum,
220
                                                const GdpDatum *pb,
221
                                                const GdpSignature *sig);
222

    
223
EP_STAT                        _gdp_datum_sign(                // sign a datum
224
                                                gdp_datum_t *datum,                        // the datum to sign
225
                                                gdp_gob_t *gob);                        // the object storing it
226

    
227
EP_STAT                        _gdp_datum_vrfy_gob(        // verify a datum signature
228
                                                gdp_datum_t *datum,
229
                                                gdp_gob_t *gob);
230

    
231
void                        _gdp_timestamp_from_pb(        // convert protobuf form to EP_TIME_SPEC
232
                                                EP_TIME_SPEC *ts,
233
                                                const GdpTimestamp *pbd);
234

    
235

    
236

    
237
/*
238
**  GDP Objects
239
**
240
**                There are two data structures around GOBs.
241
**
242
**                The gdp_gin is an open handle on a GDP Object Instance.
243
**                Client-side subscriptions are associated with this so
244
**                that gdp_event_next can deliver the correct information.
245
**                Read and append filters are also considered "external".
246
**                It is not used at all by gdplogd.
247
**                Mostly implemented in gdp_api.c.
248
**
249
**                The gdp_gob is the internal representation of a potentially
250
**                shared GOB.  This is what is in the cache.
251
**                It has the request list representing
252
**                server-side subscriptions.  It is used both by the
253
**                GDP library and by gdplogd.  Mostly implemented in
254
**                gdp_gob_ops.c.
255
*/
256

    
257
SLIST_HEAD(gcl_head, gdp_gcl);
258

    
259

    
260
// application per-open-instance information (unused in gdplogd)
261
struct gdp_gin
262
{
263
        EP_THR_MUTEX                mutex;                        // lock on this data structure
264
        gdp_gob_t                        *gob;                        // internal GDP object
265
        SLIST_ENTRY(gdp_gin)
266
                                                next;                        // chain for freelist
267
        uint16_t                        flags;                        // see below
268
        gdp_iomode_t                iomode;                        // read only or append only
269
        void                                (*closefunc)(gdp_gin_t *);
270
                                                                                // called when this is closed
271
        EP_STAT                                (*apndfilter)(        // append filter function
272
                                                        gdp_datum_t *,
273
                                                        void *);
274
        void                                *apndfpriv;                // private data for apndfilter
275
        EP_STAT                                (*readfilter)(        // read filter function
276
                                                        gdp_datum_t *,
277
                                                        void *);
278
        void                                *readfpriv;                // private data for readfilter
279
};
280

    
281
#define GINF_INUSE                        0x0001                // GIN is allocated
282
#define GINF_ISLOCKED                0x0002                // GIN is locked
283
#define GINF_SIG_VRFY                0x0004                // verify returned data if possible
284
#define GINF_SIG_VRFY_REQ        0x0008                // signature verification required
285

    
286
// internal GDP object, shared between open instances, used in gdplogd
287
struct gdp_gob
288
{
289
        EP_THR_MUTEX                mutex;                        // lock on this data structure
290
        time_t                                utime;                        // last time used (seconds only)
291
        LIST_ENTRY(gdp_gob)        ulist;                        // list sorted by use time
292
        struct req_head                reqs;                        // list of outstanding requests
293
        gdp_name_t                        name;                        // the internal name
294
        gdp_pname_t                        pname;                        // printable name (for debugging)
295
        uint16_t                        flags;                        // flag bits, see below
296
        uint16_t                        hashalg;                // hash algorithm
297
        int                                        refcnt;                        // reference counter
298
        void                                (*freefunc)(gdp_gob_t *);
299
                                                                                // called when this is freed
300
        gdp_recno_t                        nrecs;                        // # of records (actually last recno)
301
        gdp_md_t                        *gob_md;                // metadata
302
        EP_CRYPTO_MD                *sign_ctx;                // base digest for signature
303
        EP_CRYPTO_MD                *vrfy_ctx;                // base digest for verification
304
        struct gdp_gob_xtra        *x;                                // for use by gdplogd, gdp-rest
305
};
306

    
307
// flags for GDP objects
308
#define GOBF_INUSE                        0x0001                // handle is allocated
309
#define GOBF_ISLOCKED                0x0002                // GOB is locked
310
#define GOBF_DROPPING                0x0004                // handle is being deallocated
311
#define GOBF_INCACHE                0x0008                // handle is in cache
312
#define GOBF_DEFER_FREE                0x0010                // defer actual free until reclaim
313
#define GOBF_KEEPLOCKED                0x0020                // don't unlock in _gdp_gob_decref
314
#define GOBF_PENDING                0x0040                // not yet fully open
315
#define GOBF_SIGNING                0x0080                // we are signing records
316
#define GOBF_VERIFYING                0x0100                // we are verifying records
317
#define GOBF_VRFY_WARN                0x0200                // verification fail is a warning only
318

    
319

    
320
/*
321
**  GOB functions
322
*/
323

    
324
// Used to avoid compiler warnings on some versions of gcc ("value computed is
325
// not used").  If "inline" doesn't work, use #define _gdp_bool_null(b) (b).
326
static inline bool _gdp_bool_null(bool b) { return b; }
327

    
328
#define GDP_GOB_ISGOOD(gob)                                                                                                \
329
                                ((gob) != NULL &&                                                                                \
330
                                 EP_UT_BITSET(GOBF_INUSE, (gob)->flags))
331
#define GDP_GOB_ASSERT_ISLOCKED(gob)                                                                        \
332
                        _gdp_bool_null(                                                                                                \
333
                                EP_ASSERT(GDP_GOB_ISGOOD(gob)) &&                                                \
334
                                EP_ASSERT(EP_UT_BITSET(GOBF_ISLOCKED, (gob)->flags)) &&        \
335
                                EP_THR_MUTEX_ASSERT_ISLOCKED(&(gob)->mutex)                                \
336
                        )
337

    
338

    
339
EP_STAT                        _gdp_gob_new(                                // create new in-mem handle
340
                                                gdp_name_t name,
341
                                                gdp_gob_t **gobhp);
342

    
343
void                        _gdp_gob_free(                                // free in-memory handle
344
                                                gdp_gob_t **gob);                // GOB to free
345

    
346
#define _gdp_gob_lock(g)                _gdp_gob_lock_trace(g, __FILE__, __LINE__, #g)
347
#define _gdp_gob_unlock(g)                _gdp_gob_unlock_trace(g, __FILE__, __LINE__, #g)
348
#define _gdp_gob_incref(g)                _gdp_gob_incref_trace(g, __FILE__, __LINE__, #g)
349
#define _gdp_gob_decref(g, k)        _gdp_gob_decref_trace(g, k, __FILE__, __LINE__, #g)
350

    
351
void                        _gdp_gob_lock_trace(                // lock the GOB mutex
352
                                                gdp_gob_t *gob,
353
                                                const char *file,
354
                                                int line,
355
                                                const char *id);
356

    
357
void                        _gdp_gob_unlock_trace(                // unlock the GOB mutex
358
                                                gdp_gob_t *gob,
359
                                                const char *file,
360
                                                int line,
361
                                                const char *id);
362

    
363
gdp_gob_t                *_gdp_gob_incref_trace(                // increase reference count (trace)
364
                                                gdp_gob_t *gob,
365
                                                const char *file,
366
                                                int line,
367
                                                const char *id);
368

    
369
void                        _gdp_gob_decref_trace(                // decrease reference count (trace)
370
                                                gdp_gob_t **gobp,
371
                                                bool keeplocked,
372
                                                const char *file,
373
                                                int line,
374
                                                const char *id);
375

    
376
EP_STAT                        _gdp_gob_newname(                        // create new name based on metadata
377
                                                gdp_gob_t *gob);
378

    
379
void                        _gdp_gob_dump(                                // dump for debugging
380
                                                const gdp_gob_t *gob,        // GOB to print
381
                                                FILE *fp,                                // where to print it
382
                                                int detail,                                // how much to print
383
                                                int indent);                        // unused at this time
384

    
385
EP_STAT                        _gdp_gob_init_vrfy_ctx(                // initialize for proof verification
386
                                                gdp_gob_t *gob);
387

    
388
EP_STAT                        _gdp_gob_create(                        // create a new GDP object
389
                                                gdp_md_t *gmd,
390
                                                gdp_name_t logdname,
391
                                                gdp_gob_t **pgob);
392

    
393
EP_STAT                        _gdp_gob_open(                                // open a GOB
394
                                                gdp_gob_t *gob,
395
                                                gdp_cmd_t cmd,
396
                                                gdp_open_info_t *open_info,
397
                                                gdp_chan_t *chan,
398
                                                uint32_t reqflags);
399

    
400
EP_STAT                        _gdp_gob_close(                                // close a GOB (handle)
401
                                                gdp_gob_t *gob,
402
                                                gdp_chan_t *chan,
403
                                                uint32_t reqflags);
404

    
405
EP_STAT                        _gdp_gob_delete(                        // delete and close a GOB (handle)
406
                                                gdp_gob_t *gob,
407
                                                gdp_chan_t *chan,
408
                                                uint32_t reqflags);
409

    
410
EP_STAT                        _gdp_gob_read_by_recno(                        // read GOB record based on datum
411
                                                gdp_gob_t *gob,
412
                                                gdp_recno_t recno,
413
                                                gdp_chan_t *chan,
414
                                                uint32_t reqflags,
415
                                                gdp_datum_t *datum);
416

    
417
EP_STAT                        _gdp_gob_read_by_recno_async(        // read asynchronously
418
                                                gdp_gob_t *gob,
419
                                                gdp_gin_t *gin,
420
                                                gdp_recno_t recno,
421
                                                uint32_t nrecs,
422
                                                gdp_event_cbfunc_t cbfunc,
423
                                                void *cbarg,
424
                                                gdp_chan_t *chan);
425

    
426
EP_STAT                        _gdp_gob_append_sync(                // append a record (gdpd shared)
427
                                                gdp_gob_t *gob,
428
                                                int n_datums,
429
                                                gdp_datum_t **datums,
430
                                                gdp_hash_t *prevhash,
431
                                                gdp_chan_t *chan,
432
                                                uint32_t reqflags);
433

    
434
EP_STAT                        _gdp_gob_append_async(                // append asynchronously
435
                                                gdp_gob_t *gob,
436
                                                gdp_gin_t *gin,
437
                                                int n_datums,
438
                                                gdp_datum_t **datums,
439
                                                gdp_hash_t *prevhash,
440
                                                gdp_event_cbfunc_t cbfunc,
441
                                                void *cbarg,
442
                                                gdp_chan_t *chan,
443
                                                uint32_t reqflags);
444

    
445
EP_STAT                        _gdp_gin_subscribe(                        // subscribe to data
446
                                                gdp_gin_t *gin,
447
                                                gdp_cmd_t cmd,
448
                                                gdp_recno_t start,
449
                                                int32_t numrecs,
450
                                                gdp_sub_qos_t *qos,
451
                                                gdp_event_cbfunc_t cbfunc,
452
                                                void *cbarg);
453

    
454
EP_STAT                        _gdp_gin_unsubscribe(                // delete subscriptions
455
                                                gdp_gin_t *gin,
456
                                                gdp_event_cbfunc_t cbfunc,
457
                                                void *cbarg,
458
                                                uint32_t reqflags);
459

    
460
EP_STAT                        _gdp_gob_getmetadata(                // retrieve metadata
461
                                                gdp_gob_t *gob,
462
                                                gdp_md_t **gmdp,
463
                                                gdp_chan_t *chan,
464
                                                uint32_t reqflags);
465

    
466
EP_STAT                        _gdp_gob_newsegment(                // create a new physical segment
467
                                                gdp_gob_t *gob,
468
                                                gdp_chan_t *chan,
469
                                                uint32_t reqflags);
470

    
471
EP_STAT                        _gdp_gob_fwd_append(                // forward APPEND (replication)
472
                                                gdp_gob_t *gob,
473
                                                gdp_datum_t *datum,
474
                                                gdp_name_t to_server,
475
                                                gdp_event_cbfunc_t cbfunc,
476
                                                void *cbarg,
477
                                                gdp_chan_t *chan,
478
                                                uint32_t reqflags);
479

    
480
/*
481
**  GIN functions
482
*/
483

    
484
#define GDP_GIN_ISGOOD(gin)                                                                                                \
485
                                ((gin) != NULL &&                                                                                \
486
                                 EP_UT_BITSET(GOBF_INUSE, (gin)->flags) &&                                \
487
                                 GDP_GOB_ISGOOD((gin)->gob))
488
#define GDP_GIN_ASSERT_ISLOCKED(gin)                                                                        \
489
                        _gdp_bool_null(                                                                                                \
490
                                EP_ASSERT(GDP_GIN_ISGOOD(gin)) &&                                                \
491
                                EP_ASSERT(EP_UT_BITSET(GOBF_ISLOCKED, (gin)->flags)) &&        \
492
                                EP_THR_MUTEX_ASSERT_ISLOCKED(&(gin)->mutex) &&                        \
493
                                GDP_GOB_ASSERT_ISLOCKED((gin)->gob)                                                \
494
                        )
495
#define GDP_GIN_CHECK_RETURN_STAT(gin)                                                                        \
496
                        do                                                                                                                        \
497
                        {                                                                                                                        \
498
                                if (!EP_ASSERT((gin) != NULL))                                                        \
499
                                                return GDP_STAT_NULL_GOB;                                                \
500
                                if (!EP_ASSERT(EP_UT_BITSET(GOBF_INUSE, (gin)->flags)))        \
501
                                                return GDP_STAT_LOG_NOT_OPEN;                                        \
502
                        } while (false)
503
#define GDP_GIN_CHECK_RETURN_NULL(gin)                                                                        \
504
                        do                                                                                                                        \
505
                        {                                                                                                                        \
506
                                if (!EP_ASSERT((gin) != NULL))                                                        \
507
                                                return NULL;                                                                        \
508
                                if (!EP_ASSERT(EP_UT_BITSET(GOBF_INUSE, (gin)->flags)))        \
509
                                                return NULL;                                                                        \
510
                        } while (false)
511

    
512
gdp_gin_t                *_gdp_gin_new(                                // create new GIN from GOB
513
                                                gdp_gob_t *gob);
514

    
515
void                        _gdp_gin_free(                                // free a GIN
516
                                                gdp_gin_t *gin);
517

    
518
void                        _gdp_gin_lock_trace(                // lock the GIN mutex
519
                                                gdp_gin_t *gin,
520
                                                const char *file,
521
                                                int line,
522
                                                const char *id);
523
#define _gdp_gin_lock(g)                _gdp_gin_lock_trace(g, __FILE__, __LINE__, #g)
524

    
525
void                        _gdp_gin_unlock_trace(                // unlock the GIN mutex
526
                                                gdp_gin_t *gin,
527
                                                const char *file,
528
                                                int line,
529
                                                const char *id);
530
#define _gdp_gin_unlock(g)                _gdp_gin_unlock_trace(g, __FILE__, __LINE__, #g)
531

    
532

    
533
/*
534
**  GOB cache.
535
**
536
**                Implemented in gdp/gdp_gob_cache.c.
537
*/
538

    
539
EP_STAT                        _gdp_gob_cache_init(void);        // initialize cache
540

    
541
void                        _gdp_gob_cache_dump(                // print cache (for debugging)
542
                                                int plev,
543
                                                FILE *fp);
544

    
545
typedef EP_STAT        gcl_open_func(
546
                                                gdp_gin_t *gcl,
547
                                                void *open_info);
548

    
549
EP_STAT                        _gdp_gob_cache_get(                // get entry from cache
550
                                                gdp_name_t gcl_name,
551
                                                uint32_t flags,
552
                                                gdp_gob_t **pgob);
553

    
554
#define GGCF_NOCREATE                0                        // dummy
555
#define GGCF_CREATE                        0x00000001        // create cache entry if non existent
556
#define GGCF_GET_PENDING        0x00000002        // return "pending" entries
557
#define GGCF_PEEK                        0x00000004        // don't update cache usage time
558

    
559
void                        _gdp_gob_cache_add(                        // add entry to cache
560
                                                gdp_gob_t *gob);
561

    
562
void                        _gdp_gob_cache_changename(        // update the name of a cached GOB
563
                                                gdp_gob_t *gob,
564
                                                gdp_name_t newname);
565

    
566
void                        _gdp_gob_cache_drop(                // drop entry from cache
567
                                                gdp_gob_t *gob,                        // GOB to drop
568
                                                bool cleanup);                        // set if doing cache cleanup
569

    
570
void                        _gdp_gob_cache_reclaim(                // flush old entries
571
                                                time_t maxage);
572

    
573
void                        _gdp_gob_cache_shutdown(        // immediately shut down cache
574
                                                void (*shutdownfunc)(gdp_req_t *));
575

    
576
void                        _gdp_gob_touch(                                // move to front of LRU list
577
                                                gdp_gob_t *gob);
578

    
579
void                        _gdp_gob_cache_foreach(                // run over all cached GOBs
580
                                                void (*f)(gdp_gob_t *));
581

    
582
void                        _gdp_gob_pr_stats(                        // print (debug) GOB statistics
583
                                                FILE *fp);
584

    
585

    
586

    
587
/*
588
**  GOB Open Information
589
**
590
**                Passed from application into library to allow for all the
591
**                parameters we didn't think of when we first defined the API.
592
*/
593

    
594
struct gdp_open_info
595
{
596
        EP_CRYPTO_KEY                *signkey;                        // signing key
597
        gdp_signkey_cb_t        *signkey_cb;                // callback to get signing key
598
        void                                *signkey_udata;                // passed to signkey_cb
599
        uint32_t                        flags;                                // see below
600
};
601

    
602
// flags values
603
#define GOIF_KEEP_IN_CACHE                0x00000001        // defer GOB free
604
#define GOIF_VERIFY_PROOF                0x00000002        // when reading, verify datum
605
#define GOIF_NO_SKEY_NONFATAL        0x00000004        // missing secret key not fatal
606

    
607

    
608
/*
609
**  A Work Request (and associated Response)
610
**
611
**                A GDP request is packaged up in one of these things and
612
**                submitted.  Responses are returned in the same structure.
613
**
614
**                There are two PDU pointers:
615
**                * cpdu is the PDU with the command.  Generally this is
616
**                        kept around until the response is read in case you
617
**                        need to retransmit the command PDU.
618
**                * rpdu is the PDU with the response.
619
**
620
**                PDUs have an associated gdp_buf_t to store the actual
621
**                data.  That buffer does not have a write callback, so
622
**                it can be used without having any side effects.
623
**
624
**                The PDU includes the command/response code, the rid,
625
**                the record number, the timestamp, the data buffer,
626
**                and an optional signature buffer.
627
**
628
**                There can be mulitple requests active on a single GOB at
629
**                any time, but they should have unique rids.  Rids can be
630
**                reused if desired once an operation is complete.  Note:
631
**                some operations (e.g., subscriptions) can return multiple
632
**                results, but they will have the same rid.
633
**
634
**                Requests are potentially linked on lists.  Every request
635
**                that is active on a channel is linked to that channel
636
**                (with the GDP_REQ_ON_CHAN_LIST flag set); this is so that
637
**                requests can be cleaned up if the channel goes away.  At
638
**                this point we try to recover the channel, so this should
639
**                be rare, but that list is also used to find requests that
640
**                need to be timed out.
641
**
642
**                For active requests --- that is, requests that are either
643
**                waiting for a response (in _gdp_invoke) or represent
644
**                potential points for subscriptions --- are also linked to
645
**                the corresponding GOB, and will have the GDP_REQ_ON_GOB_LIST
646
**                flag set.  Subscription listeners also have the
647
**                GDP_REQ_CLT_SUBSCR flag set.  GDP_REQ_SRV_SUBSCR is used
648
**                by gdplogd to find the other end of the subscription, i.e,
649
**                subscription data producers.
650
**
651
**                In both the case of applications and gdplogd, requests may
652
**                get passed between threads.  To prevent someone from finding
653
**                a request on one of these lists and using it at the same time
654
**                someone else has it in use, you would like to lock the data
655
**                structure while it is active.  But you can't pass a mutex
656
**                between threads.  This is a particular problem if subscription
657
**                or multiread data comes in faster than it can be processed;
658
**                since the I/O thread is separate from the processing thread
659
**                things can clobber each other.
660
**
661
**                We solve this by assigning a state to each request:
662
**
663
**                FREE means that this request is on the free list.  It
664
**                        should never appear in any other context.
665
**                ACTIVE means that there is currently an operation taking
666
**                        place on the request, and no one other than the owner
667
**                        should use it.  If you need it, you can wait on the
668
**                        condition variable.
669
**                WAITING means that the request has been sent from a client
670
**                        to a server but hasn't gotten the response yet.  It
671
**                        shouldn't be possible for a WAITING request to also
672
**                        have an active subscription, but it will be in the GOB
673
**                        list.
674
**                IDLE means that the request is not free, but there is no
675
**                        operation in process on it.  This will generally be
676
**                        because it is a subscription that does not have any
677
**                        currently active data.
678
**
679
**                If you want to deliver data to a subscription, you have to
680
**                first make sure the req is in IDLE state, turn it to ACTIVE
681
**                state, and then process it.  If it is not in IDLE state you
682
**                sleep on the condition variable and try again.
683
**
684
**                Passing a request to another thread is basically the same.
685
**                The invariant is that any req being passed between threads
686
**                should always be ACTIVE.
687
**
688
**                In some cases requests may have pending events.  This
689
**                occurs for commands such as SUBSCRIBE or MULTIREAD when
690
**                the first data return appears before the ack for the
691
**                initial command has finished processing.  To avoid confusing
692
**                applications you have to defer these events until the app
693
**                knows that the command succeeded.  This list is sorted by
694
**                seqno (that is, the sequence number of the PDU as issued
695
**                by the sender).  The next expected seqno is stored in
696
**                seqnext.
697
**
698
**                Implemented in gdp_req.c.
699
*/
700

    
701
struct gdp_req
702
{
703
        EP_THR_MUTEX                mutex;                // lock on this data structure
704
        EP_THR_COND                        cond;                // pthread wakeup condition variable
705
        uint16_t                        state;                // see below
706
        LIST_ENTRY(gdp_req)        goblist;        // linked list for cache management
707
        LIST_ENTRY(gdp_req)        chanlist;        // reqs associated with a given channel
708
        gdp_gob_t                        *gob;                // associated GDP Object handle
709
        gdp_pdu_t                        *cpdu;                // PDU for commands
710
        gdp_pdu_t                        *rpdu;                // PDU for ack/nak responses
711
        gdp_chan_t                        *chan;                // the network channel for this req
712
        EP_STAT                                stat;                // status code from last operation
713
        gdp_recno_t                        nextrec;        // next record to return (subscriptions)
714
        int64_t                                s_results;        // number of results sent
715
        int32_t                                numrecs;        // remaining number of records to return
716
        uint32_t                        flags;                // see below
717
        void                                (*postproc)(struct gdp_req *);
718
                                                                        // do post processing after ack sent
719
        EP_TIME_SPEC                act_ts;                // timestamp of last successful activity
720
        EP_TIME_SPEC                sub_ts;                // time of current subscription lease start
721
        gdp_event_cbfunc_t        sub_cbfunc;        // callback function (subscribe & async I/O)
722
        void                                *sub_cbarg;        // user-supplied opaque data to cb
723

    
724
        // these are only of interest in clients, never in gdplogd
725
        gdp_gin_t                        *gin;                // GIN handle (client only, may be NULL)
726
        int64_t                                r_results;        // number of results received so far
727
        struct gev_list                events;                // pending events (see above)
728
        gdp_seqno_t                        seqnext;        // next expected seqno
729
        struct event                *ev_to;                // event timeout (to scan pending events)
730
};
731

    
732
// states
733
#define GDP_REQ_FREE                        0                        // request is free
734
#define GDP_REQ_ACTIVE                        1                        // currently being processed
735
#define GDP_REQ_WAITING                        2                        // waiting on cond variable
736
#define GDP_REQ_IDLE                        3                        // subscription waiting for data
737

    
738
// flags
739
#define GDP_REQ_ASYNCIO                        0x00000001        // async I/O operation
740
#define GDP_REQ_DONE                        0x00000002        // operation complete
741
#define GDP_REQ_CLT_SUBSCR                0x00000004        // client-side subscription
742
#define GDP_REQ_SRV_SUBSCR                0x00000008        // server-side subscription
743
#define GDP_REQ_PERSIST                        0x00000010        // request persists after response
744
#define GDP_REQ_SUBUPGRADE                0x00000020        // can upgrade to subscription
745
#define GDP_REQ_ALLOC_RID                0x00000040        // force allocation of new rid
746
#define GDP_REQ_ON_GOB_LIST                0x00000080        // this is on a GOB list
747
#define GDP_REQ_ON_CHAN_LIST        0x00000100        // this is on a channel list
748
#define GDP_REQ_VRFY_CONTENT        0x00000200        // verify content proof
749
#define GDP_REQ_ROUTEFAIL                0x00000400        // fail immediately on route failure
750

    
751
EP_STAT                        _gdp_req_new(                                // create new request
752
                                                gdp_cmd_t cmd,
753
                                                gdp_gob_t *gob,
754
                                                gdp_chan_t *chan,
755
                                                gdp_pdu_t *pdu,
756
                                                uint32_t flags,
757
                                                gdp_req_t **reqp);
758

    
759
void                        _gdp_req_free(                                // free old request
760
                                                gdp_req_t **reqp);
761

    
762
EP_STAT                        _gdp_req_lock(                                // lock a request mutex
763
                                                gdp_req_t *);
764

    
765
void                        _gdp_req_unlock(                        // unlock a request mutex
766
                                                gdp_req_t *);
767

    
768
gdp_req_t                *_gdp_req_find(                                // find a request in a GOB
769
                                                gdp_gob_t *gob, gdp_rid_t rid);
770

    
771
gdp_rid_t                _gdp_rid_new(                                // create new request id
772
                                                gdp_gob_t *gob, gdp_chan_t *chan);
773

    
774
EP_STAT                        _gdp_req_send(                                // send request to daemon (async)
775
                                                gdp_req_t *req);
776

    
777
EP_STAT                        _gdp_req_unsend(                        // pull failed request off GOB list
778
                                                gdp_req_t *req);
779

    
780
EP_STAT                        _gdp_req_dispatch(                        // do local req processing
781
                                                gdp_req_t *req,
782
                                                int cmd);
783

    
784
EP_STAT                        _gdp_invoke(                                // send request to daemon (sync)
785
                                                gdp_req_t *req);
786

    
787
void                        _gdp_req_freeall(                        // free all requests in GOB list
788
                                                gdp_gob_t *gob,
789
                                                gdp_gin_t *gin,
790
                                                void (*shutdownfunc)(gdp_req_t *));
791

    
792
void                        _gdp_req_dump(                                // print (debug) request
793
                                                const gdp_req_t *req,
794
                                                FILE *fp,
795
                                                int detail,
796
                                                int indent);
797

    
798
void                        _gdp_req_pr_stats(                        // print (debug) statistics
799
                                                FILE *fp);
800

    
801
EP_STAT                        _gdp_req_ack_resp(                        // helper: create ACK response
802
                                                gdp_req_t *req,                        // active request
803
                                                gdp_cmd_t ack_type);        // actual ACK command
804

    
805
EP_STAT                        _gdp_req_nak_resp(                        // helper: create NAK response
806
                                                gdp_req_t *req,                        // active request
807
                                                gdp_cmd_t nak_type,                // actual NAK command
808
                                                const char *detail,                // text detail
809
                                                EP_STAT estat);                        // status code detail
810

    
811

    
812
/*
813
**  Channel and I/O Event support
814
*/
815

    
816
// extended channel information (passed as channel "cdata")
817
struct gdp_chan_x
818
{
819
        struct req_head                reqs;                        // reqs associated with this channel
820
        EP_STAT                                (*connect_cb)(        // called on connection established
821
                                                        gdp_chan_t *chan);
822
        long                                adv_intvl;                // advertising interval
823
        struct event                *adv_timer;                // re-advertise event (gdplogd only)
824
};
825

    
826
// functions used internally related to channel I/O
827
EP_STAT                        _gdp_io_recv(
828
                                                gdp_chan_t *chan,
829
                                                gdp_name_t src,
830
                                                gdp_name_t dst,
831
                                                gdp_seqno_t seqno,
832
                                                gdp_buf_t *payload_buf,
833
                                                size_t payload_len);
834

    
835
EP_STAT                        _gdp_io_event(
836
                                                gdp_chan_t *chan,
837
                                                uint32_t flags);
838

    
839
// router control information
840
EP_STAT                        _gdp_router_event(
841
                                                gdp_chan_t *chan,
842
                                                gdp_name_t src,
843
                                                gdp_name_t dst,
844
                                                size_t payload_len,
845
                                                EP_STAT estat);
846

    
847
// I/O event handling
848
struct event_loop_info
849
{
850
        const char                *where;
851
};
852

    
853
void                        *_gdp_run_event_loop(
854
                                                void *eli_);
855

    
856
void                        _gdp_stop_event_loop(void);
857

    
858
typedef void        libevent_event_t(
859
                                                evutil_socket_t sock,
860
                                                short what,
861
                                                void *cbarg);
862

    
863
void                        _gdp_evloop_timer_set(
864
                                                uint32_t timeout,                        // in timeout usec
865
                                                libevent_event_t *cbfunc,        // ... call cbfunc
866
                                                void *cbarg,                                // ... with this arg
867
                                                struct event **pev);                // ... stored here
868

    
869
void                        _gdp_evloop_timer_clr(
870
                                                struct event **pev);
871

    
872

    
873
/*
874
**  Protobuf message handling.  These are only for the unpacked
875
**  (in memory, unserialized) version; the rest is hidden in
876
**  gdp_pdu.[ch].
877
*/
878

    
879
gdp_msg_t                *_gdp_msg_new(                                // create new message
880
                                        gdp_cmd_t cmd,
881
                                        gdp_rid_t rid,
882
                                        gdp_l5seqno_t l5seqno);
883

    
884
void                        _gdp_msg_free(                                // free a message
885
                                        gdp_msg_t **pmsg);
886

    
887
void                        _gdp_msg_dump(                                // print a message for debugging
888
                                        const gdp_msg_t *msg,
889
                                        FILE *fp,
890
                                        int indent);
891

    
892

    
893
/*
894
**  Structure used for registering command functions
895
**
896
**                The names are already known to the GDP library, so this is just
897
**                to bind functions that implement the individual commands.
898
*/
899

    
900
typedef EP_STAT        cmdfunc_t(                        // per command dispatch entry
901
                                        gdp_req_t *req);        // the request to be processed
902

    
903
struct cmdfuncs
904
{
905
        int                        cmd;                                // command number
906
        cmdfunc_t        *func;                                // pointer to implementing function
907
};
908

    
909
void                        _gdp_register_cmdfuncs(
910
                                                struct cmdfuncs *);
911

    
912
const char                *_gdp_proto_cmd_name(                // return printable cmd name
913
                                                uint8_t cmd);
914

    
915
#define GDP_RECLAIM_AGE_DEF                300L                // default reclaim age (sec)
916

    
917

    
918
/*
919
**  Advertising.
920
*/
921

    
922
EP_STAT                        _gdp_advertise_me(                        // advertise me only
923
                                                gdp_chan_t *chan,
924
                                                int cmd,
925
                                                void *ctx);
926

    
927
/*
928
**  Subscriptions.
929
*/
930

    
931
#define GDP_SUBSCR_REFRESH_DEF        60L                        // default refresh interval (sec)
932
#define GDP_SUBSCR_TIMEOUT_DEF        180L                // default timeout (sec)
933

    
934
extern EP_THR_MUTEX                _GdpSubscriptionMutex;
935
extern struct req_head        _GdpSubscriptionRequests;
936

    
937
void                        _gdp_subscr_lost(                        // subscription disappeared
938
                                                gdp_req_t *req);
939

    
940
void                        _gdp_subscr_poke(                        // test subscriptions still alive
941
                                                gdp_chan_t *chan);
942

    
943
/*
944
**  Initialization and Maintenance.
945
*/
946

    
947
void                        _gdp_newname(gdp_name_t gname,
948
                                                gdp_md_t *gmd);
949

    
950
void                        _gdp_reclaim_resources(                // reclaim system resources
951
                                                void *);                                // unused
952

    
953
void                        _gdp_reclaim_resources_init(
954
                                                void (*f)(int, short, void *));
955

    
956
void                        _gdp_dump_state(int plev);
957

    
958
gdp_cmd_t                _gdp_acknak_from_estat(                // produce acknak code from status
959
                                                EP_STAT estat,                        // status to evaluate
960
                                                gdp_cmd_t def);                        // use this if nothing better...
961

    
962
/*
963
**  Cryptography support
964
*/
965

    
966
EP_CRYPTO_KEY        *_gdp_crypto_skey_read(                // read a secret key
967
                                                const char *searchpath,
968
                                                const char *filename);
969
void                        _gdp_sign_metadata(                        // sign the metadata
970
                                                gdp_gin_t *gin);
971

    
972

    
973
/*
974
**  Orders for lock acquisition
975
**                Lower numbered locks should be acquired before higher numbered locks.
976
*/
977

    
978
#define GDP_MUTEX_LORDER_GIN                6
979
#define GDP_MUTEX_LORDER_GOBCACHE        8
980
#define GDP_MUTEX_LORDER_GOB                10
981
#define GDP_MUTEX_LORDER_REQ                12
982
#define GDP_MUTEX_LORDER_CHAN                14
983
#define GDP_MUTEX_LORDER_DATUM                18
984
#define GDP_MUTEX_LORDER_LEAF                31        // freelists, etc.
985

    
986

    
987
/*
988
**  Utility routines
989
*/
990

    
991
const char                *_gdp_pr_indent(                        // return indenting for debug output
992
                                                int indent);
993

    
994
void                        _gdp_adm_readparams(                // read admin params w/ versioning
995
                                                const char *name);                // base of config name
996

    
997
EP_STAT                        _gdp_adm_path_find(                        // find file in path via getstrparam
998
                                                const char *dir_param,
999
                                                const char *dir_def,
1000
                                                const char *file_param,
1001
                                                const char *file_def,
1002
                                                char *path_buf,
1003
                                                size_t path_buf_len);
1004

    
1005
void                        _gdp_show_elapsed(                        // show elapsed time
1006
                                                const char *func,                // function name
1007
                                                gdp_cmd_t cmd,                        // associated command
1008
                                                EP_TIME_SPEC *start);        // starting time
1009

    
1010

    
1011
/*
1012
**  Convenience macros
1013
*/
1014

    
1015
#define MICROSECONDS        * INT64_C(1000)
1016
#define MILLISECONDS        * INT64_C(1000000)
1017
#define SECONDS                        * INT64_C(1000000000)
1018

    
1019

    
1020
/*
1021
**  Low level support for cracking protocol, computing hashes, etc.
1022
*/
1023

    
1024
#define PUT8(v) \
1025
                { \
1026
                        *pbp++ = ((v) & 0xff); \
1027
                }
1028
#define PUT16(v) \
1029
                { \
1030
                        *pbp++ = ((v) >> 8) & 0xff; \
1031
                        *pbp++ = ((v) & 0xff); \
1032
                }
1033
#define PUT24(v) \
1034
                { \
1035
                        *pbp++ = ((v) >> 16) & 0xff; \
1036
                        *pbp++ = ((v) >> 8) & 0xff; \
1037
                        *pbp++ = ((v) & 0xff); \
1038
                }
1039
#define PUT32(v) \
1040
                { \
1041
                        *pbp++ = ((v) >> 24) & 0xff; \
1042
                        *pbp++ = ((v) >> 16) & 0xff; \
1043
                        *pbp++ = ((v) >> 8) & 0xff; \
1044
                        *pbp++ = ((v) & 0xff); \
1045
                }
1046
#define PUT48(v) \
1047
                { \
1048
                        *pbp++ = ((v) >> 40) & 0xff; \
1049
                        *pbp++ = ((v) >> 32) & 0xff; \
1050
                        *pbp++ = ((v) >> 24) & 0xff; \
1051
                        *pbp++ = ((v) >> 16) & 0xff; \
1052
                        *pbp++ = ((v) >> 8) & 0xff; \
1053
                        *pbp++ = ((v) & 0xff); \
1054
                }
1055
#define PUT64(v) \
1056
                { \
1057
                        *pbp++ = ((v) >> 56) & 0xff; \
1058
                        *pbp++ = ((v) >> 48) & 0xff; \
1059
                        *pbp++ = ((v) >> 40) & 0xff; \
1060
                        *pbp++ = ((v) >> 32) & 0xff; \
1061
                        *pbp++ = ((v) >> 24) & 0xff; \
1062
                        *pbp++ = ((v) >> 16) & 0xff; \
1063
                        *pbp++ = ((v) >> 8) & 0xff; \
1064
                        *pbp++ = ((v) & 0xff); \
1065
                }
1066

    
1067
#define GET8(v) \
1068
                { \
1069
                                v  = *pbp++; \
1070
                }
1071
#define GET16(v) \
1072
                { \
1073
                                v  = *pbp++ << 8; \
1074
                                v |= *pbp++; \
1075
                }
1076
#define GET24(v) \
1077
                { \
1078
                                v  = *pbp++ << 16; \
1079
                                v |= *pbp++ << 8; \
1080
                                v |= *pbp++; \
1081
                }
1082
#define GET32(v) \
1083
                { \
1084
                                v  = *pbp++ << 24; \
1085
                                v |= *pbp++ << 16; \
1086
                                v |= *pbp++ << 8; \
1087
                                v |= *pbp++; \
1088
                }
1089
#define GET48(v) \
1090
                { \
1091
                                v  = ((uint64_t) *pbp++) << 40; \
1092
                                v |= ((uint64_t) *pbp++) << 32; \
1093
                                v |= ((uint64_t) *pbp++) << 24; \
1094
                                v |= ((uint64_t) *pbp++) << 16; \
1095
                                v |= ((uint64_t) *pbp++) << 8; \
1096
                                v |= ((uint64_t) *pbp++); \
1097
                }
1098
#define GET64(v) \
1099
                { \
1100
                                v  = ((uint64_t) *pbp++) << 56; \
1101
                                v |= ((uint64_t) *pbp++) << 48; \
1102
                                v |= ((uint64_t) *pbp++) << 40; \
1103
                                v |= ((uint64_t) *pbp++) << 32; \
1104
                                v |= ((uint64_t) *pbp++) << 24; \
1105
                                v |= ((uint64_t) *pbp++) << 16; \
1106
                                v |= ((uint64_t) *pbp++) << 8; \
1107
                                v |= ((uint64_t) *pbp++); \
1108
                }
1109

    
1110

    
1111
#endif // _GDP_PRIV_H_