diff options
Diffstat (limited to 'storage/mroonga/vendor/groonga/lib/io.c')
-rw-r--r-- | storage/mroonga/vendor/groonga/lib/io.c | 865 |
1 files changed, 555 insertions, 310 deletions
diff --git a/storage/mroonga/vendor/groonga/lib/io.c b/storage/mroonga/vendor/groonga/lib/io.c index 3cee03f5123..a20fef614c7 100644 --- a/storage/mroonga/vendor/groonga/lib/io.c +++ b/storage/mroonga/vendor/groonga/lib/io.c @@ -1,5 +1,6 @@ /* -*- c-basic-offset: 2 -*- */ -/* Copyright(C) 2009-2015 Brazil +/* + Copyright(C) 2009-2017 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -28,6 +29,7 @@ #include "grn_plugin.h" #include "grn_hash.h" #include "grn_ctx_impl.h" +#include "grn_util.h" #ifdef WIN32 # include <io.h> @@ -62,55 +64,81 @@ typedef struct _grn_io_fileinfo { #define IO_HEADER_SIZE 64 static uint32_t grn_io_version_default = GRN_IO_VERSION_DEFAULT; +static grn_bool grn_io_use_sparse = GRN_FALSE; -inline static grn_rc grn_fileinfo_open(grn_ctx *ctx, fileinfo *fi, const char *path, int flags); +inline static grn_rc grn_fileinfo_open(grn_ctx *ctx, fileinfo *fi, + const char *path, int flags); inline static void grn_fileinfo_init(fileinfo *fis, int nfis); inline static int grn_fileinfo_opened(fileinfo *fi); inline static grn_rc grn_fileinfo_close(grn_ctx *ctx, fileinfo *fi); #ifdef WIN32 -inline static void * grn_mmap(grn_ctx *ctx, grn_io *io, - HANDLE *fmo, fileinfo *fi, +inline static void * grn_mmap(grn_ctx *ctx, grn_ctx *owner_ctx, + grn_io *io, HANDLE *fmo, fileinfo *fi, off_t offset, size_t length); -inline static int grn_munmap(grn_ctx *ctx, grn_io *io, - HANDLE *fmo, fileinfo *fi, +inline static int grn_munmap(grn_ctx *ctx, grn_ctx *owner_ctx, + grn_io *io, HANDLE *fmo, fileinfo *fi, void *start, size_t length); -# define GRN_MMAP(ctx,io,fmo,fi,offset,length)\ - (grn_mmap((ctx), (io), (fmo), (fi), (offset), (length))) -# define GRN_MUNMAP(ctx,io,fmo,fi,start,length)\ - (grn_munmap((ctx), (io), (fmo), (fi), (start), (length))) +inline static int grn_msync(grn_ctx *ctx, HANDLE fh, + void *start, size_t length); +# define GRN_MMAP(ctx,owner_ctx,io,fmo,fi,offset,length)\ + (grn_mmap((ctx), (owner_ctx), (io), (fmo), (fi), (offset), (length))) +# define GRN_MUNMAP(ctx,owner_ctx,io,fmo,fi,start,length)\ + (grn_munmap((ctx), (owner_ctx), (io), (fmo), (fi), (start), (length))) +# define GRN_MSYNC(ctx,fh,start,length) \ + (grn_msync((ctx), (fh), (start), (length))) #else /* WIN32 */ -inline static void * grn_mmap(grn_ctx *ctx, grn_io *io, fileinfo *fi, +inline static void * grn_mmap(grn_ctx *ctx, grn_ctx *owner_ctx, + grn_io *io, fileinfo *fi, off_t offset, size_t length); -inline static int grn_munmap(grn_ctx *ctx, grn_io *io, fileinfo *fi, +inline static int grn_munmap(grn_ctx *ctx, grn_ctx *owner_ctx, + grn_io *io, fileinfo *fi, void *start, size_t length); -# define GRN_MUNMAP(ctx,io,fmo,fi,start,length) \ - (grn_munmap((ctx), (io), (fi), (start), (length))) +inline static int grn_msync(grn_ctx *ctx, void *start, size_t length); +# define GRN_MUNMAP(ctx,owner_ctx,io,fmo,fi,start,length) \ + (grn_munmap((ctx), (owner_ctx), (io), (fi), (start), (length))) +# define GRN_MSYNC(ctx,fh,start,length) \ + (grn_msync((ctx), (start), (length))) # ifdef USE_FAIL_MALLOC -inline static void * grn_fail_mmap(grn_ctx *ctx, grn_io *io, fileinfo *fi, +inline static void * grn_fail_mmap(grn_ctx *ctx, grn_ctx *owner_ctx, + grn_io *io, fileinfo *fi, off_t offset, size_t length, const char* file, int line, const char *func); -# define GRN_MMAP(ctx,io,fmo,fi,offset,length)\ - (grn_fail_mmap((ctx), (io), (fi), (offset), (length),\ +# define GRN_MMAP(ctx,owner_ctx,io,fmo,fi,offset,length)\ + (grn_fail_mmap((ctx), (owner_ctx), (io), (fi), (offset), (length),\ __FILE__, __LINE__, __FUNCTION__)) # else /* USE_FAIL_MALLOC */ -# define GRN_MMAP(ctx,io,fmo,fi,offset,length)\ - (grn_mmap((ctx), (io), (fi), (offset), (length))) +# define GRN_MMAP(ctx,owner_ctx,io,fmo,fi,offset,length)\ + (grn_mmap((ctx), (owner_ctx), (io), (fi), (offset), (length))) # endif /* USE_FAIL_MALLOC */ #endif /* WIN32 */ -inline static int grn_msync(grn_ctx *ctx, void *start, size_t length); -inline static grn_rc grn_pread(grn_ctx *ctx, fileinfo *fi, void *buf, size_t count, off_t offset); -inline static grn_rc grn_pwrite(grn_ctx *ctx, fileinfo *fi, void *buf, size_t count, off_t offset); +inline static grn_rc grn_pread(grn_ctx *ctx, fileinfo *fi, void *buf, + size_t count, off_t offset); +inline static grn_rc grn_pwrite(grn_ctx *ctx, fileinfo *fi, void *buf, + size_t count, off_t offset); void grn_io_init_from_env(void) { - char version_env[GRN_ENV_BUFFER_SIZE]; + { + char version_env[GRN_ENV_BUFFER_SIZE]; - grn_getenv("GRN_IO_VERSION", - version_env, - GRN_ENV_BUFFER_SIZE); - if (version_env[0]) { - grn_io_version_default = atoi(version_env); + grn_getenv("GRN_IO_VERSION", + version_env, + GRN_ENV_BUFFER_SIZE); + if (version_env[0]) { + grn_io_version_default = atoi(version_env); + } + } + + { + char use_sparse_env[GRN_ENV_BUFFER_SIZE]; + + grn_getenv("GRN_IO_USE_SPARSE", + use_sparse_env, + GRN_ENV_BUFFER_SIZE); + if (use_sparse_env[0] && strcmp(use_sparse_env, "yes") == 0) { + grn_io_use_sparse = GRN_TRUE; + } } } @@ -169,15 +197,31 @@ grn_io_max_n_files(grn_io *io) file_size); } -grn_io * -grn_io_create_tmp(uint32_t header_size, uint32_t segment_size, +static inline uint32_t +grn_io_compute_nth_file_info(grn_io *io, uint32_t nth_segment) +{ + uint32_t segment_size; + unsigned long file_size; + uint32_t segments_per_file; + uint32_t resolved_nth_segment; + + segment_size = io->header->segment_size; + file_size = grn_io_compute_file_size(io->header->version); + segments_per_file = file_size / segment_size; + resolved_nth_segment = nth_segment + io->base_seg; + return resolved_nth_segment / segments_per_file; +} + +static grn_io * +grn_io_create_tmp(grn_ctx *ctx, uint32_t header_size, uint32_t segment_size, uint32_t max_segment, grn_io_mode mode, uint32_t flags) { grn_io *io; uint32_t b; struct _grn_io_header *header; b = grn_io_compute_base(header_size); - header = (struct _grn_io_header *)GRN_MMAP(&grn_gctx, NULL, NULL, NULL, 0, b); + header = (struct _grn_io_header *)GRN_MMAP(ctx, &grn_gctx, NULL, NULL, NULL, + 0, b); if (header) { header->version = grn_io_version_default; header->header_size = header_size; @@ -187,9 +231,9 @@ grn_io_create_tmp(uint32_t header_size, uint32_t segment_size, header->flags = flags; header->lock = 0; grn_memcpy(header->idstr, GRN_IO_IDSTR, 16); - if ((io = GRN_GMALLOCN(grn_io, 1))) { + if ((io = GRN_MALLOCN(grn_io, 1))) { grn_io_mapinfo *maps = NULL; - if ((maps = GRN_GCALLOC(sizeof(grn_io_mapinfo) * max_segment))) { + if ((maps = GRN_CALLOC(sizeof(grn_io_mapinfo) * max_segment))) { io->header = header; io->user_header = (((byte *) header) + IO_HEADER_SIZE); io->maps = maps; @@ -207,15 +251,15 @@ grn_io_create_tmp(uint32_t header_size, uint32_t segment_size, io->path[0] = '\0'; return io; } - GRN_GFREE(io); + GRN_FREE(io); } - GRN_MUNMAP(&grn_gctx, NULL, NULL, NULL, header, b); + GRN_MUNMAP(ctx, &grn_gctx, NULL, NULL, NULL, header, b); } return NULL; } static void -grn_io_register(grn_io *io) +grn_io_register(grn_ctx *ctx, grn_io *io) { if (io->fis && (io->flags & (GRN_IO_EXPIRE_GTICK|GRN_IO_EXPIRE_SEGMENT))) { grn_bool succeeded = GRN_FALSE; @@ -227,14 +271,14 @@ grn_io_register(grn_io *io) } CRITICAL_SECTION_LEAVE(grn_glock); if (!succeeded) { - GRN_LOG(&grn_gctx, GRN_LOG_WARNING, + GRN_LOG(ctx, GRN_LOG_WARNING, "grn_io_register(%s) failed", io->path); } } } static void -grn_io_unregister(grn_io *io) +grn_io_unregister(grn_ctx *ctx, grn_io *io) { if (io->fis && (io->flags & (GRN_IO_EXPIRE_GTICK|GRN_IO_EXPIRE_SEGMENT))) { grn_bool succeeded = GRN_FALSE; @@ -246,15 +290,16 @@ grn_io_unregister(grn_io *io) } CRITICAL_SECTION_LEAVE(grn_glock); if (!succeeded) { - GRN_LOG(&grn_gctx, GRN_LOG_WARNING, + GRN_LOG(ctx, GRN_LOG_WARNING, "grn_io_unregister(%s) failed", io->path); } } } grn_io * -grn_io_create(grn_ctx *ctx, const char *path, uint32_t header_size, uint32_t segment_size, - uint32_t max_segment, grn_io_mode mode, uint32_t flags) +grn_io_create(grn_ctx *ctx, const char *path, uint32_t header_size, + uint32_t segment_size, uint32_t max_segment, grn_io_mode mode, + uint32_t flags) { grn_io *io; fileinfo *fis; @@ -265,7 +310,8 @@ grn_io_create(grn_ctx *ctx, const char *path, uint32_t header_size, uint32_t seg unsigned long file_size; if (!path) { - return grn_io_create_tmp(header_size, segment_size, max_segment, mode, flags); + return grn_io_create_tmp(ctx, header_size, segment_size, max_segment, + mode, flags); } if (!*path || (strlen(path) > PATH_MAX - 4)) { return NULL; } b = grn_io_compute_base(header_size); @@ -273,10 +319,10 @@ grn_io_create(grn_ctx *ctx, const char *path, uint32_t header_size, uint32_t seg file_size = grn_io_compute_file_size(version); max_nfiles = grn_io_compute_max_n_files(segment_size, max_segment, bs, file_size); - if ((fis = GRN_GMALLOCN(fileinfo, max_nfiles))) { + if ((fis = GRN_MALLOCN(fileinfo, max_nfiles))) { grn_fileinfo_init(fis, max_nfiles); if (!grn_fileinfo_open(ctx, fis, path, O_RDWR|O_CREAT|O_EXCL)) { - header = (struct _grn_io_header *)GRN_MMAP(&grn_gctx, NULL, + header = (struct _grn_io_header *)GRN_MMAP(ctx, &grn_gctx, NULL, &fis->fmo, fis, 0, b); if (header) { header->version = version; @@ -287,10 +333,10 @@ grn_io_create(grn_ctx *ctx, const char *path, uint32_t header_size, uint32_t seg header->flags = flags; header->lock = 0; grn_memcpy(header->idstr, GRN_IO_IDSTR, 16); - grn_msync(ctx, header, b); - if ((io = GRN_GMALLOCN(grn_io, 1))) { + GRN_MSYNC(ctx, fis[0].fh, header, b); + if ((io = GRN_MALLOCN(grn_io, 1))) { grn_io_mapinfo *maps = NULL; - if ((maps = GRN_GCALLOC(sizeof(grn_io_mapinfo) * max_segment))) { + if ((maps = GRN_CALLOC(sizeof(grn_io_mapinfo) * max_segment))) { grn_strncpy(io->path, PATH_MAX, path, PATH_MAX); io->header = header; io->user_header = (((byte *) header) + IO_HEADER_SIZE); @@ -306,35 +352,35 @@ 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; - grn_io_register(io); + grn_io_register(ctx, io); return io; } - GRN_GFREE(io); + GRN_FREE(io); } - GRN_MUNMAP(&grn_gctx, NULL, &fis->fmo, fis, header, b); + GRN_MUNMAP(ctx, &grn_gctx, NULL, &fis->fmo, fis, header, b); } grn_fileinfo_close(ctx, fis); - if (grn_unlink(path) == -1) { - GRN_LOG(ctx, GRN_LOG_ERROR, - "failed to grn_unlink() path on grn_io_create() error: " - "<%s>: <%s>", - path, grn_strerror(errno)); + if (grn_unlink(path) == 0) { + GRN_LOG(ctx, GRN_LOG_INFO, + "[io][create][error] removed path: <%s>", path); + } else { + ERRNO_ERR("[io][create][error] failed to remove path: <%s>", path); } } - GRN_GFREE(fis); + GRN_FREE(fis); } return NULL; } static grn_rc -array_init_(grn_io *io, int n_arrays, size_t hsize, size_t msize) +array_init_(grn_ctx *ctx, grn_io *io, int n_arrays, size_t hsize, size_t msize) { int i; uint32_t ws; byte *hp, *mp; grn_io_array_spec *array_specs = (grn_io_array_spec *)io->user_header; hp = io->user_header; - if (!(mp = GRN_GCALLOC(msize))) { + if (!(mp = GRN_CALLOC(msize))) { return GRN_NO_MEMORY_AVAILABLE; } io->ainfo = (grn_io_array_info *)mp; @@ -357,7 +403,7 @@ array_init_(grn_io *io, int n_arrays, size_t hsize, size_t msize) } static grn_rc -array_init(grn_io *io, int n_arrays) +array_init(grn_ctx *ctx, grn_io *io, int n_arrays) { if (n_arrays) { int i; @@ -368,7 +414,7 @@ array_init(grn_io *io, int n_arrays) hsize += sizeof(uint32_t) * array_specs[i].max_n_segments; msize += sizeof(void *) * array_specs[i].max_n_segments; } - return array_init_(io, n_arrays, hsize, msize); + return array_init_(ctx, io, n_arrays, hsize, msize); } return GRN_SUCCESS; } @@ -376,7 +422,8 @@ array_init(grn_io *io, int n_arrays) grn_io * grn_io_create_with_array(grn_ctx *ctx, const char *path, uint32_t header_size, uint32_t segment_size, - grn_io_mode mode, int n_arrays, grn_io_array_spec *array_specs) + grn_io_mode mode, int n_arrays, + grn_io_array_spec *array_specs) { if (n_arrays) { int i; @@ -392,11 +439,13 @@ grn_io_create_with_array(grn_ctx *ctx, const char *path, } if ((io = grn_io_create(ctx, path, header_size + hsize, segment_size, nsegs, mode, GRN_IO_EXPIRE_GTICK))) { + grn_rc rc; hp = io->user_header; grn_memcpy(hp, array_specs, sizeof(grn_io_array_spec) * n_arrays); io->header->n_arrays = n_arrays; io->header->segment_tail = 1; - if (!array_init_(io, n_arrays, hsize, msize)) { + rc = array_init_(ctx, io, n_arrays, hsize, msize); + if (rc == GRN_SUCCESS) { return io; } ERR(GRN_NO_MEMORY_AVAILABLE, "grn_io_create_with_array failed"); @@ -407,7 +456,7 @@ grn_io_create_with_array(grn_ctx *ctx, const char *path, } inline static uint32_t -segment_alloc(grn_io *io) +segment_alloc(grn_ctx *ctx, grn_io *io) { uint32_t n, s; grn_io_array_info *ai; @@ -418,7 +467,7 @@ segment_alloc(grn_io *io) s = io->header->segment_tail++; } } else { - char *used = GRN_GCALLOC(io->header->max_segment + 1); + char *used = GRN_CALLOC(io->header->max_segment + 1); if (!used) { return 0; } for (n = io->header->n_arrays, ai = io->ainfo; n; n--, ai++) { for (s = 0; s < ai->max_n_segments; s++) { @@ -436,18 +485,19 @@ segment_alloc(grn_io *io) break; } } - GRN_GFREE(used); + GRN_FREE(used); } return s; } void -grn_io_segment_alloc(grn_ctx *ctx, grn_io *io, grn_io_array_info *ai, uint32_t lseg, int *flags, void **p) +grn_io_segment_alloc(grn_ctx *ctx, grn_io *io, grn_io_array_info *ai, + uint32_t lseg, int *flags, void **p) { uint32_t *sp = &ai->segments[lseg]; if (!*sp) { if ((*flags & GRN_TABLE_ADD)) { - if ((*sp = segment_alloc(io))) { + if ((*sp = segment_alloc(ctx, io))) { *flags |= GRN_TABLE_ADDED; } } @@ -473,11 +523,12 @@ grn_io_detect_type(grn_ctx *ctx, const char *path) struct _grn_io_header h; uint32_t res = 0; int fd; - grn_open(fd, path, O_RDWR | GRN_OPEN_FLAG_BINARY); + grn_open(fd, path, O_RDONLY | GRN_OPEN_FLAG_BINARY); if (fd != -1) { struct stat s; if (fstat(fd, &s) != -1 && s.st_size >= sizeof(struct _grn_io_header)) { - if (grn_read(fd, &h, sizeof(struct _grn_io_header)) == sizeof(struct _grn_io_header)) { + if (grn_read(fd, &h, sizeof(struct _grn_io_header)) == + sizeof(struct _grn_io_header)) { if (!memcmp(h.idstr, GRN_IO_IDSTR, GRN_IO_IDSTR_LEN)) { res = h.type; } else { @@ -487,20 +538,16 @@ grn_io_detect_type(grn_ctx *ctx, const char *path) (int)GRN_IO_IDSTR_LEN, GRN_IO_IDSTR); } } else { - SERR(path); - GRN_LOG(ctx, GRN_LOG_ERROR, - "failed to read enough data for detecting type: <%s>", - path); + SERR("failed to read enough data for detecting type: <%s>", + path); } } else { ERR(GRN_INVALID_FORMAT, "grn_io_detect_type failed"); } grn_close(fd); } else { - ERRNO_ERR(path); - GRN_LOG(ctx, GRN_LOG_ERROR, - "failed to open path for detecting type: <%s>", - path); + ERRNO_ERR("failed to open path for detecting type: <%s>", + path); } return res; } @@ -508,48 +555,88 @@ grn_io_detect_type(grn_ctx *ctx, const char *path) grn_io * grn_io_open(grn_ctx *ctx, const char *path, grn_io_mode mode) { + size_t max_path_len = PATH_MAX - 4; grn_io *io; struct stat s; fileinfo fi; uint32_t flags = 0; uint32_t b; uint32_t header_size = 0, segment_size = 0, max_segment = 0, bs; - if (!path || !*path || (strlen(path) > PATH_MAX - 4)) { return NULL; } + if (!path || !*path) { + ERR(GRN_INVALID_ARGUMENT, "[io][open] path is missing"); + return NULL; + } + if ((strlen(path) > max_path_len)) { + int truncate_length = 10; + ERR(GRN_INVALID_ARGUMENT, + "[io][open] path is too long: " + "<%" GRN_FMT_SIZE ">(max: %" GRN_FMT_SIZE "): <%.*s...>", + strlen(path), + max_path_len, + truncate_length, + path); + return NULL; + } { struct _grn_io_header h; int fd; + ssize_t read_bytes; grn_open(fd, path, O_RDWR | GRN_OPEN_FLAG_BINARY); if (fd == -1) { - ERRNO_ERR(path); - GRN_LOG(ctx, GRN_LOG_ERROR, - "failed to open path: <%s>", - path); + ERRNO_ERR("failed to open path: <%s>", + path); return NULL; } - if (fstat(fd, &s) != -1 && s.st_size >= sizeof(struct _grn_io_header)) { - if (grn_read(fd, &h, sizeof(struct _grn_io_header)) == sizeof(struct _grn_io_header)) { - if (!memcmp(h.idstr, GRN_IO_IDSTR, GRN_IO_IDSTR_LEN)) { - header_size = h.header_size; - segment_size = h.segment_size; - max_segment = h.max_segment; - flags = h.flags; - } else { - ERR(GRN_INCOMPATIBLE_FILE_FORMAT, - "failed to open: format ID is different: <%s>: <%.*s>", - path, - (int)GRN_IO_IDSTR_LEN, GRN_IO_IDSTR); - } - } + if (fstat(fd, &s) == -1) { + ERRNO_ERR("[io][open] failed to file status: <%s>", + path); + grn_close(fd); + return NULL; } + if (s.st_size < sizeof(struct _grn_io_header)) { + ERR(GRN_INCOMPATIBLE_FILE_FORMAT, + "[io][open] file size is too small: " + "<%" GRN_FMT_INT64D ">(required: >= %" GRN_FMT_SIZE "): <%s>", + (int64_t)(s.st_size), + sizeof(struct _grn_io_header), + path); + grn_close(fd); + return NULL; + } + read_bytes = grn_read(fd, &h, sizeof(struct _grn_io_header)); + if (read_bytes != sizeof(struct _grn_io_header)) { + ERRNO_ERR("[io][open] failed to read header data: " + "<%" GRN_FMT_SSIZE ">(expected: %" GRN_FMT_SSIZE "): <%s>", + read_bytes, + sizeof(struct _grn_io_header), + path); + grn_close(fd); + return NULL; + } + if (memcmp(h.idstr, GRN_IO_IDSTR, GRN_IO_IDSTR_LEN) != 0) { + ERR(GRN_INCOMPATIBLE_FILE_FORMAT, + "failed to open: format ID is different: <%s>: <%.*s>", + path, + (int)GRN_IO_IDSTR_LEN, GRN_IO_IDSTR); + grn_close(fd); + return NULL; + } + header_size = h.header_size; + segment_size = h.segment_size; + max_segment = h.max_segment; + flags = h.flags; grn_close(fd); - if (!segment_size) { return NULL; } + if (segment_size == 0) { + ERR(GRN_INCOMPATIBLE_FILE_FORMAT, "failed to open: segment size is 0"); + return NULL; + } } b = grn_io_compute_base(header_size); bs = grn_io_compute_base_segment(b, segment_size); grn_fileinfo_init(&fi, 1); if (!grn_fileinfo_open(ctx, &fi, path, O_RDWR)) { struct _grn_io_header *header; - header = GRN_MMAP(&grn_gctx, NULL, &(fi.fmo), &fi, 0, b); + header = GRN_MMAP(ctx, &grn_gctx, NULL, &(fi.fmo), &fi, 0, b); if (header) { unsigned long file_size; unsigned int max_nfiles; @@ -558,17 +645,17 @@ grn_io_open(grn_ctx *ctx, const char *path, grn_io_mode mode) file_size = grn_io_compute_file_size(header->version); max_nfiles = grn_io_compute_max_n_files(segment_size, max_segment, bs, file_size); - fis = GRN_GMALLOCN(fileinfo, max_nfiles); + fis = GRN_MALLOCN(fileinfo, max_nfiles); if (!fis) { - GRN_MUNMAP(&grn_gctx, NULL, &(fi.fmo), &fi, header, b); + GRN_MUNMAP(ctx, &grn_gctx, NULL, &(fi.fmo), &fi, header, b); grn_fileinfo_close(ctx, &fi); return NULL; } grn_fileinfo_init(fis, max_nfiles); grn_memcpy(fis, &fi, sizeof(fileinfo)); - if ((io = GRN_GMALLOC(sizeof(grn_io)))) { + if ((io = GRN_MALLOC(sizeof(grn_io)))) { grn_io_mapinfo *maps = NULL; - if ((maps = GRN_GCALLOC(sizeof(grn_io_mapinfo) * max_segment))) { + if ((maps = GRN_CALLOC(sizeof(grn_io_mapinfo) * max_segment))) { grn_strncpy(io->path, PATH_MAX, path, PATH_MAX); io->header = header; io->user_header = (((byte *) header) + IO_HEADER_SIZE); @@ -584,17 +671,17 @@ grn_io_open(grn_ctx *ctx, const char *path, grn_io_mode mode) io->count = 0; io->flags = header->flags; io->lock = &header->lock; - if (!array_init(io, io->header->n_arrays)) { - grn_io_register(io); + if (!array_init(ctx, io, io->header->n_arrays)) { + grn_io_register(ctx, io); return io; } } - if (io->maps) { GRN_GFREE(io->maps); } + if (io->maps) { GRN_FREE(io->maps); } } - GRN_GFREE(io); + GRN_FREE(io); } - GRN_GFREE(fis); - GRN_MUNMAP(&grn_gctx, NULL, &(fi.fmo), &fi, header, b); + GRN_FREE(fis); + GRN_MUNMAP(ctx, &grn_gctx, NULL, &(fi.fmo), &fi, header, b); } grn_fileinfo_close(ctx, &fi); } @@ -607,8 +694,8 @@ grn_io_close(grn_ctx *ctx, grn_io *io) uint32_t max_nfiles; max_nfiles = grn_io_max_n_files(io); - grn_io_unregister(io); - if (io->ainfo) { GRN_GFREE(io->ainfo); } + grn_io_unregister(ctx, io); + if (io->ainfo) { GRN_FREE(io->ainfo); } if (io->maps) { int i; uint32_t max_segment; @@ -631,12 +718,12 @@ grn_io_close(grn_ctx *ctx, grn_io *io) uint32_t fno = bseg / segments_per_file; fi = &io->fis[fno]; } - GRN_MUNMAP(&grn_gctx, io, &mi->fmo, fi, mi->map, segment_size); + GRN_MUNMAP(ctx, &grn_gctx, io, &mi->fmo, fi, mi->map, segment_size); } } - GRN_GFREE(io->maps); + GRN_FREE(io->maps); } - GRN_MUNMAP(&grn_gctx, io, (io->fis ? &io->fis->fmo : NULL), + GRN_MUNMAP(ctx, &grn_gctx, io, (io->fis ? &io->fis->fmo : NULL), io->fis, io->header, io->base); if (io->fis) { int i; @@ -644,9 +731,9 @@ grn_io_close(grn_ctx *ctx, grn_io *io) fileinfo *fi = &(io->fis[i]); grn_fileinfo_close(ctx, fi); } - GRN_GFREE(io->fis); + GRN_FREE(io->fis); } - GRN_GFREE(io); + GRN_FREE(io); return GRN_SUCCESS; } @@ -699,6 +786,14 @@ gen_pathname(const char *path, char *buffer, int fno) } } +static uint32_t +grn_io_n_files(grn_ctx *ctx, grn_io *io) +{ + unsigned long file_size; + file_size = grn_io_compute_file_size(io->header->version); + return ((io->header->curr_size + file_size - 1) / file_size); +} + grn_rc grn_io_size(grn_ctx *ctx, grn_io *io, uint64_t *size) { @@ -706,22 +801,14 @@ grn_io_size(grn_ctx *ctx, grn_io *io, uint64_t *size) struct stat s; uint64_t tsize = 0; char buffer[PATH_MAX]; - uint32_t nfiles; + uint32_t n_files; - if (io->header->curr_size) { - unsigned long file_size; - file_size = grn_io_compute_file_size(io->header->version); - nfiles = (uint32_t) ((io->header->curr_size + file_size - 1) / file_size); - } else { - nfiles = grn_io_max_n_files(io); - } - for (fno = 0; fno < nfiles; fno++) { + n_files = grn_io_n_files(ctx, io); + for (fno = 0; fno < n_files; fno++) { gen_pathname(io->path, buffer, fno); if (stat(buffer, &s)) { - SERR(buffer); - GRN_LOG(ctx, GRN_LOG_ERROR, - "failed to stat path to compute size: <%s>", - buffer); + SERR("failed to stat path to compute size: <%s>", + buffer); } else { tsize += s.st_size; } @@ -731,36 +818,58 @@ grn_io_size(grn_ctx *ctx, grn_io *io, uint64_t *size) } grn_rc +grn_io_remove_raw(grn_ctx *ctx, const char *path) +{ + grn_rc rc = GRN_SUCCESS; + int fno; + char buffer[PATH_MAX]; + + if (grn_unlink(path) != 0) { + ERRNO_ERR("[io][remove] failed to remove path: <%s>", + path); + return ctx->rc; + } + GRN_LOG(ctx, GRN_LOG_INFO, "[io][remove] removed path: <%s>", path); + + for (fno = 1; ; fno++) { + struct stat s; + gen_pathname(path, buffer, fno); + if (stat(buffer, &s) != 0) { + break; + } + if (grn_unlink(buffer) == 0) { + GRN_LOG(ctx, GRN_LOG_INFO, + "[io][remove] removed numbered path: <%d>: <%s>", fno, buffer); + } else { + ERRNO_ERR("[io][remove] failed to remove numbered path: <%d>: <%s>", + fno, buffer); + rc = ctx->rc; + } + } + return rc; +} + +grn_rc grn_io_remove(grn_ctx *ctx, const char *path) { struct stat s; - if (stat(path, &s)) { - SERR("stat"); - return ctx->rc; - } else if (grn_unlink(path)) { - ERRNO_ERR(path); - GRN_LOG(ctx, GRN_LOG_ERROR, - "failed to remove path: <%s>", - path); + + if (stat(path, &s) != 0) { + SERR("failed to stat: <%s>", path); return ctx->rc; - } else { - int fno; - char buffer[PATH_MAX]; - for (fno = 1; ; fno++) { - gen_pathname(path, buffer, fno); - if (!stat(buffer, &s)) { - if (grn_unlink(buffer)) { - ERRNO_ERR(buffer); - GRN_LOG(ctx, GRN_LOG_ERROR, - "failed to remove path: <%s>", - buffer); - } - } else { - break; - } - } - return GRN_SUCCESS; } + + return grn_io_remove_raw(ctx, path); +} + +grn_rc +grn_io_remove_if_exist(grn_ctx *ctx, const char *path) +{ + struct stat s; + if (stat(path, &s) == 0) { + return grn_io_remove_raw(ctx, path); + } + return GRN_SUCCESS; } grn_rc @@ -768,13 +877,11 @@ grn_io_rename(grn_ctx *ctx, const char *old_name, const char *new_name) { struct stat s; if (stat(old_name, &s)) { - SERR("stat"); + SERR("failed to stat path to be renamed: <%s>", old_name); return ctx->rc; } else if (rename(old_name, new_name)) { - SERR(old_name); - GRN_LOG(ctx, GRN_LOG_ERROR, - "failed to rename path: <%s> -> <%s>", - old_name, new_name); + SERR("failed to rename path: <%s> -> <%s>", + old_name, new_name); return ctx->rc; } else { int fno; @@ -785,16 +892,12 @@ grn_io_rename(grn_ctx *ctx, const char *old_name, const char *new_name) if (!stat(old_buffer, &s)) { gen_pathname(new_name, new_buffer, fno); if (rename(old_buffer, new_buffer)) { - SERR(old_buffer); - GRN_LOG(ctx, GRN_LOG_ERROR, - "failed to rename path: <%s> -> <%s>", - old_buffer, new_buffer); + SERR("failed to rename path: <%s> -> <%s>", + old_buffer, new_buffer); } } else { - SERR("stat"); - GRN_LOG(ctx, GRN_LOG_ERROR, - "failed to stat path to rename: <%s>", - old_buffer); + SERR("failed to stat path to be renamed: <%s>", + old_buffer); return ctx->rc; } } @@ -808,8 +911,9 @@ typedef struct { } ja_element; grn_rc -grn_io_read_ja(grn_io *io, grn_ctx *ctx, grn_io_ja_einfo *einfo, uint32_t epos, uint32_t key, - uint32_t segment, uint32_t offset, void **value, uint32_t *value_len) +grn_io_read_ja(grn_io *io, grn_ctx *ctx, grn_io_ja_einfo *einfo, uint32_t epos, + uint32_t key, uint32_t segment, uint32_t offset, void **value, + uint32_t *value_len) { uint32_t rest = 0, size = *value_len + sizeof(grn_io_ja_ehead); uint32_t segment_size = io->header->segment_size; @@ -847,28 +951,32 @@ grn_io_read_ja(grn_io *io, grn_ctx *ctx, grn_io_ja_einfo *einfo, uint32_t epos, return ctx->rc; } if (einfo->pos != epos) { - GRN_LOG(ctx, GRN_LOG_WARNING, "einfo pos changed %x => %x", einfo->pos, epos); + GRN_LOG(ctx, GRN_LOG_WARNING, + "einfo pos changed %x => %x", einfo->pos, epos); *value = NULL; *value_len = 0; GRN_FREE(v); return GRN_FILE_CORRUPT; } if (einfo->size != *value_len) { - GRN_LOG(ctx, GRN_LOG_WARNING, "einfo size changed %d => %d", einfo->size, *value_len); + GRN_LOG(ctx, GRN_LOG_WARNING, + "einfo size changed %d => %d", einfo->size, *value_len); *value = NULL; *value_len = 0; GRN_FREE(v); return GRN_FILE_CORRUPT; } if (v->head.key != key) { - GRN_LOG(ctx, GRN_LOG_ERROR, "ehead key unmatch %x => %x", key, v->head.key); + GRN_LOG(ctx, GRN_LOG_ERROR, + "ehead key unmatch %x => %x", key, v->head.key); *value = NULL; *value_len = 0; GRN_FREE(v); return GRN_INVALID_FORMAT; } if (v->head.size != *value_len) { - GRN_LOG(ctx, GRN_LOG_ERROR, "ehead size unmatch %d => %d", *value_len, v->head.size); + GRN_LOG(ctx, GRN_LOG_ERROR, + "ehead size unmatch %d => %d", *value_len, v->head.size); *value = NULL; *value_len = 0; GRN_FREE(v); @@ -905,7 +1013,8 @@ grn_io_read_ja(grn_io *io, grn_ctx *ctx, grn_io_ja_einfo *einfo, uint32_t epos, grn_rc grn_io_write_ja(grn_io *io, grn_ctx *ctx, uint32_t key, - uint32_t segment, uint32_t offset, void *value, uint32_t value_len) + uint32_t segment, uint32_t offset, void *value, + uint32_t value_len) { grn_rc rc; uint32_t rest = 0, size = value_len + sizeof(grn_io_ja_ehead); @@ -936,7 +1045,9 @@ grn_io_write_ja(grn_io *io, grn_ctx *ctx, uint32_t key, grn_io_ja_ehead eh; eh.size = value_len; eh.key = key; - if ((rc = grn_pwrite(ctx, fi, &eh, sizeof(grn_io_ja_ehead), pos))) { return rc; } + if ((rc = grn_pwrite(ctx, fi, &eh, sizeof(grn_io_ja_ehead), pos))) { + return rc; + } pos += sizeof(grn_io_ja_ehead); rc = grn_pwrite(ctx, fi, value, size - sizeof(grn_io_ja_ehead), pos); } @@ -948,7 +1059,9 @@ grn_io_write_ja(grn_io *io, grn_ctx *ctx, uint32_t key, if (!grn_fileinfo_opened(fi)) { char path[PATH_MAX]; gen_pathname(io->path, path, fno); - if ((rc = grn_fileinfo_open(ctx, fi, path, O_RDWR|O_CREAT))) { return rc; } + if ((rc = grn_fileinfo_open(ctx, fi, path, O_RDWR|O_CREAT))) { + return rc; + } } size = rest > file_size ? file_size : rest; if ((rc = grn_pwrite(ctx, fi, vr, size, 0))) { return rc; } @@ -995,7 +1108,9 @@ grn_io_win_map(grn_io *io, grn_ctx *ctx, grn_io_win *iw, uint32_t segment, offset = offset % segment_size; } nseg = (offset + size + segment_size - 1) / segment_size; - if (!size || !ctx || segment + nseg > io->header->max_segment) { return NULL; } + if (!size || !ctx || segment + nseg > io->header->max_segment) { + return NULL; + } iw->ctx = ctx; iw->diff = 0; iw->io = io; @@ -1063,7 +1178,8 @@ grn_io_win_unmap(grn_io_win *iw) byte *p, *q = NULL; uint32_t segment_size = io->header->segment_size; uint32_t s, r, offset = iw->offset, segment = iw->segment; - for (p = iw->addr, r = iw->size; r; p += s, r -= s, segment++, offset = 0) { + for (p = iw->addr, r = iw->size; r; + p += s, r -= s, segment++, offset = 0) { GRN_IO_SEG_REF(io, segment, q); if (!q) { return GRN_NO_MEMORY_AVAILABLE; } s = (offset + r > segment_size) ? segment_size - offset : r; @@ -1080,7 +1196,8 @@ grn_io_win_unmap(grn_io_win *iw) } #define DO_MAP(io,fmo,fi,pos,size,segno,res) do {\ - if (((res) = GRN_MMAP(&grn_gctx, (io), (fmo), (fi), (pos), (size)))) {\ + (res) = GRN_MMAP(ctx, &grn_gctx, (io), (fmo), (fi), (pos), (size));\ + if ((res)) {\ uint32_t nmaps;\ if (io->max_map_seg < segno) { io->max_map_seg = segno; }\ GRN_ATOMIC_ADD_EX(&io->nmaps, 1, nmaps);\ @@ -1107,9 +1224,21 @@ grn_io_seg_map_(grn_ctx *ctx, grn_io *io, uint32_t segno, grn_io_mapinfo *info) fileinfo *fi = &io->fis[fno]; if (!grn_fileinfo_opened(fi)) { char path[PATH_MAX]; + grn_bool path_exist = GRN_TRUE; gen_pathname(io->path, path, fno); + path_exist = grn_path_exist(path); if (!grn_fileinfo_open(ctx, fi, path, O_RDWR|O_CREAT)) { DO_MAP(io, &info->fmo, fi, pos, segment_size, segno, info->map); + if (!info->map && !path_exist) { + if (grn_unlink(path) == 0) { + GRN_LOG(ctx, GRN_LOG_INFO, + "[io][map][error] memory mapping is failed and then " + "removed created map file: <%s>", path); + } else { + ERRNO_ERR("[io][map][error] memory mapping is failed and then " + "failed to remove created map file: <%s>", path); + } + } } } else { DO_MAP(io, &info->fmo, fi, pos, segment_size, segno, info->map); @@ -1132,7 +1261,9 @@ grn_io_seg_expire(grn_ctx *ctx, grn_io *io, uint32_t segno, uint32_t nretry) if (nref) { GRN_ATOMIC_ADD_EX(pnref, -1, nref); if (retry >= GRN_IO_MAX_RETRY) { - GRN_LOG(ctx, GRN_LOG_CRIT, "deadlock detected! in grn_io_seg_expire(%p, %u, %u)", io, segno, nref); + GRN_LOG(ctx, GRN_LOG_CRIT, + "deadlock detected! in grn_io_seg_expire(%p, %u, %u)", + io, segno, nref); return GRN_RESOURCE_DEADLOCK_AVOIDED; } } else { @@ -1141,14 +1272,15 @@ grn_io_seg_expire(grn_ctx *ctx, grn_io *io, uint32_t segno, uint32_t nretry) GRN_ATOMIC_ADD_EX(pnref, -(GRN_IO_MAX_REF + 1), nref); GRN_FUTEX_WAKE(pnref); if (retry >= GRN_IO_MAX_RETRY) { - GRN_LOG(ctx, GRN_LOG_CRIT, "deadlock detected!! in grn_io_seg_expire(%p, %u, %u)", io, - segno, nref); + GRN_LOG(ctx, GRN_LOG_CRIT, + "deadlock detected!! in grn_io_seg_expire(%p, %u, %u)", + io, segno, nref); return GRN_RESOURCE_DEADLOCK_AVOIDED; } } else { uint32_t nmaps; fileinfo *fi = &(io->fis[segno]); - GRN_MUNMAP(&grn_gctx, io, &info->fmo, fi, + GRN_MUNMAP(ctx, &grn_gctx, io, &info->fmo, fi, info->map, io->header->segment_size); info->map = NULL; GRN_ATOMIC_ADD_EX(pnref, -(GRN_IO_MAX_REF + 1), nref); @@ -1176,7 +1308,8 @@ grn_io_expire(grn_ctx *ctx, grn_io *io, int count_thresh, uint32_t limit) uint32_t i = io->header->n_arrays; grn_io_array_spec *array_specs = (grn_io_array_spec *)io->user_header; while (i--) { - memset(io->ainfo[i].addrs, 0, sizeof(void *) * array_specs[i].max_n_segments); + memset(io->ainfo[i].addrs, 0, + sizeof(void *) * array_specs[i].max_n_segments); } } { @@ -1185,7 +1318,7 @@ grn_io_expire(grn_ctx *ctx, grn_io *io, int count_thresh, uint32_t limit) grn_io_mapinfo *info = &(io->maps[fno]); if (info->map) { fileinfo *fi = &(io->fis[fno]); - GRN_MUNMAP(&grn_gctx, io, &info->fmo, fi, + GRN_MUNMAP(ctx, &grn_gctx, io, &info->fmo, fi, info->map, io->header->segment_size); info->map = NULL; info->nref = 0; @@ -1212,7 +1345,7 @@ grn_io_expire(grn_ctx *ctx, grn_io *io, int count_thresh, uint32_t limit) uint32_t nmaps, nref, *pnref = &info->nref; GRN_ATOMIC_ADD_EX(pnref, 1, nref); if (!nref && info->map && (grn_gtick - info->count) > count_thresh) { - GRN_MUNMAP(&grn_gctx, io, &info->fmo, NULL, + GRN_MUNMAP(ctx, &grn_gctx, io, &info->fmo, NULL, info->map, io->header->segment_size); GRN_ATOMIC_ADD_EX(&io->nmaps, -1, nmaps); info->map = NULL; @@ -1226,58 +1359,22 @@ grn_io_expire(grn_ctx *ctx, grn_io *io, int count_thresh, uint32_t limit) break; } if (n) { - GRN_LOG(ctx, GRN_LOG_INFO, "<%p:%x> expired i=%p max=%d (%d/%d)", + GRN_LOG(ctx, GRN_LOG_DEBUG, "<%p:%x> expired i=%p max=%d (%d/%d)", ctx, grn_gtick, io, io->max_map_seg, n, ln); } return n; } -static uint32_t -grn_expire_(grn_ctx *ctx, int count_thresh, uint32_t limit) -{ - uint32_t n = 0; - grn_io *io; - GRN_HASH_EACH(ctx, grn_gctx.impl->ios, id, NULL, NULL, (void **)&io, { - grn_plugin_close(ctx, id); - n += grn_io_expire(ctx, io, count_thresh, limit); - if (n >= limit) { break; } - }); - return n; -} - -uint32_t -grn_expire(grn_ctx *ctx, int count_thresh, uint32_t limit) -{ - grn_ctx *c; - uint32_t n = 0; - CRITICAL_SECTION_ENTER(grn_glock); - if (grn_gtick) { - for (c = grn_gctx.next;; c = ctx->next) { - if (c == &grn_gctx) { - CRITICAL_SECTION_LEAVE(grn_glock); - n = grn_expire_(ctx, count_thresh, limit); - CRITICAL_SECTION_ENTER(grn_glock); - break; - } - if ((c->seqno & 1) && (c->seqno == c->seqno2)) { break; } - } - } - grn_gtick++; - for (c = grn_gctx.next; c != &grn_gctx; c = ctx->next) { c->seqno2 = c->seqno; } - CRITICAL_SECTION_LEAVE(grn_glock); - return n; -} - void * grn_io_anon_map(grn_ctx *ctx, grn_io_mapinfo *mi, size_t length) { - return (mi->map = GRN_MMAP(ctx, NULL, &mi->fmo, NULL, 0, length)); + return (mi->map = GRN_MMAP(ctx, ctx, NULL, &mi->fmo, NULL, 0, length)); } void grn_io_anon_unmap(grn_ctx *ctx, grn_io_mapinfo *mi, size_t length) { - GRN_MUNMAP(ctx, NULL, &mi->fmo, NULL, mi->map, length); + GRN_MUNMAP(ctx, ctx, NULL, &mi->fmo, NULL, mi->map, length); } grn_rc @@ -1285,6 +1382,7 @@ grn_io_lock(grn_ctx *ctx, grn_io *io, int timeout) { static int _ncalls = 0, _ncolls = 0; uint32_t count, count_log_border = 1000; + uint32_t rc_check_interval = 1000; _ncalls++; if (!io) { return GRN_INVALID_ARGUMENT; } for (count = 0;; count++) { @@ -1311,6 +1409,11 @@ grn_io_lock(grn_ctx *ctx, grn_io *io, int timeout) "io(%s) collisions(%d/%d)", io->path, _ncolls, _ncalls); } } + if ((count % rc_check_interval) == 0) { + if (ctx->rc != GRN_SUCCESS) { + return ctx->rc; + } + } grn_nanosleep(GRN_LOCK_WAIT_TIME_NANOSECOND); continue; } @@ -1348,14 +1451,14 @@ grn_io_flush(grn_ctx *ctx, grn_io *io) struct _grn_io_header *header; uint32_t aligned_header_size; - if (!io->path) { + if (io->path[0] == '\0') { return GRN_SUCCESS; } header = io->header; aligned_header_size = grn_io_compute_base(header->header_size); - if (grn_msync(ctx, header, aligned_header_size) != 0) { + if (GRN_MSYNC(ctx, io->fis[0].fh, header, aligned_header_size) != 0) { return ctx->rc; } @@ -1368,13 +1471,37 @@ grn_io_flush(grn_ctx *ctx, grn_io *io) segment_size = header->segment_size; for (i = 0; i < max_mapped_segment; i++) { grn_io_mapinfo *info = &(io->maps[i]); + uint32_t nth_file_info; + uint32_t *pnref; + uint32_t nref; + int msync_result; + if (!info) { continue; } + + pnref = &info->nref; + GRN_ATOMIC_ADD_EX(pnref, 1, nref); + if (nref != 0) { + GRN_ATOMIC_ADD_EX(pnref, -1, nref); + continue; + } + if (!info->map) { + GRN_ATOMIC_ADD_EX(pnref, -1, nref); + GRN_FUTEX_WAKE(pnref); continue; } - if (grn_msync(ctx, info->map, segment_size) != 0) { + + nth_file_info = grn_io_compute_nth_file_info(io, i); + msync_result = GRN_MSYNC(ctx, + io->fis[nth_file_info].fh, + info->map, + segment_size); + GRN_ATOMIC_ADD_EX(pnref, -1, nref); + GRN_FUTEX_WAKE(pnref); + + if (msync_result != 0) { rc = ctx->rc; break; } @@ -1384,6 +1511,56 @@ grn_io_flush(grn_ctx *ctx, grn_io *io) return rc; } +grn_bool +grn_io_is_corrupt(grn_ctx *ctx, grn_io *io) +{ + uint32_t i; + uint32_t n_files; + + if (!io) { + return GRN_FALSE; + } + + n_files = grn_io_n_files(ctx, io); + for (i = 0; i < n_files; i++) { + char path[PATH_MAX]; + struct stat s; + gen_pathname(io->path, path, i); + if (stat(path, &s) != 0) { + SERR("[io][corrupt] used path doesn't exist: <%s>", + path); + return GRN_TRUE; + } + } + + return GRN_FALSE; +} + +size_t +grn_io_get_disk_usage(grn_ctx *ctx, grn_io *io) +{ + size_t usage = 0; + uint32_t i; + uint32_t n_files; + + if (!io) { + return usage; + } + + n_files = grn_io_n_files(ctx, io); + for (i = 0; i < n_files; i++) { + char path[PATH_MAX]; + struct stat s; + gen_pathname(io->path, path, i); + if (stat(path, &s) != 0) { + continue; + } + usage += s.st_size; + } + + return usage; +} + /** mmap abstraction **/ static size_t mmap_size = 0; @@ -1398,7 +1575,8 @@ grn_fileinfo_open_v1(grn_ctx *ctx, fileinfo *fi, const char *path, int flags) } inline static void * -grn_mmap_v1(grn_ctx *ctx, HANDLE *fmo, fileinfo *fi, off_t offset, size_t length) +grn_mmap_v1(grn_ctx *ctx, grn_ctx *owner_ctx, HANDLE *fmo, fileinfo *fi, + off_t offset, size_t length) { void *res; if (!fi) { @@ -1409,26 +1587,22 @@ grn_mmap_v1(grn_ctx *ctx, HANDLE *fmo, fileinfo *fi, off_t offset, size_t length * If VirtualAlloc() provides better performance rather than malloc(), * we'll use it. */ - return GRN_GCALLOC(length); + return GRN_CALLOC(length); } /* CRITICAL_SECTION_ENTER(fi->cs); */ /* try to create fmo */ *fmo = CreateFileMapping(fi->fh, NULL, PAGE_READWRITE, 0, offset + length, NULL); if (!*fmo) { - SERR("CreateFileMapping"); - GRN_LOG(ctx, GRN_LOG_ERROR, - "CreateFileMapping(%lu + %" GRN_FMT_SIZE ") failed " - "<%" GRN_FMT_SIZE ">", - (DWORD)offset, length, - mmap_size); + SERR("CreateFileMapping(%lu + %" GRN_FMT_SIZE ") failed " + "<%" GRN_FMT_SIZE ">", + (DWORD)offset, length, + mmap_size); return NULL; } res = MapViewOfFile(*fmo, FILE_MAP_WRITE, 0, (DWORD)offset, (SIZE_T)length); if (!res) { - SERR("MapViewOfFile"); - GRN_LOG(ctx, GRN_LOG_ERROR, - "MapViewOfFile(%lu,%" GRN_FMT_SIZE ") failed <%" GRN_FMT_SIZE ">", - (DWORD)offset, length, mmap_size); + SERR("MapViewOfFile(%lu,%" GRN_FMT_SIZE ") failed <%" GRN_FMT_SIZE ">", + (DWORD)offset, length, mmap_size); return NULL; } /* CRITICAL_SECTION_LEAVE(fi->cs); */ @@ -1437,18 +1611,18 @@ grn_mmap_v1(grn_ctx *ctx, HANDLE *fmo, fileinfo *fi, off_t offset, size_t length } inline static int -grn_munmap_v1(grn_ctx *ctx, HANDLE *fmo, fileinfo *fi, +grn_munmap_v1(grn_ctx *ctx, grn_ctx *owner_ctx, HANDLE *fmo, fileinfo *fi, void *start, size_t length) { int r = 0; if (!fi) { - GRN_GFREE(start); + GRN_FREE(start); return r; } if (!fmo) { - GRN_GFREE(start); + GRN_FREE(start); return r; } @@ -1456,21 +1630,17 @@ grn_munmap_v1(grn_ctx *ctx, HANDLE *fmo, fileinfo *fi, if (UnmapViewOfFile(start)) { mmap_size -= length; } else { - SERR("UnmapViewOfFile"); - GRN_LOG(ctx, GRN_LOG_ERROR, - "UnmapViewOfFile(%p,%" GRN_FMT_SIZE ") failed <%" GRN_FMT_SIZE ">", - start, length, mmap_size); + SERR("UnmapViewOfFile(%p,%" GRN_FMT_SIZE ") failed <%" GRN_FMT_SIZE ">", + start, length, mmap_size); r = -1; } if (!CloseHandle(*fmo)) { - SERR("CloseHandle"); - GRN_LOG(ctx, GRN_LOG_ERROR, - "CloseHandle(%p,%" GRN_FMT_SIZE ") failed <%" GRN_FMT_SIZE ">", - start, length, mmap_size); + SERR("CloseHandle(%p,%" GRN_FMT_SIZE ") failed <%" GRN_FMT_SIZE ">", + start, length, mmap_size); } *fmo = NULL; } else { - GRN_GFREE(start); + GRN_FREE(start); } return r; @@ -1489,7 +1659,8 @@ grn_fileinfo_open_v0(grn_ctx *ctx, fileinfo *fi, const char *path, int flags) /* failed again */ if (fi->fmo == NULL) { /* try to create fmo */ - fi->fmo = CreateFileMapping(fi->fh, NULL, PAGE_READWRITE, 0, GRN_IO_FILE_SIZE_V0, NULL); + fi->fmo = CreateFileMapping(fi->fh, NULL, PAGE_READWRITE, 0, + GRN_IO_FILE_SIZE_V0, NULL); } // funlock } @@ -1498,7 +1669,8 @@ grn_fileinfo_open_v0(grn_ctx *ctx, fileinfo *fi, const char *path, int flags) CRITICAL_SECTION_INIT(fi->cs); return GRN_SUCCESS; } else { - GRN_LOG(ctx, GRN_LOG_ERROR, "fmo object already exists! handle=%p", fi->fh); + GRN_LOG(ctx, GRN_LOG_ERROR, + "fmo object already exists! handle=%p", fi->fh); CloseHandle(fi->fmo); } } else { @@ -1511,10 +1683,11 @@ grn_fileinfo_open_v0(grn_ctx *ctx, fileinfo *fi, const char *path, int flags) } inline static void * -grn_mmap_v0(grn_ctx *ctx, fileinfo *fi, off_t offset, size_t length) +grn_mmap_v0(grn_ctx *ctx, grn_ctx *owner_ctx, fileinfo *fi, off_t offset, + size_t length) { void *res; - if (!fi) { return GRN_GCALLOC(length); } + if (!fi) { return GRN_CALLOC(length); } /* file must be exceeded to GRN_IO_FILE_SIZE_V0 when FileMappingObject created. and, after fmo created, it's not allowed to expand the size of file. DWORD tail = (DWORD)(offset + length); @@ -1542,10 +1715,11 @@ grn_mmap_v0(grn_ctx *ctx, fileinfo *fi, off_t offset, size_t length) } inline static int -grn_munmap_v0(grn_ctx *ctx, fileinfo *fi, void *start, size_t length) +grn_munmap_v0(grn_ctx *ctx, grn_ctx *owner_ctx, fileinfo *fi, void *start, + size_t length) { if (!fi) { - GRN_GFREE(start); + GRN_FREE(start); return 0; } @@ -1553,10 +1727,8 @@ grn_munmap_v0(grn_ctx *ctx, fileinfo *fi, void *start, size_t length) mmap_size -= length; return 0; } else { - SERR("UnmapViewOfFile"); - GRN_LOG(ctx, GRN_LOG_ERROR, - "UnmapViewOfFile(%p,%" GRN_FMT_SIZE ") failed <%" GRN_FMT_SIZE ">", - start, length, mmap_size); + SERR("UnmapViewOfFile(%p,%" GRN_FMT_SIZE ") failed <%" GRN_FMT_SIZE ">", + start, length, mmap_size); return -1; } } @@ -1576,43 +1748,85 @@ grn_fileinfo_open_common(grn_ctx *ctx, fileinfo *fi, const char *path, int flags flags_description = "O_RDWR|O_CREAT"; } fi->fh = CreateFile(path, GRN_IO_FILE_CREATE_MODE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, 0); if (fi->fh == INVALID_HANDLE_VALUE) { - SERR("CreateFile"); - GRN_LOG(ctx, GRN_LOG_ERROR, - "CreateFile(<%s>, <%s>) failed", - path, flags_description); + SERR("CreateFile(<%s>, <%s>) failed", + path, flags_description); goto exit; } + + switch (dwCreationDisposition) { + case CREATE_NEW : + GRN_LOG(ctx, GRN_LOG_INFO, + "[io][open] create new file: <%s>", path); + break; + case OPEN_ALWAYS : + if (GetLastError() == ERROR_ALREADY_EXISTS) { + GRN_LOG(ctx, GRN_LOG_INFO, + "[io][open] open existing file because it exists: <%s>", path); + } else { + GRN_LOG(ctx, GRN_LOG_INFO, + "[io][open] create new file because it doesn't exist: <%s>", + path); + } + break; + default : + break; + } + + if (grn_io_use_sparse) { + FILE_SET_SPARSE_BUFFER buffer; + buffer.SetSparse = TRUE; + DWORD returned_bytes; + if (!DeviceIoControl(fi->fh, + FSCTL_SET_SPARSE, + &buffer, + sizeof(FILE_SET_SPARSE_BUFFER), + NULL, + 0, + &returned_bytes, + NULL)) { + GRN_LOG(ctx, GRN_LOG_INFO, + "Tried to make file sparse but failed: " + "DeviceIoControl(FSCTL_SET_SPARSE): " + "<%s>: <%s>", + path, grn_current_error_message()); + } + } + goto exit; } + if ((flags & O_TRUNC)) { CloseHandle(fi->fh); /* unable to assign OPEN_ALWAYS and TRUNCATE_EXISTING at once */ fi->fh = CreateFile(path, GRN_IO_FILE_CREATE_MODE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (fi->fh == INVALID_HANDLE_VALUE) { - SERR("CreateFile"); - GRN_LOG(ctx, GRN_LOG_ERROR, - "CreateFile(<%s>, <O_RDWR|O_TRUNC>) failed", - path); + SERR("CreateFile(<%s>, <O_RDWR|O_TRUNC>) failed", + path); goto exit; } + GRN_LOG(ctx, GRN_LOG_INFO, + "[io][open] truncated: <%s>", path); goto exit; } /* O_RDWR only */ fi->fh = CreateFile(path, GRN_IO_FILE_CREATE_MODE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (fi->fh == INVALID_HANDLE_VALUE) { - SERR("CreateFile"); - GRN_LOG(ctx, GRN_LOG_ERROR, - "CreateFile(<%s>, <O_RDWR>) failed", - path); + SERR("CreateFile(<%s>, <O_RDWR>) failed", + path); goto exit; } + GRN_LOG(ctx, GRN_LOG_INFO, + "[io][open] open existing file: <%s>", path); exit : return ctx->rc; @@ -1623,16 +1837,21 @@ grn_fileinfo_open(grn_ctx *ctx, fileinfo *fi, const char *path, int flags) { grn_rc rc; struct _grn_io_header io_header; - DWORD header_size; - DWORD read_bytes; + LARGE_INTEGER file_size; int version = grn_io_version_default; rc = grn_fileinfo_open_common(ctx, fi, path, flags); if (rc != GRN_SUCCESS) { + if (fi->fh) { + CloseHandle(fi->fh); + fi->fh = INVALID_HANDLE_VALUE; + } return rc; } - if (!(flags & O_CREAT)) { + if (GetFileSizeEx(fi->fh, &file_size) && file_size.QuadPart > 0) { + DWORD header_size; + DWORD read_bytes; header_size = sizeof(struct _grn_io_header); ReadFile(fi->fh, &io_header, header_size, &read_bytes, NULL); if (read_bytes == header_size) { @@ -1667,7 +1886,7 @@ grn_guess_io_version(grn_ctx *ctx, grn_io *io, fileinfo *fi) } inline static void * -grn_mmap(grn_ctx *ctx, grn_io *io, HANDLE *fmo, +grn_mmap(grn_ctx *ctx, grn_ctx *owner_ctx, grn_io *io, HANDLE *fmo, fileinfo *fi, off_t offset, size_t length) { int version; @@ -1675,14 +1894,14 @@ grn_mmap(grn_ctx *ctx, grn_io *io, HANDLE *fmo, version = grn_guess_io_version(ctx, io, fi); if (version == 0) { - return grn_mmap_v0(ctx, fi, offset, length); + return grn_mmap_v0(ctx, owner_ctx, fi, offset, length); } else { - return grn_mmap_v1(ctx, fmo, fi, offset, length); + return grn_mmap_v1(ctx, owner_ctx, fmo, fi, offset, length); } } inline static int -grn_munmap(grn_ctx *ctx, grn_io *io, +grn_munmap(grn_ctx *ctx, grn_ctx *owner_ctx, grn_io *io, HANDLE *fmo, fileinfo *fi, void *start, size_t length) { int version; @@ -1690,9 +1909,9 @@ grn_munmap(grn_ctx *ctx, grn_io *io, version = grn_guess_io_version(ctx, io, fi); if (version == 0) { - return grn_munmap_v0(ctx, fi, start, length); + return grn_munmap_v0(ctx, owner_ctx, fi, start, length); } else { - return grn_munmap_v1(ctx, fmo, fi, start, length); + return grn_munmap_v1(ctx, owner_ctx, fmo, fi, start, length); } } @@ -1727,20 +1946,45 @@ grn_fileinfo_opened(fileinfo *fi) } inline static int -grn_msync(grn_ctx *ctx, void *start, size_t length) +grn_msync(grn_ctx *ctx, HANDLE handle, void *start, size_t length) { BOOL succeeded; + SYSTEMTIME system_time; + FILETIME file_time; succeeded = FlushViewOfFile(start, length); - if (succeeded) { + if (!succeeded) { + SERR("FlushViewOfFile(<%p>, <%" GRN_FMT_SIZE ">) failed", + start, length); + return -1; + } + + if (handle == INVALID_HANDLE_VALUE) { return 0; - } else { - SERR("FlushViewOfFile"); - GRN_LOG(ctx, GRN_LOG_ERROR, - "FlushViewOfFile(<%p>, <%" GRN_FMT_SIZE ">) failed", - start, length); + } + + GetSystemTime(&system_time); + succeeded = SystemTimeToFileTime(&system_time, &file_time); + if (!succeeded) { + SERR("SystemTimeToFileTime(<%04u-%02u-%02uT%02u:%02u:%02u.%03u>) failed", + system_time.wYear, + system_time.wMonth, + system_time.wDay, + system_time.wHour, + system_time.wMinute, + system_time.wSecond, + system_time.wMilliseconds); return -1; } + + succeeded = SetFileTime(handle, NULL, NULL, &file_time); + if (!succeeded) { + SERR("SetFileTime(<%p>, <%p>, <%" GRN_FMT_SIZE ">) failed", + handle, start, length); + return -1; + } + + return 0; } inline static grn_rc @@ -1795,17 +2039,13 @@ grn_fileinfo_open(grn_ctx *ctx, fileinfo *fi, const char *path, int flags) struct stat st; grn_open(fi->fd, path, flags); if (fi->fd == -1) { - ERRNO_ERR(path); - GRN_LOG(ctx, GRN_LOG_ERROR, - "failed to open file info path: <%s>", - path); + ERRNO_ERR("failed to open file info path: <%s>", + path); return ctx->rc; } if (fstat(fi->fd, &st) == -1) { - ERRNO_ERR(path); - GRN_LOG(ctx, GRN_LOG_ERROR, - "failed to stat file info path: <%s>", - path); + ERRNO_ERR("failed to stat file info path: <%s>", + path); return ctx->rc; } fi->dev = st.st_dev; @@ -1845,7 +2085,8 @@ grn_fileinfo_close(grn_ctx *ctx, fileinfo *fi) #include <sys/mman.h> inline static void * -grn_mmap(grn_ctx *ctx, grn_io *io, fileinfo *fi, off_t offset, size_t length) +grn_mmap(grn_ctx *ctx, grn_ctx *owner_ctx, grn_io *io, fileinfo *fi, + off_t offset, size_t length) { void *res; int fd, flags; @@ -1865,8 +2106,8 @@ grn_mmap(grn_ctx *ctx, grn_io *io, fileinfo *fi, off_t offset, size_t length) res = mmap(NULL, length, PROT_READ|PROT_WRITE, flags, fd, offset); if (MAP_FAILED == res) { MERR("mmap(%" GRN_FMT_LLU ",%d,%" GRN_FMT_LLD ")=%s <%" GRN_FMT_LLU ">", - (unsigned long long int)length, fd, (long long int)offset, strerror(errno), - (unsigned long long int)mmap_size); + (unsigned long long int)length, fd, (long long int)offset, + strerror(errno), (unsigned long long int)mmap_size); return NULL; } mmap_size += length; @@ -1875,7 +2116,7 @@ grn_mmap(grn_ctx *ctx, grn_io *io, fileinfo *fi, off_t offset, size_t length) #ifdef USE_FAIL_MALLOC inline static void * -grn_fail_mmap(grn_ctx *ctx, grn_io *io, fileinfo *fi, +grn_fail_mmap(grn_ctx *ctx, grn_ctx *owner_ctx, grn_io *io, fileinfo *fi, off_t offset, size_t length, const char* file, int line, const char *func) { @@ -1905,14 +2146,16 @@ grn_msync(grn_ctx *ctx, void *start, size_t length) } inline static int -grn_munmap(grn_ctx *ctx, grn_io *io, fileinfo *fi, void *start, size_t length) +grn_munmap(grn_ctx *ctx, grn_ctx *owner_ctx, grn_io *io, fileinfo *fi, + void *start, size_t length) { int res; res = munmap(start, length); if (res) { - SERR("munmap"); - GRN_LOG(ctx, GRN_LOG_ERROR, "munmap(%p,%" GRN_FMT_LLU ") failed <%" GRN_FMT_LLU ">", - start, (unsigned long long int)length, (unsigned long long int)mmap_size); + SERR("munmap(%p,%" GRN_FMT_LLU ") failed <%" GRN_FMT_LLU ">", + start, + (unsigned long long int)length, + (unsigned long long int)mmap_size); } else { mmap_size -= length; } @@ -1928,7 +2171,8 @@ grn_pread(grn_ctx *ctx, fileinfo *fi, void *buf, size_t count, off_t offset) SERR("pread"); } else { /* todo : should retry ? */ - ERR(GRN_INPUT_OUTPUT_ERROR, "pread returned %" GRN_FMT_LLD " != %" GRN_FMT_LLU, + ERR(GRN_INPUT_OUTPUT_ERROR, + "pread returned %" GRN_FMT_LLD " != %" GRN_FMT_LLU, (long long int)r, (unsigned long long int)count); } return ctx->rc; @@ -1945,7 +2189,8 @@ grn_pwrite(grn_ctx *ctx, fileinfo *fi, void *buf, size_t count, off_t offset) SERR("pwrite"); } else { /* todo : should retry ? */ - ERR(GRN_INPUT_OUTPUT_ERROR, "pwrite returned %" GRN_FMT_LLD " != %" GRN_FMT_LLU, + ERR(GRN_INPUT_OUTPUT_ERROR, + "pwrite returned %" GRN_FMT_LLD " != %" GRN_FMT_LLU, (long long int)r, (unsigned long long int)count); } return ctx->rc; |