Navigation Menu

Skip to content

Commit

Permalink
cache persistent: support opening from multi processes
Browse files Browse the repository at this point in the history
TODO:

  * Support Windows
  • Loading branch information
kou committed Apr 12, 2017
1 parent c5a9975 commit 9e7db43
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 6 deletions.
33 changes: 27 additions & 6 deletions lib/cache.c
Expand Up @@ -23,6 +23,7 @@
#include "grn_pat.h"
#include "grn_store.h"
#include "grn_db.h"
#include "grn_file_lock.h"

#include <sys/stat.h>

Expand Down Expand Up @@ -140,11 +141,22 @@ grn_cache_open_persistent(grn_ctx *ctx,
grn_cache *cache,
const char *base_path)
{
grn_file_lock file_lock;
char *keys_path = NULL;
char *values_path = NULL;
char lock_path_buffer[PATH_MAX];
char keys_path_buffer[PATH_MAX];
char values_path_buffer[PATH_MAX];

cache->impl.persistent.timeout = 1000;

if (base_path) {
grn_snprintf(lock_path_buffer, PATH_MAX, PATH_MAX, "%s.lock", base_path);
grn_file_lock_init(ctx, &file_lock, lock_path_buffer);
} else {
grn_file_lock_init(ctx, &file_lock, NULL);
}

if (base_path) {
struct stat stat_buffer;

Expand All @@ -153,6 +165,13 @@ grn_cache_open_persistent(grn_ctx *ctx,
keys_path = keys_path_buffer;
values_path = values_path_buffer;

if (!grn_file_lock_acquire(ctx,
&file_lock,
cache->impl.persistent.timeout,
"[cache][persistent][open]")) {
goto exit;
}

if (stat(keys_path, &stat_buffer) == 0) {
cache->impl.persistent.keys = grn_hash_open(ctx, keys_path);
if (cache->impl.persistent.keys) {
Expand All @@ -169,15 +188,15 @@ grn_cache_open_persistent(grn_ctx *ctx,
ERRNO_ERR("[cache][persistent] "
"failed to remove path for cache keys: <%s>",
keys_path);
return;
goto exit;
}
}
if (stat(values_path, &stat_buffer) == 0) {
if (grn_ja_remove(ctx, values_path) != GRN_SUCCESS) {
ERRNO_ERR("[cache][persistent] "
"failed to remove path for cache values: <%s>",
values_path);
return;
goto exit;
}
}
}
Expand All @@ -194,7 +213,7 @@ grn_cache_open_persistent(grn_ctx *ctx,
ERR(ctx->rc == GRN_SUCCESS ? GRN_FILE_CORRUPT : ctx->rc,
"[cache][persistent] failed to create cache keys storage: <%s>",
keys_path ? keys_path : "(memory)");
return;
goto exit;
}
cache->impl.persistent.values =
grn_ja_create(ctx,
Expand All @@ -206,7 +225,7 @@ grn_cache_open_persistent(grn_ctx *ctx,
ERR(ctx->rc == GRN_SUCCESS ? GRN_FILE_CORRUPT : ctx->rc,
"[cache][persistent] failed to create cache values storage: <%s>",
values_path ? values_path : "(memory)");
return;
goto exit;
}
}

Expand Down Expand Up @@ -267,7 +286,7 @@ grn_cache_open_persistent(grn_ctx *ctx,
ERR(ctx->rc == GRN_SUCCESS ? GRN_FILE_CORRUPT : ctx->rc,
"[cache][persistent] broken cache keys storage: broken metadata: <%s>",
keys_path ? keys_path : "(memory)");
return;
goto exit;
}

if (added) {
Expand All @@ -277,7 +296,9 @@ grn_cache_open_persistent(grn_ctx *ctx,
}
}

cache->impl.persistent.timeout = 1000;
exit :
grn_file_lock_release(ctx, &file_lock);
grn_file_lock_fin(ctx, &file_lock);
}

static grn_cache *
Expand Down
83 changes: 83 additions & 0 deletions lib/file_lock.c
@@ -0,0 +1,83 @@
/* -*- c-basic-offset: 2 -*- */
/*
Copyright(C) 2017 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License version 2.1 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "grn_file_lock.h"
#include "grn_ctx.h"

#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>

void
grn_file_lock_init(grn_ctx *ctx,
grn_file_lock *file_lock,
const char *path)
{
file_lock->path = path;
file_lock->fd = -1;
}

grn_bool
grn_file_lock_acquire(grn_ctx *ctx,
grn_file_lock *file_lock,
int timeout,
const char *error_message_tag)
{
int i;
int n_lock_tries = timeout;

if (!file_lock->path) {
return GRN_TRUE;
}

for (i = 0; i < n_lock_tries; i++) {
file_lock->fd = open(file_lock->path, O_CREAT | O_EXCL);

This comment has been minimized.

Copy link
@s-yata

s-yata Apr 12, 2017

Contributor

open() with O_CREAT requires the 3rd argument that specifies the file mode.

This comment has been minimized.

Copy link
@kou

kou Apr 12, 2017

Author Member

Oh... I've added it.

This comment has been minimized.

Copy link
@s-yata

s-yata Apr 12, 2017

Contributor

Thank you!

if (file_lock->fd != -1) {
break;
}
grn_nanosleep(GRN_LOCK_WAIT_TIME_NANOSECOND);
}

if (file_lock->fd == -1) {
ERR(GRN_NO_LOCKS_AVAILABLE,
"%s failed to acquire lock: <%s>",
error_message_tag, file_lock->path);
return GRN_FALSE;
} else {
return GRN_TRUE;
}
}

void
grn_file_lock_release(grn_ctx *ctx, grn_file_lock *file_lock)
{
if (file_lock->fd == -1) {
return;
}

close(file_lock->fd);
unlink(file_lock->path);
}

void
grn_file_lock_fin(grn_ctx *ctx, grn_file_lock *file_lock)
{
if (file_lock->fd != -1) {
grn_file_lock_release(ctx, file_lock);
}
}
44 changes: 44 additions & 0 deletions lib/grn_file_lock.h
@@ -0,0 +1,44 @@
/* -*- c-basic-offset: 2 -*- */
/*
Copyright(C) 2017 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License version 2.1 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#pragma once

#include "grn.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef struct {
const char *path;
int fd;
} grn_file_lock;

void grn_file_lock_init(grn_ctx *ctx,
grn_file_lock *file_lock,
const char *path);
grn_bool grn_file_lock_acquire(grn_ctx *ctx,
grn_file_lock *file_lock,
int timeout,
const char *error_message_tag);
void grn_file_lock_release(grn_ctx *ctx, grn_file_lock *file_lock);
void grn_file_lock_fin(grn_ctx *ctx, grn_file_lock *file_lock);

#ifdef __cplusplus
}
#endif
2 changes: 2 additions & 0 deletions lib/sources.am
Expand Up @@ -30,6 +30,8 @@ libgroonga_la_SOURCES = \
grn_expr_code.h \
expr_executor.c \
grn_expr_executor.h \
file_lock.c \
grn_file_lock.h \
geo.c \
grn_geo.h \
grn.h \
Expand Down

0 comments on commit 9e7db43

Please sign in to comment.