summaryrefslogtreecommitdiff
path: root/storage/mroonga/vendor/groonga/lib/io.c
diff options
context:
space:
mode:
Diffstat (limited to 'storage/mroonga/vendor/groonga/lib/io.c')
-rw-r--r--storage/mroonga/vendor/groonga/lib/io.c865
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;