vinyl-cache/bin/vinyld/cache/cache_shmlog.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2015 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
6
 *
7
 * SPDX-License-Identifier: BSD-2-Clause
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 */
30
31
#include "config.h"
32
33
#include "cache_int.h"
34
35
#include <stdio.h>
36
#include <stdlib.h>
37
38
#include "vsl_priv.h"
39
#include "vmb.h"
40
41
#include "common/heritage.h"
42
#include "common/vsmw.h"
43
44
/* ------------------------------------------------------------
45
 * strands helpers - move elsewhere?
46
 */
47
48
static unsigned
49 1122744
strands_len(const struct strands *s)
50
{
51 1122744
        unsigned r = 0;
52
        int i;
53
54 1122744
        CHECK_OBJ_NOTNULL(s, STRANDS_MAGIC);
55 2246780
        for (i = 0; i < s->n; i++) {
56 1124036
                if (s->p[i] == NULL || *s->p[i] == '\0')
57 107587
                        continue;
58 1016449
                r += vstrlen(s->p[i]);
59 1016449
        }
60
61 1122744
        return (r);
62
}
63
64
/*
65
 * like VRT_Strands(), but truncating instead of failing for end of buffer
66
 *
67
 * returns number of bytes including NUL
68
 */
69
static unsigned
70 1126829
strands_cat(char *buf, unsigned bufl, const struct strands *s)
71
{
72 1126829
        unsigned l = 0, ll;
73
        int i;
74
75
        /* NUL-terminated */
76 1126829
        assert(bufl > 0);
77 1126829
        bufl--;
78 1126829
        CHECK_OBJ_NOTNULL(s, STRANDS_MAGIC);
79
80 2149498
        for (i = 0; i < s->n && bufl > 0; i++) {
81 1022671
                if (s->p[i] == NULL || *s->p[i] == '\0')
82 56
                        continue;
83 1022627
                ll = vmin_t(unsigned, vstrlen(s->p[i]), bufl);
84 1022627
                vmemcpy(buf, s->p[i], ll);
85 1022627
                l += ll;
86 1022627
                buf += ll;
87 1022627
                bufl -= ll;
88 1022627
        }
89 1126827
        *buf = '\0';    /* NUL-terminated */
90 1126827
        return (l + 1);
91
}
92
93
/* These cannot be struct lock, which depends on vsm/vsl working */
94
static pthread_mutex_t vsl_mtx;
95
static pthread_mutex_t vsc_mtx;
96
static pthread_mutex_t vsm_mtx;
97
98
static struct VSL_head          *vsl_head;
99
static const uint32_t           *vsl_end;
100
static uint32_t                 *vsl_ptr;
101
static unsigned                 vsl_segment_n;
102
static ssize_t                  vsl_segsize;
103
104
struct VSC_main *VSC_C_main;
105
106
static void
107 11114432
vsl_sanity(const struct vsl_log *vsl)
108
{
109
110 11114432
        CHECK_OBJ_NOTNULL(vsl, VSL_LOG_MAGIC);
111 11114432
        AN(vsl);
112 11114432
        AN(vsl->wlp);
113 11114432
        AN(vsl->wlb);
114 11114432
        AN(vsl->wle);
115 11114432
        assert(vsl->wlb <= vsl->wlp);
116 11114432
        assert(vsl->wlp <= vsl->wle);
117 11114432
}
118
119
/*--------------------------------------------------------------------
120
 * Check if the VSL_tag is masked by parameter bitmap
121
 */
122
123
static inline int
124 8785632
vsl_tag_is_masked(enum VSL_tag_e tag)
125
{
126 8785632
        volatile uint8_t *bm = &cache_param->vsl_mask[0];
127
        uint8_t b;
128
129 8785632
        assert(tag > SLT__Bogus);
130 8785632
        assert(tag < SLT__Reserved);
131 8785632
        bm += ((unsigned)tag >> 3);
132 8785632
        b = (0x80 >> ((unsigned)tag & 7));
133 8785632
        return (*bm & b);
134
}
135
136
int
137 27095
VSL_tag_is_masked(enum VSL_tag_e tag)
138
{
139 27095
        return (vsl_tag_is_masked(tag));
140
}
141
142
/*--------------------------------------------------------------------
143
 * Lay down a header fields, and return pointer to the next record
144
 */
145
146
static inline uint32_t *
147 6876380
vsl_hdr(enum VSL_tag_e tag, uint32_t *p, unsigned len, vxid_t vxid)
148
{
149
150 6876380
        AZ((uintptr_t)p & 0x3);
151 6876380
        assert(tag > SLT__Bogus);
152 6876380
        assert(tag < SLT__Reserved);
153 6876380
        AZ(len & ~VSL_LENMASK);
154
155 6876380
        p[2] = vxid.vxid >> 32;
156 6876380
        p[1] = vxid.vxid;
157 13752760
        p[0] = (((unsigned)tag & VSL_IDMASK) << VSL_IDSHIFT) |
158 6876380
             (VSL_VERSION_3 << VSL_VERSHIFT) |
159 6876380
             len;
160 6876380
        return (VSL_END(p, len));
161
}
162
163
/*--------------------------------------------------------------------
164
 * Space available in a VSL buffer when accounting for overhead
165
 */
166
167
static unsigned
168 1672706
vsl_space(const struct vsl_log *vsl)
169
{
170
        ptrdiff_t mlen;
171
172 1672706
        mlen = vsl->wle - vsl->wlp;
173 1672706
        assert(mlen >= 0);
174 1672706
        if (mlen < VSL_OVERHEAD + 1)
175 42
                return (0);
176 1672664
        mlen -= VSL_OVERHEAD;
177 1672664
        mlen *= sizeof *vsl->wlp;
178 1672664
        if (mlen > cache_param->vsl_reclen)
179 1672233
                mlen = cache_param->vsl_reclen;
180 1672664
        return(mlen);
181 1672706
}
182
183
/*--------------------------------------------------------------------
184
 * Wrap the VSL buffer
185
 */
186
187
static void
188 0
vsl_wrap(void)
189
{
190
191 0
        assert(vsl_ptr >= vsl_head->log);
192 0
        assert(vsl_ptr < vsl_end);
193 0
        vsl_segment_n += VSL_SEGMENTS - (vsl_segment_n % VSL_SEGMENTS);
194 0
        assert(vsl_segment_n % VSL_SEGMENTS == 0);
195 0
        vsl_head->offset[0] = 0;
196 0
        vsl_head->log[0] = VSL_ENDMARKER;
197 0
        VWMB();
198 0
        if (vsl_ptr != vsl_head->log) {
199 0
                *vsl_ptr = VSL_WRAPMARKER;
200 0
                vsl_ptr = vsl_head->log;
201 0
        }
202 0
        vsl_head->segment_n = vsl_segment_n;
203 0
        VSC_C_main->shm_cycles++;
204 0
}
205
206
/*--------------------------------------------------------------------
207
 * Reserve bytes for a record, wrap if necessary
208
 */
209
210
static uint32_t *
211 2053599
vsl_get(unsigned len, unsigned records, unsigned flushes)
212
{
213
        uint32_t *p;
214
        int err;
215
216 2053599
        err = pthread_mutex_trylock(&vsl_mtx);
217 2053599
        if (err == EBUSY) {
218 11687
                PTOK(pthread_mutex_lock(&vsl_mtx));
219 11687
                VSC_C_main->shm_cont++;
220 11687
        } else {
221 2041912
                AZ(err);
222
        }
223 2053599
        assert(vsl_ptr < vsl_end);
224 2053599
        AZ((uintptr_t)vsl_ptr & 0x3);
225
226 2053599
        VSC_C_main->shm_writes++;
227 2053599
        VSC_C_main->shm_flushes += flushes;
228 2053599
        VSC_C_main->shm_records += records;
229 2053599
        VSC_C_main->shm_bytes +=
230 2053599
            VSL_BYTES(VSL_OVERHEAD + VSL_WORDS((uint64_t)len));
231
232
        /* Wrap if necessary */
233 2053599
        if (VSL_END(vsl_ptr, len) >= vsl_end)
234 0
                vsl_wrap();
235
236 2053599
        p = vsl_ptr;
237 2053599
        vsl_ptr = VSL_END(vsl_ptr, len);
238 2053599
        assert(vsl_ptr < vsl_end);
239 2053599
        AZ((uintptr_t)vsl_ptr & 0x3);
240
241 2053599
        *vsl_ptr = VSL_ENDMARKER;
242
243 2053662
        while ((vsl_ptr - vsl_head->log) / vsl_segsize >
244 2053662
            vsl_segment_n % VSL_SEGMENTS) {
245 63
                vsl_segment_n++;
246 63
                vsl_head->offset[vsl_segment_n % VSL_SEGMENTS] =
247 63
                    vsl_ptr - vsl_head->log;
248
        }
249
250 2053599
        PTOK(pthread_mutex_unlock(&vsl_mtx));
251
        /* Implicit VWMB() in mutex op ensures ENDMARKER and new table
252
           values are seen before new segment number */
253 2053599
        vsl_head->segment_n = vsl_segment_n;
254
255 2053599
        return (p);
256
}
257
258
/*--------------------------------------------------------------------
259
 * Stick a finished record into VSL.
260
 */
261
262
static void
263 1371977
vslr(enum VSL_tag_e tag, vxid_t vxid, const char *b, unsigned len)
264
{
265
        uint32_t *p;
266
        unsigned mlen;
267
268 1371977
        mlen = cache_param->vsl_reclen;
269
270
        /* Truncate */
271 1371977
        if (len > mlen)
272 0
                len = mlen;
273
274 1371977
        p = vsl_get(len, 1, 0);
275
276 1371977
        vmemcpy(p + VSL_OVERHEAD, b, len);
277
278
        /*
279
         * the vxid needs to be written before the barrier to
280
         * ensure it is valid when vsl_hdr() marks the record
281
         * ready by writing p[0]
282
         */
283 1371977
        p[2] = vxid.vxid >> 32;
284 1371977
        p[1] = vxid.vxid;
285 1371977
        VWMB();
286 1371977
        (void)vsl_hdr(tag, p, len, vxid);
287 1371977
}
288
289
/*--------------------------------------------------------------------
290
 * Add a unbuffered record to VSL
291
 *
292
 * NB: This variant should be used sparingly and only for low volume
293
 * NB: since it significantly adds to the mutex load on the VSL.
294
 */
295
296
void
297 2220560
VSLv(enum VSL_tag_e tag, vxid_t vxid, const char *fmt, va_list ap)
298
{
299 2220560
        unsigned n, mlen = cache_param->vsl_reclen;
300 2220560
        char buf[mlen];
301
302 2220560
        AN(fmt);
303 2220560
        if (vsl_tag_is_masked(tag))
304 852827
                return;
305
306 1367733
        if (strchr(fmt, '%') == NULL) {
307 25059
                vslr(tag, vxid, fmt, vstrlen(fmt) + 1);
308 25059
        } else {
309 1342674
                n = vsnprintf(buf, mlen, fmt, ap);
310 1342674
                n = vmin(n, mlen - 1);
311 1342674
                buf[n++] = '\0'; /* NUL-terminated */
312 1342674
                vslr(tag, vxid, buf, n);
313
        }
314
315 2220560
}
316
317
void
318 4242
VSLs(enum VSL_tag_e tag, vxid_t vxid, const struct strands *s)
319
{
320 4242
        unsigned n, mlen = cache_param->vsl_reclen;
321 4242
        char buf[mlen];
322
323 4242
        if (vsl_tag_is_masked(tag))
324 0
                return;
325
326 4242
        n = strands_cat(buf, mlen, s);
327
328 4242
        vslr(tag, vxid, buf, n);
329 4242
}
330
331
void
332 2175591
VSL(enum VSL_tag_e tag, vxid_t vxid, const char *fmt, ...)
333
{
334
        va_list ap;
335
336 2175591
        va_start(ap, fmt);
337 2175591
        VSLv(tag, vxid, fmt, ap);
338 2175591
        va_end(ap);
339 2175591
}
340
341
/*--------------------------------------------------------------------*/
342
343
void
344 858048
VSL_Flush(struct vsl_log *vsl, int overflow)
345
{
346
        uint32_t *p;
347
        unsigned l;
348
349 858048
        vsl_sanity(vsl);
350 858048
        l = pdiff(vsl->wlb, vsl->wlp);
351 858048
        if (l == 0)
352 178633
                return;
353
354 679415
        assert(l >= 8);
355
356 679415
        p = vsl_get(l, vsl->wlr, overflow);
357
358 679415
        vmemcpy(p + VSL_OVERHEAD, vsl->wlb, l);
359 679415
        p[1] = l;
360 679415
        VWMB();
361 679415
        p[0] = ((((unsigned)SLT__Batch & 0xff) << VSL_IDSHIFT));
362 679415
        vsl->wlp = vsl->wlb;
363 679415
        vsl->wlr = 0;
364 858048
}
365
366
/*--------------------------------------------------------------------
367
 * Buffered VSLs
368
 */
369
370
static char *
371 5478128
vslb_get(struct vsl_log *vsl, enum VSL_tag_e tag, unsigned *length)
372
{
373 5478128
        unsigned mlen = cache_param->vsl_reclen;
374
        char *retval;
375
376 5478128
        vsl_sanity(vsl);
377 5478128
        if (*length < mlen)
378 5463520
                mlen = *length;
379
380 5478128
        if (VSL_END(vsl->wlp, mlen) > vsl->wle)
381 210
                VSL_Flush(vsl, 1);
382
383 5478128
        retval = VSL_DATA(vsl->wlp);
384
385
        /* If it still doesn't fit, truncate */
386 5478128
        if (VSL_END(vsl->wlp, mlen) > vsl->wle)
387 42
                mlen = vsl_space(vsl);
388
389 5478128
        vsl->wlp = vsl_hdr(tag, vsl->wlp, mlen, vsl->wid);
390 5478128
        vsl->wlr++;
391 5478128
        *length = mlen;
392 5478128
        return (retval);
393
}
394
395
static void
396 2685040
vslb_simple(struct vsl_log *vsl, enum VSL_tag_e tag,
397
    unsigned length, const char *str)
398
{
399
        char *p;
400
401 2685040
        if (length == 0)
402 211852
                length = vstrlen(str);
403 2685040
        length += 1; // NUL
404 2685040
        p = vslb_get(vsl, tag, &length);
405 2685040
        vmemcpy(p, str, length - 1);
406 2685040
        p[length - 1] = '\0';
407
408 2685040
        if (DO_DEBUG(DBG_SYNCVSL))
409 247749
                VSL_Flush(vsl, 0);
410 2685040
}
411
412
/*--------------------------------------------------------------------
413
 * VSL-buffered-txt
414
 */
415
416
void
417 3082278
VSLbt(struct vsl_log *vsl, enum VSL_tag_e tag, txt t)
418
{
419
420 3082278
        Tcheck(t);
421 3082278
        if (vsl_tag_is_masked(tag))
422 466955
                return;
423
424 2615323
        vslb_simple(vsl, tag, Tlen(t), t.b);
425 3082278
}
426
427
/*--------------------------------------------------------------------
428
 * VSL-buffered-strands
429
 */
430
void
431 1327538
VSLbs(struct vsl_log *vsl, enum VSL_tag_e tag, const struct strands *s)
432
{
433
        unsigned l;
434
        char *p;
435
436 1327538
        if (vsl_tag_is_masked(tag))
437 204762
                return;
438
439 1122776
        l = strands_len(s) + 1;
440 1122776
        p = vslb_get(vsl, tag, &l);
441
442 1122776
        (void)strands_cat(p, l, s);
443
444 1122776
        if (DO_DEBUG(DBG_SYNCVSL))
445 98767
                VSL_Flush(vsl, 0);
446 1327538
}
447
448
/*--------------------------------------------------------------------
449
 * VSL-buffered
450
 */
451
452
void
453 2065955
VSLbv(struct vsl_log *vsl, enum VSL_tag_e tag, const char *fmt, va_list ap)
454
{
455
        char *p, *p1;
456 2065955
        unsigned n = 0, mlen;
457
        va_list ap2;
458
459 2065955
        AN(fmt);
460 2065955
        if (vsl_tag_is_masked(tag))
461 323341
                return;
462
463
        /*
464
         * If there are no printf-expansions, don't waste time expanding them
465
         */
466 1742614
        if (strchr(fmt, '%') == NULL) {
467 69656
                vslb_simple(vsl, tag, 0, fmt);
468 69656
                return;
469
        }
470
471
        /*
472
         * If the format is trivial, deal with it directly
473
         */
474 1672958
        if (!vstrcmp(fmt, "%s")) {
475 168
                p1 = va_arg(ap, char *);
476 168
                vslb_simple(vsl, tag, 0, p1);
477 168
                return;
478
        }
479
480 1672790
        vsl_sanity(vsl);
481
482 1672790
        mlen = vsl_space(vsl);
483
484
        // First attempt, only if any space at all
485 1672790
        if (mlen > 0) {
486 1671939
                p = VSL_DATA(vsl->wlp);
487 1671939
                va_copy(ap2, ap);
488 1671939
                n = vsnprintf(p, mlen, fmt, ap2);
489 1671939
                va_end(ap2);
490 1671939
        }
491
492
        // Second attempt, if a flush might help
493 1672790
        if (mlen == 0 || (n + 1 > mlen && n + 1 <= cache_param->vsl_reclen)) {
494 1359
                VSL_Flush(vsl, 1);
495 1359
                mlen = vsl_space(vsl);
496 1359
                p = VSL_DATA(vsl->wlp);
497 1359
                n = vsnprintf(p, mlen, fmt, ap);
498 1359
        }
499 1673000
        if (n + 1 < mlen)
500 1667390
                mlen = n + 1;
501 1673000
        (void)vslb_get(vsl, tag, &mlen);
502
503 1673000
        if (DO_DEBUG(DBG_SYNCVSL))
504 188700
                VSL_Flush(vsl, 0);
505 2066165
}
506
507
void
508 1978822
VSLb(struct vsl_log *vsl, enum VSL_tag_e tag, const char *fmt, ...)
509
{
510
        va_list ap;
511
512 1978822
        vsl_sanity(vsl);
513 1978822
        va_start(ap, fmt);
514 1978822
        VSLbv(vsl, tag, fmt, ap);
515 1978822
        va_end(ap);
516 1978822
}
517
518
#define Tf6 "%ju.%06ju"
519
#define Ta6(t) (uintmax_t)floor((t)), (uintmax_t)floor((t) * 1e6) % 1000000U
520
521
void
522 750670
VSLb_ts(struct vsl_log *vsl, const char *event, vtim_real first,
523
    vtim_real *pprev, vtim_real now)
524
{
525
526
        /*
527
         * XXX: Make an option to turn off some unnecessary timestamp
528
         * logging. This must be done carefully because some functions
529
         * (e.g. V1L_Open) takes the last timestamp as its initial
530
         * value for timeout calculation.
531
         */
532 750670
        vsl_sanity(vsl);
533 750670
        AN(event);
534 750670
        AN(pprev);
535 750670
        assert(!isnan(now) && now != 0.);
536 1501340
        VSLb(vsl, SLT_Timestamp, "%s: " Tf6 " " Tf6 " " Tf6,
537 750670
            event, Ta6(now), Ta6(now - first), Ta6(now - *pprev));
538 750670
        *pprev = now;
539 750670
}
540
541
void
542 401270
VSLb_ts_req(struct req *req, const char *event, vtim_real now)
543
{
544
545 401270
        if (isnan(req->t_first) || req->t_first == 0.)
546 7775
                req->t_first = req->t_prev = now;
547 401268
        VSLb_ts(req->vsl, event, req->t_first, &req->t_prev, now);
548 401268
}
549
550
void
551 349525
VSLb_ts_busyobj(struct busyobj *bo, const char *event, vtim_real now)
552
{
553
554 349525
        if (isnan(bo->t_first) || bo->t_first == 0.)
555 51796
                bo->t_first = bo->t_prev = now;
556 349513
        VSLb_ts(bo->vsl, event, bo->t_first, &bo->t_prev, now);
557 349513
}
558
559
void
560 63483
VSLb_bin(struct vsl_log *vsl, enum VSL_tag_e tag, ssize_t len, const void *ptr)
561
{
562
        unsigned mlen;
563
        char *p;
564
565 63483
        vsl_sanity(vsl);
566 63483
        AN(ptr);
567 63483
        if (vsl_tag_is_masked(tag))
568 31962
                return;
569 31521
        mlen = cache_param->vsl_reclen;
570
571
        /* Truncate */
572 31521
        len = vmin_t(ssize_t, len, mlen);
573
574 31521
        assert(vsl->wlp <= vsl->wle);
575
576
        /* Flush if necessary */
577 31521
        if (VSL_END(vsl->wlp, len) > vsl->wle)
578 189
                VSL_Flush(vsl, 1);
579 31521
        assert(VSL_END(vsl->wlp, len) <= vsl->wle);
580 31521
        p = VSL_DATA(vsl->wlp);
581 31521
        vmemcpy(p, ptr, len);
582 31521
        vsl->wlp = vsl_hdr(tag, vsl->wlp, len, vsl->wid);
583 31521
        assert(vsl->wlp <= vsl->wle);
584 31521
        vsl->wlr++;
585
586 31521
        if (DO_DEBUG(DBG_SYNCVSL))
587 13167
                VSL_Flush(vsl, 0);
588 63483
}
589
590
/*--------------------------------------------------------------------
591
 * Setup a VSL buffer
592
 */
593
594
void
595 182827
VSL_Init(struct vsl_log *vsl, void *ptr, size_t len)
596
{
597
598 182827
        AN(vsl);
599 182827
        AN(ptr);
600 182827
        AN(len);
601
602 182827
        INIT_OBJ(vsl, VSL_LOG_MAGIC);
603 182827
        vsl->wlp = ptr;
604 182827
        vsl->wlb = ptr;
605 182827
        vsl->wle = ptr;
606 182827
        vsl->wle += len / sizeof(*vsl->wle);
607 182827
        vsl->wlr = 0;
608 182827
        vsl->wid = NO_VXID;
609 182827
        vsl_sanity(vsl);
610 182827
}
611
612
void
613 62613
VSL_Alloc(struct vsl_log *vsl)
614
{
615 62613
        size_t len = cache_param->vsl_buffer;
616 62613
        void *ptr = malloc(len);
617 62613
        AN(ptr);
618 62613
        VSL_Init(vsl, ptr, len);
619 62613
        vsl->flags |= VSL_LOG_F_MALLOCED;
620 62613
}
621
622
void
623 41244
VSL_Free(struct vsl_log *vsl)
624
{
625
626 41244
        CHECK_OBJ_NOTNULL(vsl, VSL_LOG_MAGIC);
627 41244
        assert(vsl->flags & VSL_LOG_F_MALLOCED);
628 41244
        free(vsl->wlb);
629 41244
        memset(vsl, 0, sizeof *vsl);
630 41244
}
631
632
/*--------------------------------------------------------------------*/
633
634
void
635 2130
VSL_ChgId(struct vsl_log *vsl, const char *typ, const char *why, vxid_t vxid)
636
{
637
        vxid_t ovxid;
638
639 2130
        vsl_sanity(vsl);
640 2130
        ovxid = vsl->wid;
641 2130
        VSLb(vsl, SLT_Link, "%s %ju %s", typ, VXID(vxid), why);
642 2130
        VSL_End(vsl);
643 2130
        vsl->wid = vxid;
644 2130
        VSLb(vsl, SLT_Begin, "%s %ju %s", typ, VXID(ovxid), why);
645 2130
}
646
647
/*--------------------------------------------------------------------*/
648
649
void
650 142036
VSL_End(struct vsl_log *vsl)
651
{
652
        txt t;
653 142036
        char p[] = "";
654
655 142036
        vsl_sanity(vsl);
656 142036
        assert(!IS_NO_VXID(vsl->wid));
657 142036
        t.b = p;
658 142036
        t.e = p;
659 142036
        VSLbt(vsl, SLT_End, t);
660 142036
        VSL_Flush(vsl, 0);
661 142036
        vsl->wid = NO_VXID;
662 142036
}
663
664
static void v_matchproto_(vsm_lock_f)
665 829914
vsm_vsc_lock(void)
666
{
667 829914
        PTOK(pthread_mutex_lock(&vsc_mtx));
668 829914
}
669
670
static void v_matchproto_(vsm_lock_f)
671 829901
vsm_vsc_unlock(void)
672
{
673 829901
        PTOK(pthread_mutex_unlock(&vsc_mtx));
674 829901
}
675
676
static void v_matchproto_(vsm_lock_f)
677 1058805
vsm_vsmw_lock(void)
678
{
679 1058805
        PTOK(pthread_mutex_lock(&vsm_mtx));
680 1058805
}
681
682
static void v_matchproto_(vsm_lock_f)
683 1058792
vsm_vsmw_unlock(void)
684
{
685 1058792
        PTOK(pthread_mutex_unlock(&vsm_mtx));
686 1058792
}
687
688
/*--------------------------------------------------------------------*/
689
690
void
691 20888
VSM_Init(void)
692
{
693
        unsigned u;
694
695 20888
        assert(UINT_MAX % VSL_SEGMENTS == VSL_SEGMENTS - 1);
696
697 20888
        PTOK(pthread_mutex_init(&vsl_mtx, &mtxattr_errorcheck));
698 20888
        PTOK(pthread_mutex_init(&vsc_mtx, &mtxattr_errorcheck));
699 20888
        PTOK(pthread_mutex_init(&vsm_mtx, &mtxattr_errorcheck));
700
701 20888
        vsc_lock = vsm_vsc_lock;
702 20888
        vsc_unlock = vsm_vsc_unlock;
703 20888
        vsmw_lock = vsm_vsmw_lock;
704 20888
        vsmw_unlock = vsm_vsmw_unlock;
705
706 20888
        heritage.proc_vsmw = VSMW_New(heritage.vsm_fd, 0640, "_.index");
707 20888
        AN(heritage.proc_vsmw);
708
709 20888
        VSC_C_main = VSC_main_New(NULL, NULL, "");
710 20888
        AN(VSC_C_main);
711
712 20888
        AN(heritage.proc_vsmw);
713 41776
        vsl_head = VSMW_Allocf(heritage.proc_vsmw, NULL, VSL_CLASS,
714 20888
            cache_param->vsl_space, VSL_CLASS);
715 20888
        AN(vsl_head);
716 41776
        vsl_segsize = ((cache_param->vsl_space - sizeof *vsl_head) /
717 20888
            sizeof *vsl_end) / VSL_SEGMENTS;
718 20888
        vsl_end = vsl_head->log + vsl_segsize * VSL_SEGMENTS;
719
        /* Make segment_n always overflow on first log wrap to make any
720
           problems with regard to readers on that event visible */
721 20888
        vsl_segment_n = UINT_MAX - (VSL_SEGMENTS - 1);
722 20888
        AZ(vsl_segment_n % VSL_SEGMENTS);
723 20888
        vsl_ptr = vsl_head->log;
724 20888
        *vsl_ptr = VSL_ENDMARKER;
725
726 20888
        memset(vsl_head, 0, sizeof *vsl_head);
727 20888
        vsl_head->segsize = vsl_segsize;
728 20888
        vsl_head->offset[0] = 0;
729 20888
        vsl_head->segment_n = vsl_segment_n;
730 167104
        for (u = 1; u < VSL_SEGMENTS; u++)
731 146216
                vsl_head->offset[u] = -1;
732 20888
        VWMB();
733 20888
        vmemcpy(vsl_head->marker, VSL_HEAD_MARKER, sizeof vsl_head->marker);
734 20888
}