/*
 *  call-seq:
 *     lmc.clear -> Qnil
 *
 *  Clears content of hashtable.
 */
static mrb_value Cache__clear(mrb_state *mrb, mrb_value self)
{
  local_memcache_t *lmc = get_Cache(mrb, self);
  if (!local_memcache_clear(lmc))
    rb_lmc_raise_exception(mrb, &lmc->error);
  return mrb_nil_value();
}
/*
 *  call-seq:
 *     lmc.delete(key)   ->   Qnil
 *
 *  Deletes key from hashtable.  The key is converted to string.
 */
static mrb_value Cache__delete(mrb_state *mrb, mrb_value self)
{
  char *key;
  mrb_int n_key;

  mrb_get_args(mrb, "s", &key, &n_key);
  return bool_local_memcache_delete(get_Cache(mrb, self), key, n_key);
}
/*
 *  call-seq:
 *     lmc.get_by_no_lock(key)   ->   string value or nil
 *
 *  Retrieve string value from hashtable without obtain a semaphore.
 */
static mrb_value Cache__get_by_no_lock(mrb_state *mrb, mrb_value self)
{
  local_memcache_t *lmc = get_Cache(mrb, self);
  size_t l;
  char *key;
  mrb_int n_key;

  mrb_get_args(mrb, "s", &key, &n_key);
  const char *r = __local_memcache_get_by_no_lock(lmc, key, n_key, &l);
  mrb_value rr = lmc_ruby_string2(mrb, r, l);
  return rr;
}
/*
 *  call-seq:
 *     lmc.get(key)   ->   string value or nil
 *     lmc[key]       ->   string value or nil
 *
 *  Retrieve string value from hashtable.
 */
static mrb_value Cache__get(mrb_state *mrb, mrb_value self)
{
  local_memcache_t *lmc = get_Cache(mrb, self);
  size_t l;
  mrb_cache_iovec_t k;
  char *key;
  mrb_int n_key;

  mrb_get_args(mrb, "s", &key, &n_key);
  const char *r = __local_memcache_get(lmc, key, n_key, &l);
  mrb_value rr = lmc_ruby_string2(mrb, r, l);
  lmc_unlock_shm_region("local_memcache_get", lmc);
  return rr;
}
static mrb_value Cache__shm_status(mrb_state *mrb, mrb_value self)
{
  mrb_value hash = mrb_hash_new(mrb);

  local_memcache_t *lmc = get_Cache(mrb, self);
  if (!lmc_lock_shm_region("shm_status", lmc))
    return mrb_nil_value();
  lmc_mem_status_t ms = lmc_status(lmc->base, "shm_status");
  if (!lmc_unlock_shm_region("shm_status", lmc))
    return mrb_nil_value();

  mrb_hash_set(mrb, hash, mrb_symbol_value(mrb_intern_cstr(mrb, "free_bytes")), mrb_fixnum_value(ms.total_free_mem));
  mrb_hash_set(mrb, hash, mrb_symbol_value(mrb_intern_cstr(mrb, "total_bytes")), mrb_fixnum_value(ms.total_shm_size));
  mrb_hash_set(mrb, hash, mrb_symbol_value(mrb_intern_cstr(mrb, "used_bytes")),
               mrb_fixnum_value(ms.total_shm_size - ms.total_free_mem));
  mrb_hash_set(mrb, hash, mrb_symbol_value(mrb_intern_cstr(mrb, "free_chunks")), mrb_fixnum_value(ms.free_chunks));
  mrb_hash_set(mrb, hash, mrb_symbol_value(mrb_intern_cstr(mrb, "largest_chunk")), mrb_fixnum_value(ms.largest_chunk));
  return hash;
}
/*
 *  call-seq:
 *     lmc.set(key, value)   ->   Qnil
 *     lmc[key]=value        ->   Qnil
 *
 *  Set value for key in hashtable.  Value and key will be converted to
 *  string.
 */
static mrb_value Cache__set(mrb_state *mrb, mrb_value self)
{
  local_memcache_t *lmc = get_Cache(mrb, self);
  mrb_value key, value;
  mrb_cache_iovec_t k, v;

  mrb_get_args(mrb, "oo", &key, &value);
  if (mrb_type(key) != MRB_TT_STRING || mrb_type(value) != MRB_TT_STRING) {
    mrb_raise(mrb, E_TYPE_ERROR, "both key and value must be STRING");
  }

  mrb_cache_str_to_iovec(mrb, key, &k);
  mrb_cache_str_to_iovec(mrb, value, &v);

  if (!local_memcache_set(lmc, k.base, k.len, v.base, v.len)) {
    rb_lmc_raise_exception(mrb, &lmc->error);
  }
  return mrb_nil_value();
}
/*
 *  call-seq:
 *     lmc.size -> number
 *
 *  Number of pairs in the hashtable.
 */
static mrb_value Cache__size(mrb_state *mrb, mrb_value self)
{
  local_memcache_t *lmc = get_Cache(mrb, self);
  ht_hash_t *ht = lmc->base + lmc->va_hash;
  return mrb_fixnum_value(ht->size);
}