diff --git a/lib/grn_io.h b/lib/grn_io.h index 6de63bd..fa2990e 100644 --- a/lib/grn_io.h +++ b/lib/grn_io.h @@ -107,6 +107,8 @@ struct _grn_io { uint32_t count; uint8_t flags; uint32_t *lock; + uint32_t segment_size_mask; + uint8_t segment_size_shift; }; GRN_API grn_io *grn_io_create(grn_ctx *ctx, const char *path, diff --git a/lib/io.c b/lib/io.c index 9913c8a..c792fef 100644 --- a/lib/io.c +++ b/lib/io.c @@ -161,6 +161,22 @@ grn_io_compute_file_size(uint32_t version) } } +static uint8_t +grn_io_compute_shift(uint32_t size) +{ + uint8_t shift = 0; + while (((uint64_t)1 << shift) < size) { + shift++; + } + return (((uint64_t)1 << shift) == size) ? shift : 0; +} + +static uint32_t +grn_io_compute_mask(uint32_t shift) +{ + return ((uint32_t)1 << shift) - 1; +} + static inline uint32_t grn_io_max_segment(grn_io *io) { @@ -219,6 +235,8 @@ grn_io_create_tmp(uint32_t header_size, uint32_t segment_size, io->flags = GRN_IO_TEMPORARY; io->lock = &header->lock; io->path[0] = '\0'; + io->segment_size_shift = grn_io_compute_shift(segment_size); + io->segment_size_mask = grn_io_compute_mask(io->segment_size_shift); return io; } GRN_GFREE(io); @@ -320,6 +338,8 @@ grn_io_create(grn_ctx *ctx, const char *path, uint32_t header_size, uint32_t seg io->count = 0; io->flags = flags; io->lock = &header->lock; + io->segment_size_shift = grn_io_compute_shift(segment_size); + io->segment_size_mask = grn_io_compute_mask(io->segment_size_shift); grn_io_register(io); return io; } @@ -592,6 +612,8 @@ grn_io_open(grn_ctx *ctx, const char *path, grn_io_mode mode) io->count = 0; io->flags = header->flags; io->lock = &header->lock; + io->segment_size_shift = grn_io_compute_shift(segment_size); + io->segment_size_mask = grn_io_compute_mask(io->segment_size_shift); if (!array_init(io, io->header->n_arrays)) { grn_io_register(io); return io; @@ -987,10 +1009,19 @@ grn_io_win_map(grn_io *io, grn_ctx *ctx, grn_io_win *iw, uint32_t segment, { uint32_t nseg, segment_size = io->header->segment_size; if (offset >= segment_size) { - segment += offset / segment_size; - offset = offset % segment_size; + if (io->segment_size_shift) { + segment += offset >> io->segment_size_shift; + offset = offset & io->segment_size_mask; + } else { + segment += offset / segment_size; + offset = offset % segment_size; + } + } + if (io->segment_size_shift) { + nseg = (offset + size + segment_size - 1) >> io->segment_size_shift; + } else { + nseg = (offset + size + segment_size - 1) / segment_size; } - nseg = (offset + size + segment_size - 1) / segment_size; if (!size || !ctx || segment + nseg > io->header->max_segment) { return NULL; } iw->ctx = ctx; iw->diff = 0;