X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=ucw%2Ffb-atomic.c;h=a29e758b62283cc2e9a29f96440714d4e515736e;hb=b8667492cf36a609939ee35ac42900ff0b0cc80f;hp=5eca3905770afb4a62be08b3d8739665a500d515;hpb=343150ef4c405939d98421d5ac4c09f9565ef35a;p=libucw.git diff --git a/ucw/fb-atomic.c b/ucw/fb-atomic.c index 5eca3905..a29e758b 100644 --- a/ucw/fb-atomic.c +++ b/ucw/fb-atomic.c @@ -7,45 +7,24 @@ * of the GNU Lesser General Public License. */ -/* - * This fastbuf backend is intended for cases where several threads - * of a single program append records to a single file and while the - * record can mix in an arbitrary way, the bytes inside a single - * record must remain uninterrupted. - * - * In case of files with fixed record size, we just allocate the - * buffer to hold a whole number of records and take advantage - * of the atomicity of the write() system call. - * - * With variable-sized records, we need another solution: when - * writing a record, we keep the fastbuf in a locked state, which - * prevents buffer flushing (and if the buffer becomes full, we extend it), - * and we wait for an explicit commit operation which write()s the buffer - * if the free space in the buffer falls below the expected maximum record - * length. - * - * fbatomic_open() is called with the following parameters: - * name - name of the file to open - * master - fbatomic for the master thread or NULL if it's the first open - * bufsize - initial buffer size - * record_len - record length for fixed-size records; - * or -(expected maximum record length) for variable-sized ones. - */ - -#include "ucw/lib.h" -#include "ucw/fastbuf.h" -#include "ucw/lfs.h" -#include "ucw/conf.h" +#include +#include +#include +#include +#include #include #include #include -static uns trace; +static uint trace; + +#ifndef TEST static struct cf_section fbatomic_config = { CF_ITEMS { - CF_UNS("Trace", &trace) + CF_UINT("Trace", &trace), + CF_END } }; @@ -54,13 +33,16 @@ static void CONSTRUCTOR fbatomic_init_config(void) cf_declare_section("FBAtomic", &fbatomic_config, 1); } +#endif + +#define FB_ATOMIC(f) ((struct fb_atomic *)(f)) #define TRACE(m...) do { if(trace) msg(L_DEBUG, "FB_ATOMIC: " m); } while(0) struct fb_atomic_file { int fd; int use_count; int record_len; - uns locked; + uint locked; byte name[1]; }; @@ -74,9 +56,9 @@ fbatomic_internal_write(struct fastbuf *f) ASSERT(af->record_len < 0 || !(size % af->record_len)); int res = write(af->fd, f->buffer, size); if (res < 0) - die("Error writing %s: %m", f->name); + bthrow(f, "write", "Error writing %s: %m", f->name); if (res != size) - die("Unexpected partial write to %s: written only %d bytes of %d", f->name, res, size); + bthrow(f, "write", "Unexpected partial write to %s: written only %d bytes of %d", f->name, res, size); f->bptr = f->buffer; } } @@ -90,13 +72,14 @@ fbatomic_spout(struct fastbuf *f) struct fb_atomic *F = FB_ATOMIC(f); if (F->af->locked) { - uns written = f->bptr - f->buffer; - uns size = f->bufend - f->buffer + F->slack_size; + uint written = f->bptr - f->buffer; + uint size = f->bufend - f->buffer + F->slack_size; F->slack_size *= 2; TRACE("Reallocating buffer for atomic file %s with slack %d", f->name, F->slack_size); f->buffer = xrealloc(f->buffer, size); f->bufend = f->buffer + size; f->bptr = f->buffer + written; + f->bstop = f->buffer; F->expected_max_bptr = f->bufend - F->slack_size; } else @@ -107,7 +90,8 @@ static void fbatomic_close(struct fastbuf *f) { struct fb_atomic_file *af = FB_ATOMIC(f)->af; - fbatomic_internal_write(f); /* Need to flush explicitly, because the file can be locked */ + if (!(f->flags & FB_DEAD)) + fbatomic_internal_write(f); /* Need to flush explicitly, because the file can be locked */ if (!--af->use_count) { close(af->fd); @@ -117,7 +101,7 @@ fbatomic_close(struct fastbuf *f) } struct fastbuf * -fbatomic_open(const char *name, struct fastbuf *master, uns bufsize, int record_len) +fbatomic_open(const char *name, struct fastbuf *master, uint bufsize, int record_len) { struct fb_atomic *F = xmalloc_zero(sizeof(*F)); struct fastbuf *f = &F->fb; @@ -130,9 +114,11 @@ fbatomic_open(const char *name, struct fastbuf *master, uns bufsize, int record_ } else { + int fd = ucw_open(name, O_WRONLY | O_CREAT | O_TRUNC | O_APPEND, 0666); + if (fd < 0) + trans_throw("ucw.fb.open", NULL, "Cannot create %s: %m", name); af = xmalloc_zero(sizeof(*af) + strlen(name)); - if ((af->fd = ucw_open(name, O_WRONLY | O_CREAT | O_TRUNC | O_APPEND, 0666)) < 0) - die("Cannot create %s: %m", name); + af->fd = fd; af->use_count = 1; af->record_len = record_len; af->locked = (record_len < 0);