Commit a0993006 authored by Martin Blix Grydeland's avatar Martin Blix Grydeland

Beginnings of new VSL api

Remove automagic reopening logic from vsl

Make vsl use the new VSL_head structure

Remove most of the old functionality
parent ef23d995
......@@ -28,131 +28,129 @@
*
* This is the public API for the VSL access.
*
* VSL is a "subclass" of VSM.
*
* VSL can either read from VSM or from a file.
*
* When reading from a file, the filename is passed in with:
* VSL_Arg(vd, "r", "/some/file");
* and once VSL_Dispatch()/VSL_NextSLT() will indicate EOF by returning -2.
* Another file can then be opened with VSL_Arg() and processed.
*
*/
#ifndef VAPI_VSL_H_INCLUDED
#define VAPI_VSL_H_INCLUDED
#include "vapi/vsl_int.h"
#include <stdio.h>
struct VSM_data;
#include "vapi/vsm.h"
#include "vapi/vsl_int.h"
/*---------------------------------------------------------------------
* VSL level access functions
*/
#define VSL_ARGS "i:x:"
#define VSL_ARGS "bCcdI:i:k:n:r:s:X:x:m:"
#define VSL_b_USAGE "[-b]"
#define VSL_c_USAGE "[-c]"
#define VSL_C_USAGE "[-C]"
#define VSL_d_USAGE "[-d]"
#define VSL_i_USAGE "[-i tag]"
#define VSL_I_USAGE "[-I regexp]"
#define VSL_k_USAGE "[-k keep]"
#define VSL_m_USAGE "[-m tag:regex]"
#define VSL_n_USAGE VSM_n_USAGE
#define VSL_r_USAGE "[-r file]"
#define VSL_s_USAGE "[-s skip]"
#define VSL_x_USAGE "[-x tag]"
#define VSL_X_USAGE "[-X regexp]"
#define VSL_USAGE "[-bCcd] " \
#define VSL_USAGE "[...] " \
VSL_i_USAGE " " \
VSL_I_USAGE " " \
VSL_k_USAGE " " \
VSL_m_USAGE " " \
VSL_n_USAGE " " \
VSL_r_USAGE " " \
VSL_s_USAGE " " \
VSL_X_USAGE " " \
VSL_x_USAGE
int VSL_Arg(struct VSM_data *vd, int arg, const char *opt);
struct VSL_data;
struct VSL_cursor {
const uint32_t *ptr; /* Record pointer */
};
extern const char *VSL_tags[256];
/*
* Tag to string array. Contains NULL for invalid tags.
*/
int VSL_Name2Tag(const char *name, int l);
/*
* Convert string to tag number (= enum VSL_tag_e)
*
* Return values:
* >=0: Tag number
* -1: No tag matches
* -2: Multiple tags match substring
*/
struct VSL_data *VSL_New(void);
int VSL_Arg(struct VSL_data *vsl, int opt, const char *arg);
/*
* Handle standard log-presenter arguments
* Return:
* -1 error, VSM_Error() returns diagnostic string
* -1 error, VSL_Error() returns diagnostic string
* 0 not handled
* 1 Handled.
*/
typedef int VSL_handler_f(void *priv, enum VSL_tag_e tag, unsigned fd,
unsigned len, unsigned spec, const char *ptr, uint64_t bitmap);
void VSL_Delete(struct VSL_data *vsl);
/*
* This is the call-back function you must provide.
* priv is whatever you asked for it to be.
* tag is the SLT_mumble tag
* fd is the filedescriptor associated with this record
* len is the length of the data at ptr
* spec are the VSL_S_* flags
* ptr points to the data, beware of non-printables.
* bitmap is XXX ???
* Delete a VSL context, freeing up the resources
*/
#define VSL_S_CLIENT (1 << 0)
#define VSL_S_BACKEND (1 << 1)
VSL_handler_f VSL_H_Print;
const char *VSL_Error(const struct VSL_data *vsl);
/*
* This call-back function will printf() the record to the FILE *
* specified in priv.
* Return the latest error message.
*/
void VSL_Select(struct VSM_data *vd, enum VSL_tag_e tag);
void VSL_ResetError(struct VSL_data *vsl);
/*
* This adds tags which shall always be selected, similar to using
* the '-i' option.
* VSL_Select()/-i takes precedence over all other filtering.
* Reset any error message.
*/
int VSL_Dispatch(struct VSM_data *vd, VSL_handler_f *func, void *priv);
struct VSL_cursor *VSL_CursorVSM(struct VSL_data *vsl, struct VSM_data *vsm,
int tail);
/*
* Set the cursor pointed to by cursor up as a raw cursor in the
* log. If tail is non-zero, it will point to the tail of the
* log. Is tail is zero, it will point close to the head of the
* log, at least 2 segments away from the head.
*
* Return values:
* non-NULL: Pointer to cursor
* NULL: Error, see VSL_Error
*/
struct VSL_cursor *VSL_CursorFile(struct VSL_data *vsl, const char *name);
/*
* Call func(priv, ...) for all filtered VSL records.
* Create a cursor pointing to the beginning of the binary VSL log
* in file name. If name is '-' reads from stdin.
*
* Return values:
* !=0: Non-zero return value from func()
* 0: no VSL records.
* -1: VSL chunk was abandoned.
* -2: End of file (-r) / -k arg exhausted / "done"
* non-NULL: Pointer to cursor
* NULL: Error, see VSL_Error
*/
int VSL_NextSLT(struct VSM_data *lh, uint32_t **pp, uint64_t *bitmap);
void VSL_DeleteCursor(struct VSL_cursor *c);
/*
* Return raw pointer to next filtered VSL record.
*
* Return values:
* 1: Valid VSL record at *pp
* 0: no VSL records
* -1: VSL chunk was abandoned
* -2: End of file (-r) / -k arg exhausted / "done"
* Delete the cursor pointed to by c
*/
int VSL_Matched(struct VSM_data *vd, uint64_t bitmap);
int VSL_Next(struct VSL_cursor *c);
/*
* Return raw pointer to next VSL record.
*
* Return values:
* 1: Cursor points to next log record
* 0: End of log
* -1: End of file (-r) (XXX / -k arg exhausted / "done")
* -2: Remote abandoned or closed
* -3: Overrun
* -4: I/O read error - see errno
*/
int VSL_Name2Tag(const char *name, int l);
int VSL_Match(struct VSL_data *vsl, const struct VSL_cursor *c);
/*
* Convert string to tag number (= enum VSL_tag_e)
* Returns true if the record pointed to by cursor matches the
* record current record selectors
*
* Return values:
* >=0: Tag number
* -1: No tag matches
* -2: Multiple tags match substring
* Return value:
* 1: Match
* 0: No match
*/
extern const char *VSL_tags[256];
int VSL_Print(struct VSL_data *vsl, const struct VSL_cursor *c, void *file);
/*
* Tag to string array. Contains NULL for invalid tags.
* Print the log record pointed to by cursor to stream.
*
* Return values:
* 0: OK
* -5: I/O write error - see errno
*/
#endif /* VAPI_VSL_H_INCLUDED */
......@@ -88,6 +88,7 @@ struct VSL_head {
#define VSL_CLIENT(ptr) (((ptr)[1]) & VSL_CLIENTMARKER)
#define VSL_BACKEND(ptr) (((ptr)[1]) & VSL_BACKENDMARKER)
#define VSL_DATA(ptr) ((char*)((ptr)+2))
#define VSL_CDATA(ptr) ((const char*)((ptr)+2))
#define VSL_ENDMARKER (((uint32_t)SLT__Reserved << 24) | 0x454545) /* "EEE" */
#define VSL_WRAPMARKER (((uint32_t)SLT__Reserved << 24) | 0x575757) /* "WWW" */
......
......@@ -148,7 +148,8 @@ int VSM_StillValid(const struct VSM_data *vd, struct VSM_fantom *vf);
* Return:
* 0: fantom is not valid any more.
* 1: fantom is still the same.
* 2: a fantom with same dimensions exist, check class/type/ident
* 2: a fantom with same dimensions exist in same position,
* check class/type/ident
*/
int VSM_Get(const struct VSM_data *vd, struct VSM_fantom *vf,
......
......@@ -26,6 +26,7 @@ libvarnishapi_la_SOURCES = \
../libvarnish/vsha256.c \
vsm.c \
vsl_arg.c \
vsl_cursor.c \
vsl.c \
vsc.c \
libvarnishapi.map
......
......@@ -95,5 +95,15 @@ LIBVARNISHAPI_1.3 {
VSC_MainValid;
VSC_IterValid;
VSC_LevelDesc;
VSL_New;
VSL_Delete;
VSL_Error;
VSL_ResetError;
VSL_CursorVSM;
VSL_CursorFile;
VSL_DeleteCursor;
VSL_Next;
VSL_Match;
VSL_Print;
# Variables:
} LIBVARNISHAPI_1.0;
This diff is collapsed.
/*-
* Copyright (c) 2006 Verdens Gang AS
* Copyright (c) 2006-2011 Varnish Software AS
* Copyright (c) 2006-2013 Varnish Software AS
* All rights reserved.
*
* Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
* Author: Martin Blix Grydeland <martin@varnish-software.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
......@@ -28,64 +29,38 @@
*
*/
#include "vdef.h"
#include "vqueue.h"
#include "vapi/vsm.h"
#define SLEEP_USEC (50*1000)
#define TIMEOUT_USEC (5*1000*1000)
#define VSL_FILE_HEAD "VSL"
int vsl_diag(struct VSL_data *vsl, const char *fmt, ...)
__printflike(2, 3);
struct vsl_re_match {
unsigned magic;
#define VSL_RE_MATCH_MAGIC 0x4013151e
int tag;
vre_t *re;
VTAILQ_ENTRY(vsl_re_match) next;
};
struct vsl {
unsigned magic;
#define VSL_MAGIC 0x7a31db38
struct VSM_fantom vf;
/* Stuff relating the log records below here */
volatile uint32_t *log_start;
volatile uint32_t *log_end;
volatile uint32_t *log_ptr;
typedef void vslc_delete_f(void *);
typedef int vslc_next_f(void *);
volatile uint32_t last_seq;
/* for -r option */
int r_fd;
unsigned rbuflen;
uint32_t *rbuf;
int b_opt;
int c_opt;
int d_opt;
struct vslc {
struct VSL_cursor c;
unsigned magic;
#define VSLC_MAGIC 0x5007C0DE
unsigned flags;
#define F_SEEN_IX (1 << 0)
vslc_delete_f *delete;
vslc_next_f *next;
};
/*
* Bit map of programatically selected tags, that cannot be suppressed.
* This way programs can make sure they will see certain tags, even
* if the user tries to supress them with -x/-X
*/
struct vbitmap *vbm_select; /* index: tag */
struct VSL_data {
unsigned magic;
#undef VSL_MAGIC
#define VSL_MAGIC 0x8E6C92AA
/* Bit map of tags selected/supressed with -[iIxX] options */
struct vbitmap *vbm_supress; /* index: tag */
struct vsb *diag;
int regflags;
vre_t *regincl;
vre_t *regexcl;
int num_matchers;
VTAILQ_HEAD(, vsl_re_match) matchers;
unsigned flags;
#define F_SEEN_ix (1 << 0)
unsigned long skip;
unsigned long keep;
/* Bitmaps of -ix selected tags */
struct vbitmap *vbm_select;
struct vbitmap *vbm_supress;
};
struct vsl *vsl_Setup(struct VSM_data *vd);
......@@ -83,71 +83,20 @@ VSL_Name2Tag(const char *name, int l)
return (n);
}
/*--------------------------------------------------------------------*/
static int
vsl_r_arg(struct VSM_data *vd, const char *opt)
{
struct vsl *vsl = vsl_Setup(vd);
if (vsl->r_fd > STDIN_FILENO)
(void)close(vsl->r_fd);
if (!strcmp(opt, "-"))
vsl->r_fd = STDIN_FILENO;
else
vsl->r_fd = open(opt, O_RDONLY);
if (vsl->r_fd < 0)
return (vsm_diag(vd,
"Could not open %s: %s", opt, strerror(errno)));
if (vsl->rbuflen == 0) {
vsl->rbuflen = BUFSIZ;
vsl->rbuf = malloc(vsl->rbuflen);
AN(vsl->rbuf);
}
return (1);
}
/*--------------------------------------------------------------------*/
static int
vsl_IX_arg(struct VSM_data *vd, const char *opt, int arg)
vsl_ix_arg(struct VSL_data *vsl, int opt, const char *arg)
{
struct vsl *vsl = vsl_Setup(vd);
vre_t **rp;
const char *error;
int erroroffset;
CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
if (arg == 'I')
rp = &vsl->regincl;
else
rp = &vsl->regexcl;
if (*rp != NULL)
return (vsm_diag(vd, "Option %c can only be given once", arg));
*rp = VRE_compile(opt, vsl->regflags, &error, &erroroffset);
if (*rp == NULL)
return (vsm_diag(vd, "Illegal regex: %s\n", error));
return (1);
}
/*--------------------------------------------------------------------*/
static int
vsl_ix_arg(struct VSM_data *vd, const char *opt, int arg)
{
struct vsl *vsl = vsl_Setup(vd);
int i, l;
const char *b, *e;
CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
/* If first option is 'i', set all bits for supression */
if (arg == 'i' && !(vsl->flags & F_SEEN_IX))
if (opt == 'i' && !(vsl->flags & F_SEEN_ix))
for (i = 0; i < 256; i++)
vbit_set(vsl->vbm_supress, i);
vsl->flags |= F_SEEN_IX;
vsl->flags |= F_SEEN_ix;
for (b = opt; *b; b = e) {
for (b = arg; *b; b = e) {
while (isspace(*b))
b++;
e = strchr(b, ',');
......@@ -160,123 +109,28 @@ vsl_ix_arg(struct VSM_data *vd, const char *opt, int arg)
l--;
i = VSL_Name2Tag(b, l);
if (i >= 0) {
if (arg == 'x')
if (opt == 'x')
vbit_set(vsl->vbm_supress, i);
else
vbit_clr(vsl->vbm_supress, i);
} else if (i == -2) {
return (vsm_diag(vd,
"\"%*.*s\" matches multiple tags\n", l, l, b));
return (vsl_diag(vsl,
"-%c: \"%*.*s\" matches multiple tags\n",
(char)opt, l, l, b));
} else {
return (vsm_diag(vd,
"Could not match \"%*.*s\" to any tag\n", l, l, b));
return (vsl_diag(vsl,
"-%c: Could not match \"%*.*s\" to any tag\n",
(char)opt, l, l, b));
}
}
return (1);
}
/*--------------------------------------------------------------------*/
static int
vsl_m_arg(struct VSM_data *vd, const char *opt)
{
struct vsl *vsl = vsl_Setup(vd);
struct vsl_re_match *m;
const char *error;
char *o, *regex;
int erroroffset;
CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
if (!strchr(opt, ':'))
return (vsm_diag(vd,
"No : found in -m option %s\n", opt));
o = strdup(opt);
AN(o);
regex = strchr(o, ':');
*regex = '\0';
regex++;
ALLOC_OBJ(m, VSL_RE_MATCH_MAGIC);
AN(m);
m->tag = VSL_Name2Tag(o, -1);
if (m->tag < 0) {
(void)vsm_diag(vd, "Illegal tag %s specified\n", o);
free(o);
FREE_OBJ(m);
return (-1);
}
/* Get tag, regex */
m->re = VRE_compile(regex, vsl->regflags, &error, &erroroffset);
if (m->re == NULL) {
(void)vsm_diag(vd, "Illegal regex: %s\n", error);
free(o);
FREE_OBJ(m);
return (-1);
}
vsl->num_matchers++;
VTAILQ_INSERT_TAIL(&vsl->matchers, m, next);
free(o);
return (1);
}
/*--------------------------------------------------------------------*/
static int
vsl_s_arg(struct VSM_data *vd, const char *opt)
{
struct vsl *vsl = vsl_Setup(vd);
char *end;
CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
if (*opt == '\0')
return (vsm_diag(vd, "number required for -s\n"));
vsl->skip = strtoul(opt, &end, 10);
if (*end != '\0')
return (vsm_diag(vd, "invalid number for -k\n"));
return (1);
}
/*--------------------------------------------------------------------*/
static int
vsl_k_arg(struct VSM_data *vd, const char *opt)
{
struct vsl *vsl = vsl_Setup(vd);
char *end;
CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
if (*opt == '\0')
return (vsm_diag(vd, "number required for -k\n"));
vsl->keep = strtoul(opt, &end, 10);
if (*end != '\0')
return (vsm_diag(vd, "invalid number for -k\n"));
return (1);
}
/*--------------------------------------------------------------------*/
int
VSL_Arg(struct VSM_data *vd, int arg, const char *opt)
VSL_Arg(struct VSL_data *vsl, int opt, const char *arg)
{
struct vsl *vsl = vsl_Setup(vd);
switch (arg) {
case 'b': vsl->b_opt = !vsl->b_opt; return (1);
case 'c': vsl->c_opt = !vsl->c_opt; return (1);
case 'd':
vsl->d_opt = !vsl->d_opt;
return (1);
case 'i': case 'x': return (vsl_ix_arg(vd, opt, arg));
case 'k': return (vsl_k_arg(vd, opt));
case 'n': return (VSM_n_Arg(vd, opt));
case 'r': return (vsl_r_arg(vd, opt));
case 's': return (vsl_s_arg(vd, opt));
case 'I': case 'X': return (vsl_IX_arg(vd, opt, arg));
case 'm': return (vsl_m_arg(vd, opt));
case 'C': vsl->regflags = VRE_CASELESS; return (1);
switch (opt) {
case 'i': case'x': return (vsl_ix_arg(vsl, opt, arg));
default:
return (0);
}
......
/*-
* Copyright (c) 2006 Verdens Gang AS
* Copyright (c) 2006-2013 Varnish Software AS
* All rights reserved.
*
* Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
* Author: Martin Blix Grydeland <martin@varnish-software.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "vas.h"
#include "vdef.h"
#include "miniobj.h"
#include "vapi/vsm.h"
#include "vsm_api.h"
#include "vapi/vsl.h"
#include "vsl_api.h"
struct vslc_vsm {
struct vslc c;
unsigned magic;
#define VSLC_VSM_MAGIC 0x4D3903A6
struct VSM_data *vsm;
struct VSM_fantom vf;
volatile const struct VSL_head *head;
volatile const uint32_t *next;
const uint32_t *end;
ssize_t segsize;
unsigned seq;
};
static void
vslc_vsm_delete(void *cursor)
{
struct vslc_vsm *c;
CAST_OBJ_NOTNULL(c, (void *)cursor, VSLC_VSM_MAGIC);
FREE_OBJ(c);
}
static int
vslc_vsm_next(void *cursor)
{
struct vslc_vsm *c;
int diff;
unsigned segment;
uint32_t t;
CAST_OBJ_NOTNULL(c, cursor, VSLC_VSM_MAGIC);
CHECK_OBJ_NOTNULL(c->vsm, VSM_MAGIC);
/* Assert pointers */
AN(c->next);
assert(c->next >= c->head->log);
assert(c->next < c->end);
/* Check sequence number */
diff = c->head->seq - c->seq;
if (c->head->seq < c->seq)
/* Wrap around skips 0 */
diff -= 1;
if (diff > 1)
return (-3);
/* Check overrun */
segment = (c->next - c->head->log) / c->segsize;
if (segment >= VSL_SEGMENTS)
segment = VSL_SEGMENTS - 1;
diff = (segment - c->head->segment) % VSL_SEGMENTS;
if (0 < diff && diff <= 2)
return (-3);
/* Check VSL fantom and abandonment */
if (*c->next == VSL_ENDMARKER) {
if (!VSM_StillValid(c->vsm, &c->vf) ||
VSM_Abandoned(c->vsm))
return (-2);
}
while (1) {
assert(c->next >= c->head->log);
assert(c->next < c->end);
AN(c->head->seq);
t = *c->next;
AN(t);
if (t == VSL_WRAPMARKER) {
/* Wrap around not possible at front */
assert(c->next != c->head->log);
c->next = c->head->log;
continue;
}
if (t == VSL_ENDMARKER) {
if (c->next != c->head->log &&
c->seq != c->head->seq) {
/* ENDMARKER not at front and seq wrapped */
/* XXX: assert on this? */
c->next = c->head->log;
continue;
}
return (0);
}
if (c->next == c->head->log)
c->seq = c->head->seq;
c->c.c.ptr = (void*)(uintptr_t)c->next; /* Loose volatile */
c->next = VSL_NEXT(c->next);
return (1);
}
}
struct VSL_cursor *
VSL_CursorVSM(struct VSL_data *vsl, struct VSM_data *vsm, int tail)
{
struct vslc_vsm *c;
struct VSM_fantom vf;
struct VSL_head *head;
unsigned segment;
CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
CHECK_OBJ_NOTNULL(vsm, VSM_MAGIC);
if (!VSM_Get(vsm, &vf, VSL_CLASS, "", "")) {
vsl_diag(vsl, "No VSL chunk found (child not started ?)\n");
return (NULL);
}
head = vf.b;
if (memcmp(head->marker, VSL_HEAD_MARKER, sizeof head->marker)) {
vsl_diag(vsl, "Not a VSL chunk\n");
return (NULL);
}
if (head->seq == 0) {
vsl_diag(vsl, "VSL chunk not initialized\n");
return (NULL);
}
ALLOC_OBJ(c, VSLC_VSM_MAGIC);
if (c == NULL) {
vsl_diag(vsl, "Out of memory\n");
return (NULL);
}
c->c.magic = VSLC_MAGIC;
c->c.delete = vslc_vsm_delete;
c->c.next = vslc_vsm_next;
c->vsm = vsm;
c->vf = vf;
c->head = head;
c->end = vf.e;
c->segsize = (c->end - c->head->log) / VSL_SEGMENTS;
if (tail) {
/* Locate tail of log */
c->next = c->head->log + c->head->segments[c->head->segment];
while (c->next < c->end && *c->next != VSL_ENDMARKER)
c->next = VSL_NEXT(c->next);
} else {
/*
* Starting (VSL_SEGMENTS - 3) behind varnishd. This way
* even if varnishd wraps immediately, we'll still have a
* full segment worth of log before the general constraint
* of at least 2 segments apart will be broken
*/
segment = (c->head->segment + 3) % VSL_SEGMENTS;
if (c->head->segments[segment] < 0)
segment = 0;
assert(c->head->segments[segment] >= 0);
c->next = c->head->log + c->head->segments[segment];
}
c->seq = c->head->seq;
return (&c->c.c);
}
struct vslc_file {
struct vslc c;
unsigned magic;
#define VSLC_FILE_MAGIC 0x1D65FFEF
int error;
int fd;
ssize_t buflen;
uint32_t *buf;
};
static void
vslc_file_delete(void *cursor)
{
struct vslc_file *c;
CAST_OBJ_NOTNULL(c, cursor, VSLC_FILE_MAGIC);
if (c->fd > STDIN_FILENO)
(void)close(c->fd);
if (c->buf != NULL)
free(c->buf);
FREE_OBJ(c);
}
static ssize_t
vslc_file_readn(int fd, void *buf, size_t n)
{
size_t t = 0;
ssize_t l;
while (t < n) {
l = read(fd, (char *)buf + t, n - t);
if (l <= 0)
return (l);
t += l;
}
return (t);
}
static int
vslc_file_next(void *cursor)
{
struct vslc_file *c;
ssize_t i, l;
CAST_OBJ_NOTNULL(c, cursor, VSLC_FILE_MAGIC);
if (c->error)
return (c->error);
do {
c->c.c.ptr = NULL;
assert(c->buflen >= 2 * 4);
i = vslc_file_readn(c->fd, c->buf, 2 * 4);
if (i < 0)
return (-4); /* I/O error */
if (i == 0)
return (-1); /* EOF */
assert(i == 2 * 4);
l = (2 + VSL_WORDS(VSL_LEN(c->buf))) * 4;
if (c->buflen < l) {
c->buf = realloc(c->buf, 2 * l);
AN(c->buf);
c->buflen = 2 * l;
}
i = vslc_file_readn(c->fd, c->buf + 2, l - 2 * 4);
if (i < 0)
return (-4); /* I/O error */
if (i == 0)
return (-1); /* EOF */
assert(i == l - 2 * 4);
c->c.c.ptr = c->buf;
} while (c->c.c.ptr != NULL && VSL_TAG(c->c.c.ptr) == SLT__Batch);
return (1);
}
struct VSL_cursor *
VSL_CursorFile(struct VSL_data *vsl, const char *name)
{
struct vslc_file *c;
int fd;
char buf[4];
ssize_t i;
if (!strcmp(name, "-")) {
fd = open(name, O_RDONLY);
if (fd < 0) {
vsl_diag(vsl, "Could not open %s: %s\n", name,
strerror(errno));
return (NULL);
}
} else
fd = STDIN_FILENO;
i = vslc_file_readn(fd, buf, sizeof buf);
if (i <= 0) {
if (fd > STDIN_FILENO)
(void)close(fd);
vsl_diag(vsl, "VSL file read error: %s\n",
i < 0 ? strerror(errno) : "EOF");
return (NULL);
}
assert(i == sizeof buf);
if (memcmp(buf, VSL_FILE_HEAD, sizeof buf)) {
if (fd > STDIN_FILENO)
(void)close(fd);
vsl_diag(vsl, "Not a VSL file: %s\n", name);
return (NULL);
}
ALLOC_OBJ(c, VSLC_FILE_MAGIC);
if (c == NULL) {
if (fd > STDIN_FILENO)
(void)close(fd);
vsl_diag(vsl, "Out of memory\n");
return (NULL);
}
c->c.magic = VSLC_MAGIC;
c->c.delete = vslc_file_delete;
c->c.next = vslc_file_next;
c->fd = fd;
c->buflen = BUFSIZ;
c->buf = malloc(c->buflen);
AN(c->buf);
return (&c->c.c);
}
void
VSL_DeleteCursor(struct VSL_cursor *cursor)
{
struct vslc *c;
CAST_OBJ_NOTNULL(c, (void *)cursor, VSLC_MAGIC);
if (c->delete == NULL)
return;
(c->delete)(c);
}
int
VSL_Next(struct VSL_cursor *cursor)
{
struct vslc *c;
CAST_OBJ_NOTNULL(c, (void *)cursor, VSLC_MAGIC);
AN(c->next);
return ((c->next)(c));
}
......@@ -163,8 +163,7 @@ VSM_Delete(struct VSM_data *vd)
free(vd->fname);
if (vd->vsc != NULL)
VSC_Delete(vd);
if (vd->vsl != NULL)
VSL_Delete(vd);
VSM_ResetError(vd);
FREE_OBJ(vd);
}
......
......@@ -57,4 +57,3 @@ struct VSM_data {
int vsm_diag(struct VSM_data *vd, const char *fmt, ...)
__printflike(2, 3);
void VSC_Delete(struct VSM_data *vd);
void VSL_Delete(struct VSM_data *vd);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment