<commit_before>/*
  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
  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_cache.h"
#include "grn_ctx.h"
#include "grn_ctx_impl.h"
#include "grn_hash.h"
#include "grn_pat.h"
#include "grn_store.h"
#include "grn_db.h"
#include "grn_file_lock.h"

#include <sys/stat.h>

typedef struct _grn_cache_entry_memory grn_cache_entry_memory;

struct _grn_cache_entry_memory {
  grn_cache_entry_memory *next;
  grn_cache_entry_memory *prev;
  grn_obj *value;
  grn_timeval tv;
  grn_id id;
};

typedef struct _grn_cache_entry_persistent_data {
  grn_id next;
  grn_id prev;
  grn_timeval modified_time;
} grn_cache_entry_persistent_data;

/*
  sizeof(grn_cache_entry_persistent_metadata) should be equal or smaller
  than sizeof(grn_cache_entry_persistent_data).
 */
typedef struct _grn_cache_entry_persistent_metadata {
  uint32_t max_nentries;
  uint32_t nfetches;
  uint32_t nhits;
} grn_cache_entry_persistent_metadata;

typedef union _grn_cache_entry_persistent {
  grn_cache_entry_persistent_data data;
  grn_cache_entry_persistent_metadata metadata;
} grn_cache_entry_persistent;

struct _grn_cache {
  union {
    struct {
      grn_cache_entry_memory *next;
      grn_cache_entry_memory *prev;
      grn_hash *hash;
      grn_mutex mutex;
      uint32_t max_nentries;
      uint32_t nfetches;
      uint32_t nhits;
    } memory;
    struct {
      grn_hash *keys;
      grn_ja *values;
      int timeout;
    } persistent;
  } impl;
  grn_bool is_memory;
  grn_ctx *ctx;
};

#define GRN_CACHE_PERSISTENT_ROOT_ID 1
#define GRN_CACHE_PERSISTENT_ROOT_KEY "\0"
#define GRN_CACHE_PERSISTENT_ROOT_KEY_LEN \
  (sizeof(GRN_CACHE_PERSISTENT_ROOT_KEY) - 1)
#define GRN_CACHE_PERSISTENT_METADATA_ID 2
#define GRN_CACHE_PERSISTENT_METADATA_KEY "\1"
#define GRN_CACHE_PERSISTENT_METADATA_KEY_LEN \
  (sizeof(GRN_CACHE_PERSISTENT_METADATA_KEY) - 1)

static grn_ctx grn_cache_ctx;
static grn_cache *grn_cache_current = NULL;
static grn_cache *grn_cache_default = NULL;
static char grn_cache_default_base_path[PATH_MAX];

void
grn_set_default_cache_base_path(const char *base_path)
{
  if (base_path) {
    grn_strcpy(grn_cache_default_base_path,
               PATH_MAX,
               base_path);
  } else {
    grn_cache_default_base_path[0] = '\0';
  }
}

const char *
grn_get_default_cache_base_path(void)
{
  if (grn_cache_default_base_path[0] == '\0') {
    return NULL;
  } else {
    return grn_cache_default_base_path;
  }
}

static void
grn_cache_open_memory(grn_ctx *ctx, grn_cache *cache)
{
  cache->impl.memory.next = (grn_cache_entry_memory *)cache;
  cache->impl.memory.prev = (grn_cache_entry_memory *)cache;
  cache->impl.memory.hash = grn_hash_create(cache->ctx,
                                            NULL,
                                            GRN_CACHE_MAX_KEY_SIZE,
                                            sizeof(grn_cache_entry_memory),
                                            GRN_OBJ_KEY_VAR_SIZE);
  if (!cache->impl.memory.hash) {
    ERR(GRN_NO_MEMORY_AVAILABLE, "[cache] failed to create hash table");
    return;
  }
  MUTEX_INIT(cache->impl.memory.mutex);

  cache->impl.memory.max_nentries = GRN_CACHE_DEFAULT_MAX_N_ENTRIES;
  cache->impl.memory.nfetches = 0;
  cache->impl.memory.nhits = 0;
}

static void
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) {<commit_msg>cache: use more readable code<commit_after>/*
  Copyright(C) 2009-2017  Brazil
  Copyright(C) 2021  <NAME> <<EMAIL>>

  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_cache.h"
#include "grn_ctx.h"
#include "grn_ctx_impl.h"
#include "grn_hash.h"
#include "grn_pat.h"
#include "grn_store.h"
#include "grn_db.h"
#include "grn_file_lock.h"

#include <sys/stat.h>

typedef struct _grn_cache_entry_memory grn_cache_entry_memory;

struct _grn_cache_entry_memory {
  grn_cache_entry_memory *next;
  grn_cache_entry_memory *prev;
  grn_obj *value;
  grn_timeval tv;
  grn_id id;
};

typedef struct _grn_cache_entry_persistent_data {
  grn_id next;
  grn_id prev;
  grn_timeval modified_time;
} grn_cache_entry_persistent_data;

/*
  sizeof(grn_cache_entry_persistent_metadata) should be equal or smaller
  than sizeof(grn_cache_entry_persistent_data).
 */
typedef struct _grn_cache_entry_persistent_metadata {
  uint32_t max_nentries;
  uint32_t nfetches;
  uint32_t nhits;
} grn_cache_entry_persistent_metadata;

typedef union _grn_cache_entry_persistent {
  grn_cache_entry_persistent_data data;
  grn_cache_entry_persistent_metadata metadata;
} grn_cache_entry_persistent;

struct _grn_cache {
  union {
    struct {
      /* next and prev is the same layout as grn_cache_entry_memory to
       * use this struct as the root entry. */
      grn_cache_entry_memory *next;
      grn_cache_entry_memory *prev;
      grn_hash *hash;
      grn_mutex mutex;
      uint32_t max_nentries;
      uint32_t nfetches;
      uint32_t nhits;
    } memory;
    struct {
      grn_hash *keys;
      grn_ja *values;
      int timeout;
    } persistent;
  } impl;
  grn_bool is_memory;
  grn_ctx *ctx;
};

#define GRN_CACHE_PERSISTENT_ROOT_ID 1
#define GRN_CACHE_PERSISTENT_ROOT_KEY "\0"
#define GRN_CACHE_PERSISTENT_ROOT_KEY_LEN \
  (sizeof(GRN_CACHE_PERSISTENT_ROOT_KEY) - 1)
#define GRN_CACHE_PERSISTENT_METADATA_ID 2
#define GRN_CACHE_PERSISTENT_METADATA_KEY "\1"
#define GRN_CACHE_PERSISTENT_METADATA_KEY_LEN \
  (sizeof(GRN_CACHE_PERSISTENT_METADATA_KEY) - 1)

static grn_ctx grn_cache_ctx;
static grn_cache *grn_cache_current = NULL;
static grn_cache *grn_cache_default = NULL;
static char grn_cache_default_base_path[PATH_MAX];

void
grn_set_default_cache_base_path(const char *base_path)
{
  if (base_path) {
    grn_strcpy(grn_cache_default_base_path,
               PATH_MAX,
               base_path);
  } else {
    grn_cache_default_base_path[0] = '\0';
  }
}

const char *
grn_get_default_cache_base_path(void)
{
  if (grn_cache_default_base_path[0] == '\0') {
    return NULL;
  } else {
    return grn_cache_default_base_path;
  }
}

static void
grn_cache_open_memory(grn_ctx *ctx, grn_cache *cache)
{
  cache->impl.memory.next = (grn_cache_entry_memory *)&(cache->impl.memory);
  cache->impl.memory.prev = (grn_cache_entry_memory *)&(cache->impl.memory);
  cache->impl.memory.hash = grn_hash_create(cache->ctx,
                                            NULL,
                                            GRN_CACHE_MAX_KEY_SIZE,
                                            sizeof(grn_cache_entry_memory),
                                            GRN_OBJ_KEY_VAR_SIZE);
  if (!cache->impl.memory.hash) {
    ERR(GRN_NO_MEMORY_AVAILABLE, "[cache] failed to create hash table");
    return;
  }
  MUTEX_INIT(cache->impl.memory.mutex);

  cache->impl.memory.max_nentries = GRN_CACHE_DEFAULT_MAX_N_ENTRIES;
  cache->impl.memory.nfetches = 0;
  cache->impl.memory.nhits = 0;
}

static void
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) {
{'fraction_non_alphanumeric': 0.0772732445658359, 'fraction_numerical': 0.011608057357459884, 'mean_word_length': 3.5699427977119083, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 30, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6361672', 'n_tokens_mistral': 3219, 'n_tokens_neox': 3109, 'n_words': 685}