Project

General

Profile

Statistics
| Branch: | Tag: | Revision:

gdp / gdplogd / logd_gcl.c @ master

History | View | Annotate | Download (5.9 KB)

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

    
3
/*
4
**        ----- BEGIN LICENSE BLOCK -----
5
**        GDPLOGD: Log Daemon for the Global Data Plane
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
#include "logd.h"
32
#include "logd_pubsub.h"
33

    
34
#if !LOG_CHECK
35
static EP_DBG        Dbg = EP_DBG_INIT("gdplogd.gob", "GDP Log Daemon GOB handling");
36
#endif
37

    
38

    
39
/*
40
**  GOB_ALLOC --- allocate a new GOB handle in memory
41
*/
42

    
43
EP_STAT
44
gob_alloc(gdp_name_t gob_name, gdp_iomode_t iomode, gdp_gob_t **pgob)
45
{
46
        EP_STAT estat;
47
        gdp_gob_t *gob;
48
        extern void gob_close(gdp_gob_t *gob);
49

    
50
        // get the standard handle
51
        estat = _gdp_gob_new(gob_name, &gob);
52
        EP_STAT_CHECK(estat, goto fail0);
53

    
54
        // add the gdpd-specific information
55
        gob->x = (struct gdp_gob_xtra *) ep_mem_zalloc(sizeof *gob->x);
56
        if (gob->x == NULL)
57
        {
58
                estat = EP_STAT_OUT_OF_MEMORY;
59
                goto fail0;
60
        }
61
        gob->x->gob = gob;
62

    
63
        //XXX for now, assume all GOBs are on disk
64
        gob->x->physimpl = &GdpSqliteImpl;
65

    
66
        // make sure that if this is freed it gets removed from GclsByUse
67
        gob->freefunc = gob_close;
68

    
69
        // OK, return the value
70
        *pgob = gob;
71

    
72
fail0:
73
        return estat;
74
}
75

    
76

    
77
/*
78
**  GOB_CLOSE --- close a GDP version of a GOB handle
79
**
80
**                Called from _gdp_gob_freehandle, generally when the reference
81
**                count drops to zero and the GOB is reclaimed.
82
*/
83

    
84
void
85
gob_close(gdp_gob_t *gob)
86
{
87
        if (gob->x == NULL)
88
                return;
89

    
90
        // close the underlying files and free memory as needed
91
        if (gob->x->physimpl->close != NULL)
92
                gob->x->physimpl->close(gob);
93

    
94
        ep_mem_free(gob->x);
95
        gob->x = NULL;
96
}
97

    
98
#if !LOG_CHECK
99

    
100
/*
101
**   GOB_DELETE --- delete and close a GOB
102
*/
103

    
104
void
105
gob_delete(gdp_gob_t *gob)
106
{
107
        // arrange to remove the GOB from the cache
108
        gob->flags &= ~GOBF_DEFER_FREE;
109

    
110
        if (gob->x == NULL)
111
                return;
112

    
113
        // close the underlying files and free memory as needed
114
        if (gob->x->physimpl->close != NULL)
115
                gob->x->physimpl->close(gob);
116

    
117
        // now delete the files
118
        if (gob->x->physimpl->remove != NULL)
119
                gob->x->physimpl->remove(gob);
120

    
121
        ep_mem_free(gob->x);
122
        gob->x = NULL;
123
}
124

    
125

    
126
/*
127
**  Get an open instance of the GOB in the request.
128
**
129
**                This maps the GOB name to the internal GOB instance.
130
**                That open instance is returned in the request passed in.
131
**                The GOB will have it's reference count bumped, so the
132
**                caller must call _gdp_gob_decref when done with it.
133
**
134
**                GOB is returned locked and with its reference count
135
**                incremented.
136
*/
137

    
138
static EP_STAT
139
do_physical_open(gdp_gob_t *gob, void *open_info_)
140
{
141
        EP_STAT estat;
142

    
143
        if (ep_dbg_test(Dbg, 11))
144
                ep_dbg_printf("do_physical_open: %s\n", gob->pname);
145

    
146
        gob->x = (struct gdp_gob_xtra *) ep_mem_zalloc(sizeof *gob->x);
147
        gob->x->gob = gob;
148

    
149
        //XXX for now, assume all GOBs are on disk
150
        gob->x->physimpl = &GdpSqliteImpl;
151

    
152
        // make sure that if this is freed it gets removed from GclsByUse
153
        gob->freefunc = gob_close;
154

    
155
        // open the physical disk files
156
        estat = gob->x->physimpl->open(gob);
157
        if (EP_STAT_ISOK(estat))
158
        {
159
                gob->flags |= GOBF_DEFER_FREE;
160
                gob->flags &= ~GOBF_PENDING;
161
        }
162
        else
163
        {
164
                // if this isn't a "not found" error, mark it as an internal error
165
                if (!EP_STAT_IS_SAME(estat, GDP_STAT_NAK_NOTFOUND))
166
                        estat = GDP_STAT_NAK_INTERNAL;
167
        }
168

    
169
        return estat;
170
}
171

    
172

    
173
/*
174
**  Make sure GOB in req->gob is filled in.
175
**
176
**                It must correspond to the address in req->cpdu->dst.
177
**                If req->gob is filled in (i.e., it was NULL on entry), the GOB
178
**                        reference count will be bumped; otherwise it is untouched..
179
*/
180

    
181
EP_STAT
182
get_open_handle(gdp_req_t *req)
183
{
184
        EP_STAT estat;
185

    
186
        // sanity check
187
        EP_THR_MUTEX_ASSERT_ISLOCKED(&req->mutex);
188

    
189
        // if we already got this (e.g., in _gdp_pdu_process or in cache),
190
        //                just let it be
191
        if (req->gob != NULL)
192
        {
193
                estat = EP_STAT_OK;
194
                if (ep_dbg_test(Dbg, 40))
195
                {
196
                        gdp_pname_t pname;
197

    
198
                        gdp_printable_name(req->cpdu->dst, pname);
199
                        ep_dbg_printf("get_open_handle: using existing GOB:\n\t%s => %p\n",
200
                                        pname, req->gob);
201
                }
202
        }
203
        else
204
        {
205
                if (ep_dbg_test(Dbg, 40))
206
                {
207
                        gdp_pname_t pname;
208

    
209
                        gdp_printable_name(req->cpdu->dst, pname);
210
                        ep_dbg_printf("get_open_handle: finding %s in cache\n", pname);
211
                }
212

    
213
                // it should be safe to unlock the req here, since we should hold the
214
                // only reference, and we need to get the lock ordering right
215
                _gdp_req_unlock(req);
216
                estat = _gdp_gob_cache_get(req->cpdu->dst, GGCF_CREATE, &req->gob);
217
                _gdp_req_lock(req);
218
                if (EP_STAT_ISOK(estat) && EP_UT_BITSET(GOBF_PENDING, req->gob->flags))
219
                {
220
                        estat = do_physical_open(req->gob, NULL);
221
                        if (EP_STAT_IS_SAME(estat, GDP_STAT_NAK_NOTFOUND))
222
                        {
223
                                // router sent us a reference to a log that we don't own
224
                                _gdp_gob_free(&req->gob);
225
                        }
226
                }
227
                if (!EP_STAT_ISOK(estat) && req->gob != NULL)
228
                        _gdp_gob_decref(&req->gob, false);
229
                if (ep_dbg_test(Dbg, 40))
230
                {
231
                        char ebuf[60];
232
                        gdp_pname_t pname;
233

    
234
                        gdp_printable_name(req->cpdu->dst, pname);
235
                        ep_stat_tostr(estat, ebuf, sizeof ebuf);
236
                        ep_dbg_printf("get_open_handle: %s => %p: %s\n",
237
                                        pname, req->gob, ebuf);
238
                }
239
        }
240
        return estat;
241
}
242

    
243

    
244
# endif // LOG_CHECK