Project

General

Profile

Statistics
| Branch: | Tag: | Revision:

gdp / gdplogd / logd_pubsub.c @ master

History | View | Annotate | Download (11.5 KB)

1 9509f13b Eric Allman
/* vim: set ai sw=4 sts=4 ts=4 : */
2
3
/*
4
**  Handle publish/subscribe requests
5 055d3009 Eric Allman
**
6
**        ----- BEGIN LICENSE BLOCK -----
7
**        GDPLOGD: Log Daemon for the Global Data Plane
8
**        From the Ubiquitous Swarm Lab, 490 Cory Hall, U.C. Berkeley.
9
**
10 c87dd166 Eric Allman
**        Copyright (c) 2015-2019, Regents of the University of California.
11 6bd5476b Eric Allman
**        All rights reserved.
12 055d3009 Eric Allman
**
13 6bd5476b Eric Allman
**        Permission is hereby granted, without written agreement and without
14
**        license or royalty fees, to use, copy, modify, and distribute this
15
**        software and its documentation for any purpose, provided that the above
16
**        copyright notice and the following two paragraphs appear in all copies
17
**        of this software.
18 055d3009 Eric Allman
**
19 6bd5476b Eric Allman
**        IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
20
**        SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST
21
**        PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
22
**        EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 055d3009 Eric Allman
**
24 6bd5476b Eric Allman
**        REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
25 055d3009 Eric Allman
**        LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 6bd5476b Eric Allman
**        FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION,
27
**        IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO
28
**        OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
29
**        OR MODIFICATIONS.
30 055d3009 Eric Allman
**        ----- END LICENSE BLOCK -----
31 9509f13b Eric Allman
*/
32
33 66474e0a Eric Allman
#include "logd.h"
34
#include "logd_pubsub.h"
35 9509f13b Eric Allman
36
#include <gdp/gdp_priv.h>
37 34e502ee Eric Allman
#include <gdp/gdp_chan.h>
38 42443eab Eric Allman
#include <ep/ep.h>
39 9509f13b Eric Allman
#include <ep/ep_dbg.h>
40 42443eab Eric Allman
#include <ep/ep_hash.h>
41
42
#include <sys/queue.h>
43 9509f13b Eric Allman
44 66474e0a Eric Allman
static EP_DBG        Dbg = EP_DBG_INIT("gdplogd.pubsub",
45
                                                                "GDP Log Daemon pub/sub handling");
46 9509f13b Eric Allman
47 fec93aac Eric Allman
extern EP_HASH        *_OpenGOBCache;                // associative cache
48 42443eab Eric Allman
49 9509f13b Eric Allman
50
/*
51
**  SUB_SEND_MESSAGE_NOTIFICATION --- inform a subscriber of a new message
52 e7b2a80c Eric Allman
**
53
**                Assumes req is locked.
54 9509f13b Eric Allman
*/
55
56 8bebf0e3 Eric Allman
EP_STAT
57
sub_send_message_notification(gdp_req_t *req)
58 9509f13b Eric Allman
{
59
        EP_STAT estat;
60 2e4a5d7d Eric Allman
61 c5389e19 Eric Allman
        if (ep_dbg_test(Dbg, 33))
62 9509f13b Eric Allman
        {
63 a34bb9a0 Eric Allman
                ep_dbg_printf("sub_send_message_notification: ");
64 8bebf0e3 Eric Allman
                _gdp_req_dump(req, NULL, GDP_PR_BASIC, 0);
65 9509f13b Eric Allman
        }
66
67 79ec15a3 Eric Allman
        // sanity checks
68 8bebf0e3 Eric Allman
        EP_ASSERT(req->rpdu != NULL);
69
        EP_ASSERT(req->cpdu != NULL);
70
        EP_ASSERT(req->rpdu->msg != NULL);
71 a34bb9a0 Eric Allman
72 8bebf0e3 Eric Allman
        memcpy(req->rpdu->dst, req->cpdu->src, sizeof req->rpdu->dst);
73
        req->rpdu->msg->rid = req->cpdu->msg->rid;
74 e6319882 Eric Allman
        req->rpdu->msg->l5seqno = req->cpdu->msg->l5seqno;
75 80b79281 Eric Allman
        estat = _gdp_pdu_out(req->rpdu, req->chan);
76 d65c01e2 Eric Allman
77 04ceac3d Eric Allman
        if (!EP_STAT_ISOK(estat))
78
        {
79
                ep_dbg_cprintf(Dbg, 1,
80
                                "sub_send_message_notification: couldn't write PDU!\n");
81
        }
82 ea6bb08e Eric Allman
83 8bebf0e3 Eric Allman
        return estat;
84 9509f13b Eric Allman
}
85
86
87
/*
88
**  SUB_NOTIFY_ALL_SUBSCRIBERS --- send something to all interested parties
89 e7b2a80c Eric Allman
**
90 53393e9c Eric Allman
**                pubreq should be locked when this is called.
91 9509f13b Eric Allman
*/
92
93
void
94 53393e9c Eric Allman
sub_notify_all_subscribers(gdp_req_t *pubreq)
95 9509f13b Eric Allman
{
96
        gdp_req_t *req;
97 101504b5 Eric Allman
        gdp_req_t *nextreq;
98 8bebf0e3 Eric Allman
        long timeout;
99 101504b5 Eric Allman
        EP_TIME_SPEC sub_timeout;
100 9509f13b Eric Allman
101 53393e9c Eric Allman
        EP_THR_MUTEX_ASSERT_ISLOCKED(&pubreq->mutex);
102 fec93aac Eric Allman
        GDP_GOB_ASSERT_ISLOCKED(pubreq->gob);
103 8bebf0e3 Eric Allman
        EP_ASSERT_ELSE(pubreq->rpdu != NULL, return);
104
        EP_ASSERT_ELSE(pubreq->rpdu->msg != NULL, return);
105 9509f13b Eric Allman
106 a34bb9a0 Eric Allman
        // set up for subscription timeout
107 9509f13b Eric Allman
        {
108 101504b5 Eric Allman
                EP_TIME_SPEC sub_delta;
109 8bebf0e3 Eric Allman
                timeout = ep_adm_getlongparam("swarm.gdplogd.subscr.timeout", 0);
110 101504b5 Eric Allman
111 b068acef Eric Allman
                if (timeout == 0)
112
                        timeout = ep_adm_getlongparam("swarm.gdp.subscr.timeout",
113
                                                                        GDP_SUBSCR_TIMEOUT_DEF);
114 101504b5 Eric Allman
                ep_time_from_nsec(-timeout SECONDS, &sub_delta);
115
                ep_time_deltanow(&sub_delta, &sub_timeout);
116
        }
117
118 8bebf0e3 Eric Allman
        if (ep_dbg_test(Dbg, 32))
119
        {
120
                EP_TIME_SPEC now;
121
                char tbuf[100];
122
123
                ep_time_now(&now);
124
                ep_dbg_printf("sub_notify_all_subscribers(timeout=%ld, now=%s)\n",
125
                                        timeout,
126
                                        ep_time_format(&now, tbuf, sizeof tbuf, EP_TIME_FMT_HUMAN));
127
                ep_dbg_printf("%spub", _gdp_pr_indent(1));
128
                _gdp_req_dump(pubreq, ep_dbg_getfile(), GDP_PR_BASIC, 1);
129
        }
130
131 eae1d3ec Eric Allman
        pubreq->gob->flags |= GOBF_KEEPLOCKED;
132 fec93aac Eric Allman
        for (req = LIST_FIRST(&pubreq->gob->reqs); req != NULL; req = nextreq)
133 101504b5 Eric Allman
        {
134 7f515f6d Eric Allman
                _gdp_req_lock(req);
135 fec93aac Eric Allman
                nextreq = LIST_NEXT(req, goblist);
136 65f23ae5 Eric Allman
                EP_ASSERT_ELSE(req != nextreq, break);
137 7f515f6d Eric Allman
138 9509f13b Eric Allman
                // make sure we don't tell ourselves
139
                if (req == pubreq)
140 7f515f6d Eric Allman
                {
141
                        _gdp_req_unlock(req);
142 9509f13b Eric Allman
                        continue;
143 7f515f6d Eric Allman
                }
144 e7b2a80c Eric Allman
145 cf71c5ea Eric Allman
                if (ep_dbg_test(Dbg, 59))
146
                {
147 02de7463 Eric Allman
                        ep_dbg_printf("sub_notify_all_subscribers: checking ");
148 4102ad3a Eric Allman
                        _gdp_req_dump(req, ep_dbg_getfile(), GDP_PR_BASIC, 0);
149 cf71c5ea Eric Allman
                }
150
151 9509f13b Eric Allman
                // notify subscribers
152 101504b5 Eric Allman
                if (!EP_UT_BITSET(GDP_REQ_SRV_SUBSCR, req->flags))
153
                {
154 8bebf0e3 Eric Allman
                        ep_dbg_cprintf(Dbg, 59,
155
                                        "   ... not a subscription (flags = 0x%x)\n",
156
                                        req->flags);
157 101504b5 Eric Allman
                }
158 94e663bc Eric Allman
                else if (!ep_time_before(&req->sub_ts, &sub_timeout))
159 101504b5 Eric Allman
                {
160 8bebf0e3 Eric Allman
                        EP_STAT estat;
161
                        EP_ASSERT_ELSE(req->cpdu != NULL, continue);
162
                        EP_ASSERT_ELSE(req->cpdu->msg != NULL, continue);
163
                        gdp_pdu_t *save_pdu = req->rpdu;
164
                        req->rpdu = pubreq->rpdu;
165
                        estat = sub_send_message_notification(req);
166
                        req->rpdu = save_pdu;
167
                        if (EP_STAT_ISOK(estat))
168
                        {
169
                                // XXX: This won't really work in case of holes.
170
                                req->nextrec++;
171
172
                                if (req->numrecs > 0 && --req->numrecs <= 0)
173
                                        sub_end_subscription(req);
174
                        }
175 101504b5 Eric Allman
                }
176 02de7463 Eric Allman
                else
177 101504b5 Eric Allman
                {
178
                        // this subscription seems to be dead
179
                        if (ep_dbg_test(Dbg, 18))
180
                        {
181 8bebf0e3 Eric Allman
                                char tbuf[100];
182
                                ep_time_format(&sub_timeout, tbuf, sizeof tbuf,
183
                                                        EP_TIME_FMT_HUMAN);
184
                                ep_dbg_printf("sub_notify_all_subscribers: "
185
                                                "subscription timeout (%s):\n%s",
186
                                                tbuf, _gdp_pr_indent(1));
187
                                _gdp_req_dump(req, ep_dbg_getfile(), GDP_PR_BASIC, 1);
188
                                ep_dbg_printf("%s", _gdp_pr_indent(1));
189
                                _gdp_gob_dump(req->gob, ep_dbg_getfile(), GDP_PR_BASIC, 1);
190 101504b5 Eric Allman
                        }
191
192
                        // actually remove the subscription
193 e6b0a042 Eric Allman
                        //XXX isn't this done by _gdp_req_free???
194 fec93aac Eric Allman
                        //LIST_REMOVE(req, goblist);
195 19efef53 Eric Allman
196 fec93aac Eric Allman
                        EP_ASSERT(req->gob != NULL);
197
                        EP_ASSERT(EP_UT_BITSET(GDP_REQ_ON_GOB_LIST, req->flags));
198 283110f2 Eric Allman
                        _gdp_req_free(&req);
199 101504b5 Eric Allman
                }
200 e7b2a80c Eric Allman
                if (req != NULL)
201
                        _gdp_req_unlock(req);
202 9509f13b Eric Allman
        }
203 eae1d3ec Eric Allman
        pubreq->gob->flags &= ~GOBF_KEEPLOCKED;
204 9509f13b Eric Allman
}
205 2e4a5d7d Eric Allman
206
207
/*
208
**  SUB_END_SUBSCRIPTION --- terminate a subscription
209 e7b2a80c Eric Allman
**
210 fec93aac Eric Allman
**                req and req->gob should be locked when this is called.
211 2e4a5d7d Eric Allman
*/
212
213
void
214
sub_end_subscription(gdp_req_t *req)
215
{
216 1b7c480e Eric Allman
217 2a8cda22 Eric Allman
        EP_THR_MUTEX_ASSERT_ISLOCKED(&req->mutex);
218 fec93aac Eric Allman
        GDP_GOB_ASSERT_ISLOCKED(req->gob);
219 e7b2a80c Eric Allman
220 2e4a5d7d Eric Allman
        // make it not persistent and not a subscription
221 1440421a Eric Allman
        req->flags &= ~(GDP_REQ_PERSIST | GDP_REQ_SRV_SUBSCR);
222 2e4a5d7d Eric Allman
223
        // remove the request from the work list
224 fec93aac Eric Allman
        if (EP_UT_BITSET(GDP_REQ_ON_GOB_LIST, req->flags))
225 42443eab Eric Allman
        {
226 fec93aac Eric Allman
                gdp_gob_t *gob = req->gob;
227
                LIST_REMOVE(req, goblist);
228
                req->flags &= ~GDP_REQ_ON_GOB_LIST;
229
                EP_ASSERT(gob->refcnt > 1);
230
                _gdp_gob_decref(&gob, true);
231 42443eab Eric Allman
        }
232 deca9f59 Eric Allman
233 b27895fb Eric Allman
        // make sure we have a response message available
234
        if (req->rpdu == NULL || req->rpdu->msg == NULL)
235
        {
236
                GdpMessage *msg = ep_mem_malloc(sizeof *msg);
237
                gdp_message__init(msg);
238
                if (req->rpdu == NULL)
239 5edf4ad2 Eric Allman
                        req->rpdu = _gdp_pdu_new(msg, req->cpdu->dst, req->cpdu->src,
240
                                                                        GDP_SEQNO_NONE);
241 b27895fb Eric Allman
                req->rpdu->msg = msg;
242
        }
243
244 2e4a5d7d Eric Allman
        // send an "end of subscription" event
245 b27895fb Eric Allman
        req->rpdu->msg->rid = req->cpdu->msg->rid;
246 bd278f2e Eric Allman
        req->rpdu->msg->cmd = GDP_ACK_END_OF_RESULTS;
247 2e4a5d7d Eric Allman
248 9c515e64 Eric Allman
        if (ep_dbg_test(Dbg, 39))
249 2e4a5d7d Eric Allman
        {
250 9c515e64 Eric Allman
                ep_dbg_printf("sub_end_subscription removing:\n  ");
251 4102ad3a Eric Allman
                _gdp_req_dump(req, ep_dbg_getfile(), GDP_PR_BASIC, 0);
252 2e4a5d7d Eric Allman
        }
253
254 80b79281 Eric Allman
        (void) _gdp_pdu_out(req->rpdu, req->chan);
255 2e4a5d7d Eric Allman
}
256 9d11c6da Eric Allman
257
258
/*
259 fec93aac Eric Allman
**  Unsubscribe all requests for a given gob and destination.
260 9c515e64 Eric Allman
**  Can also optionally select a particular request id.
261 cf05aa39 Eric Allman
*/
262
263
EP_STAT
264
sub_end_all_subscriptions(
265 fec93aac Eric Allman
                gdp_gob_t *gob,
266 9c515e64 Eric Allman
                gdp_name_t dest,
267
                gdp_rid_t rid)
268 cf05aa39 Eric Allman
{
269
        EP_STAT estat;
270
        gdp_req_t *req;
271
        gdp_req_t *nextreq;
272
273 2f4bea8c Eric Allman
        if (ep_dbg_test(Dbg, 29))
274
        {
275 cfc94dab Eric Allman
                gdp_pname_t dst_p;
276
                ep_dbg_printf("sub_end_all_subscriptions: rid %" PRIgdp_rid " dst %s\n    ",
277
                                rid, gdp_printable_name(dest, dst_p));
278 c5a6d4fa Eric Allman
                _gdp_gob_dump(gob, ep_dbg_getfile(), GDP_PR_BASIC, 1);
279 2f4bea8c Eric Allman
        }
280
281 fec93aac Eric Allman
        GDP_GOB_ASSERT_ISLOCKED(gob);
282 eae1d3ec Eric Allman
        if (EP_UT_BITSET(GOBF_KEEPLOCKED, gob->flags) && ep_dbg_test(Dbg, 1))
283
                ep_dbg_printf("sub_end_all_subscriptions: GOBF_KEEPLOCKED on entry\n");
284
        gob->flags |= GOBF_KEEPLOCKED;
285 2f4bea8c Eric Allman
286 cf05aa39 Eric Allman
        do
287
        {
288
                estat = EP_STAT_OK;
289 fec93aac Eric Allman
                for (req = LIST_FIRST(&gob->reqs); req != NULL; req = nextreq)
290 cf05aa39 Eric Allman
                {
291
                        estat = _gdp_req_lock(req);
292
                        EP_STAT_CHECK(estat, break);
293 fec93aac Eric Allman
                        nextreq = LIST_NEXT(req, goblist);
294 cfc94dab Eric Allman
                        if (!GDP_NAME_SAME(req->cpdu->dst, dest) ||
295
                                        (rid != GDP_PDU_NO_RID && rid != req->cpdu->msg->rid) ||
296 fec93aac Eric Allman
                                        !EP_ASSERT(req->gob == gob))
297 cf05aa39 Eric Allman
                        {
298
                                _gdp_req_unlock(req);
299
                                continue;
300
                        }
301
302 fec93aac Eric Allman
                        // remove subscription for this destination (but keep GOB locked)
303 9c515e64 Eric Allman
                        if (ep_dbg_test(Dbg, 39))
304
                        {
305
                                ep_dbg_printf("sub_end_all_subscriptions removing ");
306
                                _gdp_req_dump(req, ep_dbg_getfile(), GDP_PR_BASIC, 0);
307
                        }
308 fec93aac Eric Allman
                        LIST_REMOVE(req, goblist);
309
                        req->flags &= ~GDP_REQ_ON_GOB_LIST;
310
                        _gdp_gob_decref(&req->gob, false);
311 cf05aa39 Eric Allman
                        _gdp_req_free(&req);
312
                }
313
        } while (!EP_STAT_ISOK(estat));
314 eae1d3ec Eric Allman
        gob->flags &= ~GOBF_KEEPLOCKED;
315 cf05aa39 Eric Allman
        return estat;
316
}
317
318
319
/*
320 9d11c6da Eric Allman
**  SUB_RECLAIM_RESOURCES --- remove any expired subscriptions
321 42443eab Eric Allman
**
322
**                This is a bit tricky to get lock ordering correct.  The
323
**                obvious implementation is to loop through the channel
324 fec93aac Eric Allman
**                list, but when you try to lock a GOB or a request you
325 42443eab Eric Allman
**                have a lock ordering problem (the channel is quite low
326
**                in the locking hierarchy).  Instead you run through
327 fec93aac Eric Allman
**                the GOB hash table.
328 9d11c6da Eric Allman
*/
329
330 42443eab Eric Allman
// helper (does most of the work)
331
static void
332 fec93aac Eric Allman
gob_reclaim_subscriptions(gdp_gob_t *gob)
333 9d11c6da Eric Allman
{
334 42443eab Eric Allman
        int istat;
335 9d11c6da Eric Allman
        gdp_req_t *req;
336
        gdp_req_t *nextreq;
337
        EP_TIME_SPEC sub_timeout;
338
339 42443eab Eric Allman
        // just in case
340 fec93aac Eric Allman
        if (gob == NULL)
341 42443eab Eric Allman
                return;
342
343 9d11c6da Eric Allman
        {
344
                EP_TIME_SPEC sub_delta;
345 2f4bea8c Eric Allman
                long timeout = ep_adm_getlongparam("swarm.gdp.subscr.timeout",
346
                                                                GDP_SUBSCR_TIMEOUT_DEF);
347 9d11c6da Eric Allman
348
                ep_time_from_nsec(-timeout SECONDS, &sub_delta);
349
                ep_time_deltanow(&sub_delta, &sub_timeout);
350 b8f93c05 Eric Allman
                ep_dbg_cprintf(Dbg, 39,
351 fec93aac Eric Allman
                                "gob_reclaim_subscriptions: GOB = %p, refcnt = %d, timeout = %ld\n",
352
                                gob, gob->refcnt, timeout);
353 9d11c6da Eric Allman
        }
354
355 fec93aac Eric Allman
        // don't even try locked GOBs
356 42443eab Eric Allman
        // first check is to avoid extraneous errors
357 eae1d3ec Eric Allman
        if (EP_UT_BITSET(GOBF_ISLOCKED, gob->flags))
358 b8f93c05 Eric Allman
        {
359 fec93aac Eric Allman
                ep_dbg_cprintf(Dbg, 39, " ... skipping locked GOB\n");
360 42443eab Eric Allman
                return;
361 b8f93c05 Eric Allman
        }
362 fec93aac Eric Allman
        istat = ep_thr_mutex_trylock(&gob->mutex);
363 42443eab Eric Allman
        if (istat != 0)
364 9d11c6da Eric Allman
        {
365 42443eab Eric Allman
                if (ep_dbg_test(Dbg, 21))
366
                {
367 fec93aac Eric Allman
                        ep_dbg_printf("gob_reclaim_subscriptions: gob already locked:\n    ");
368
                        _gdp_gob_dump(gob, ep_dbg_getfile(), GDP_PR_BASIC, 0);
369 42443eab Eric Allman
                }
370
                return;
371
        }
372 eae1d3ec Eric Allman
        gob->flags |= GOBF_ISLOCKED;        // if trylock succeeded
373 193dfcd3 Eric Allman
374 fec93aac Eric Allman
        nextreq = LIST_FIRST(&gob->reqs);
375 42443eab Eric Allman
        while ((req = nextreq) != NULL)
376
        {
377 b8f93c05 Eric Allman
                if (ep_dbg_test(Dbg, 59))
378
                {
379 fec93aac Eric Allman
                        ep_dbg_printf("gob_reclaim_subscriptions: checking ");
380 b8f93c05 Eric Allman
                        _gdp_req_dump(req, ep_dbg_getfile(), GDP_PR_BASIC, 0);
381
                }
382
383 fec93aac Eric Allman
                // now that GOB is locked, we lock the request
384 193dfcd3 Eric Allman
                istat = ep_thr_mutex_trylock(&req->mutex);
385 42443eab Eric Allman
                if (istat != 0)                // checking on status of req lock attempt
386 193dfcd3 Eric Allman
                {
387
                        // already locked
388 b8f93c05 Eric Allman
                        if (ep_dbg_test(Dbg, 41))
389 474af7ac Eric Allman
                        {
390 fec93aac Eric Allman
                                ep_dbg_printf("gob_reclaim_subscriptions: req already locked:\n    ");
391 474af7ac Eric Allman
                                _gdp_req_dump(req, ep_dbg_getfile(), GDP_PR_BASIC, 0);
392
                        }
393 fec93aac Eric Allman
                        _gdp_gob_unlock(req->gob);
394 193dfcd3 Eric Allman
                        continue;
395
                }
396 9d11c6da Eric Allman
397 42443eab Eric Allman
                // get next request while locked and do sanity checks
398 fec93aac Eric Allman
                nextreq = LIST_NEXT(req, goblist);
399
                if (!EP_ASSERT(req != nextreq) || !EP_ASSERT(req->gob == gob))
400 42443eab Eric Allman
                {
401 fec93aac Eric Allman
                        _gdp_gob_unlock(req->gob);
402 42443eab Eric Allman
                        break;
403
                }
404
405 9d11c6da Eric Allman
406
                if (!EP_UT_BITSET(GDP_REQ_SRV_SUBSCR, req->flags))
407
                {
408
                        ep_dbg_cprintf(Dbg, 59, "   ... not a subscription (flags = 0x%x)\n",
409
                                        req->flags);
410
                }
411 94e663bc Eric Allman
                else if (ep_time_before(&req->sub_ts, &sub_timeout))
412 9d11c6da Eric Allman
                {
413
                        // this subscription seems to be dead
414
                        if (ep_dbg_test(Dbg, 18))
415
                        {
416 2f4bea8c Eric Allman
                                ep_dbg_printf("    ...  subscription timeout: ");
417 fec93aac Eric Allman
                                _gdp_gob_dump(req->gob, ep_dbg_getfile(), GDP_PR_BASIC, 0);
418 9d11c6da Eric Allman
                        }
419
420 8a421c17 Eric Allman
                        // have to manually remove req from lists to avoid lock inversion
421 fec93aac Eric Allman
                        if (EP_UT_BITSET(GDP_REQ_ON_GOB_LIST, req->flags))
422 6dfc87d5 Eric Allman
                        {
423 fec93aac Eric Allman
                                // gob is already locked
424
                                LIST_REMOVE(req, goblist);
425 6dfc87d5 Eric Allman
                        }
426
                        if (EP_UT_BITSET(GDP_REQ_ON_CHAN_LIST, req->flags))
427
                        {
428
                                LIST_REMOVE(req, chanlist);                        // chan already locked
429
                        }
430 fec93aac Eric Allman
                        req->flags &= ~(GDP_REQ_ON_GOB_LIST | GDP_REQ_ON_CHAN_LIST);
431
                        _gdp_gob_decref(&req->gob, true);
432 9d11c6da Eric Allman
                        _gdp_req_free(&req);
433
                }
434 2f4bea8c Eric Allman
                else if (ep_dbg_test(Dbg, 59))
435
                {
436
                        ep_dbg_printf("    ... not yet time\n");
437
                }
438 b8f93c05 Eric Allman
439 9d11c6da Eric Allman
                if (req != NULL)
440
                        _gdp_req_unlock(req);
441
        }
442 b8f93c05 Eric Allman
443 fec93aac Eric Allman
        if (gob != NULL)
444
                _gdp_gob_unlock(gob);
445 42443eab Eric Allman
}
446
447
void
448
sub_reclaim_resources(gdp_chan_t *chan)
449
{
450 fec93aac Eric Allman
        _gdp_gob_cache_foreach(gob_reclaim_subscriptions);
451 9d11c6da Eric Allman
}