fs_index.c

/* [<][>]
[^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following functions.
  1. my_open_index
  2. my_read_index
  3. my_get_index
  4. my_index_info2hash
  5. be_index_close
  6. my_init_index
  7. free_index
  8. be_index_s_new
  9. be_index_s_open
  10. be_index_each
  11. be_index_s_foreach
  12. be_index_s_entries
  13. be_index_initialize
  14. be_index_read
  15. be_index_rewind
  16. be_index_reverse
  17. be_index_s_create
  18. be_index_s_remove
  19. be_index_s_stat
  20. Init_fs_index

/*
 *  fs_index.c
 */

#include <fs_index.h>
#include <StorageDefs.h>
#include "bfs.h"


static VALUE cIndex;


static DIR*
my_open_index(VALUE vol)
/* [<][>][^][v][top][bottom][index][help] */
{
  dev_t dev;
  DIR *dirp;

  rb_secure(2);
  dev = my_get_dev_for_obj(vol);
  dirp = fs_open_index_dir(dev);
  if (!dirp) {
    if (errno == EMFILE || errno == ENFILE) {
      rb_gc();
      dirp = fs_open_index_dir(dev);
    }
    if (!dirp) {
      rb_sys_fail(ROBJ_AS_CSTR(vol));
    }
  }
  return dirp;
}


static VALUE
my_read_index(DIR *dirp)
/* [<][>][^][v][top][bottom][index][help] */
{
  dirent_t *dp;

  errno = 0;
  dp = fs_read_index_dir(dirp);
  if (!dp && errno) {
    rb_sys_fail(0);
  }
  if (dp) {
    return rb_tainted_str_new2(dp->d_name);
  }
  return Qnil;
}


static DIR*
my_get_index(VALUE indx)
/* [<][>][^][v][top][bottom][index][help] */
{
  DIR *dirp;

  Data_Get_Struct(indx, DIR, dirp);
  my_check_dirp_closed(dirp, "closed index");
  return dirp;
}


static VALUE
my_index_info2hash(index_info *info)
/* [<][>][^][v][top][bottom][index][help] */
{
  VALUE h = rb_hash_new();
  rb_hash_aset(h, rb_str_new2("type"), UINT2NUM(info->type));
  rb_hash_aset(h, rb_str_new2("size"), LLONG2NUM(info->size));
  rb_hash_aset(h, rb_str_new2("modification_time"), rb_time_new(info->modification_time, 0));
  rb_hash_aset(h, rb_str_new2("creation_time"),     rb_time_new(info->creation_time, 0));
  rb_hash_aset(h, rb_str_new2("uid"), UINT2NUM(info->uid));
  rb_hash_aset(h, rb_str_new2("gid"), UINT2NUM(info->gid));
  return h;
}


static VALUE
be_index_close(VALUE indx)
/* [<][>][^][v][top][bottom][index][help] */
{
  DIR *dirp = my_get_index(indx);
  if (fs_close_index_dir(dirp) < 0) {
    rb_sys_fail(ROBJ_AS_CSTR(indx));
  }
  DATA_PTR(indx) = NULL;
  return Qnil;
}


static VALUE
my_init_index(VALUE indx, VALUE vol)
/* [<][>][^][v][top][bottom][index][help] */
{
  if (DATA_PTR(indx)) {
    be_index_close(indx);
  }
  DATA_PTR(indx) = my_open_index(vol);
  return indx;
}


static void
free_index(DIR *dirp)
/* [<][>][^][v][top][bottom][index][help] */
{
  if (dirp && (fs_close_index_dir(dirp) < 0)) {
    rb_warn("%s", strerror(errno));
  }
}


static VALUE
be_index_s_new(int argc, VALUE *argv, VALUE klass)
/* [<][>][^][v][top][bottom][index][help] */
{
  VALUE obj = Data_Wrap_Struct(klass, 0, free_index, 0);
  rb_obj_call_init(obj, argc, argv);
  return obj;
}


static VALUE
be_index_s_open(VALUE klass, VALUE vol)
/* [<][>][^][v][top][bottom][index][help] */
{
  VALUE indx;

  indx = Data_Wrap_Struct(klass, 0, free_index, 0);
  my_init_index(indx, vol);

  if (rb_block_given_p()) {
    return rb_ensure(rb_yield, indx, be_index_close, indx);
  }
  return indx;
}


static VALUE
be_index_each(VALUE indx)
/* [<][>][^][v][top][bottom][index][help] */
{
  DIR *dirp;
  VALUE d_name;

  my_check_block_given();
  dirp = my_get_index(indx);

  d_name = my_read_index(dirp);
  while (!NIL_P(d_name)) {
    rb_yield(d_name);
    my_check_dirp_closed(DATA_PTR(indx), "closed index");
    d_name = my_read_index(dirp);
  }
  return indx;
}


static VALUE
be_index_s_foreach(VALUE klass, VALUE vol)
/* [<][>][^][v][top][bottom][index][help] */
{
  VALUE indx = rb_funcall(cIndex, i_open, 1, vol);
  rb_ensure(be_index_each, indx, be_index_close, indx);
  return Qnil;
}


static VALUE
be_index_s_entries(VALUE klass, VALUE vol)
/* [<][>][^][v][top][bottom][index][help] */
{
  VALUE indx = rb_funcall(cIndex, i_open, 1, vol);
  return rb_ensure(rb_Array, indx, be_index_close, indx);
}


static VALUE
be_index_initialize(VALUE indx, VALUE vol)
/* [<][>][^][v][top][bottom][index][help] */
{
  if (rb_block_given_p()) {
    char *cname = rb_class2name(CLASS_OF(indx));
    rb_warn("%s::new() does not take block; use %s::open() instead", cname, cname);
  }
  my_init_index(indx, vol);
  return indx;
}


static VALUE
be_index_read(VALUE indx)
/* [<][>][^][v][top][bottom][index][help] */
{
  DIR *dirp = my_get_index(indx);
  return my_read_index(dirp);
}


static VALUE
be_index_rewind(VALUE indx)
/* [<][>][^][v][top][bottom][index][help] */
{
  DIR *dirp = my_get_index(indx);
  fs_rewind_index_dir(dirp);
  return indx;
}


static VALUE
be_index_reverse(VALUE indx)
/* [<][>][^][v][top][bottom][index][help] */
{
  return rb_ary_reverse(rb_Array(indx));
}


static VALUE
be_index_s_create(int argc, VALUE *argv, VALUE klass)
/* [<][>][^][v][top][bottom][index][help] */
{
  VALUE vol, name, type, flags;
  dev_t dev;
  int result, typ;
  uint flgs;

  typ = B_STRING_TYPE;
  flgs = 0;

  rb_scan_args(argc, argv, "22", &vol, &name, &type, &flags);

  rb_secure(2);
  Check_SafeStr(name);
  if (RSTRING(name)->len >= B_ATTR_NAME_LENGTH) { /* <-- ? not found `B_INDEX_NAME_LENGTH' */
    my_sys_fail(B_BAD_VALUE, RSTRING(name)->ptr);
  }
  dev = my_get_dev_for_obj(vol);
  if (argc >= 3) {
    typ = NUM2LONG(type);
  }
  if (argc == 4) {
    flgs = NUM2ULONG(flags);
  }

  result = fs_create_index(dev, RSTRING(name)->ptr, typ, flgs);
  if (result < 0) {
    rb_sys_fail(RSTRING(name)->ptr);
  }
  return Qnil;
}


static VALUE
be_index_s_remove(VALUE klass, VALUE vol, VALUE name)
/* [<][>][^][v][top][bottom][index][help] */
{
  dev_t dev;
  int result;

  rb_secure(2);
  Check_SafeStr(name);
  dev = my_get_dev_for_obj(vol);

  result = fs_remove_index(dev, RSTRING(name)->ptr);
  if (result < 0) {
    rb_sys_fail(RSTRING(name)->ptr);
  }
  return Qnil;
}


static VALUE
be_index_s_stat(VALUE klass, VALUE vol, VALUE name)
/* [<][>][^][v][top][bottom][index][help] */
{
  dev_t dev;
  index_info info;
  int result;

  rb_secure(2);
  Check_SafeStr(name);
  dev = my_get_dev_for_obj(vol);

  result = fs_stat_index(dev, RSTRING(name)->ptr, &info);
  if (result < 0) {
    rb_sys_fail(RSTRING(name)->ptr);
  }
  return my_index_info2hash(&info);
}


void
Init_fs_index()
/* [<][>][^][v][top][bottom][index][help] */
{
  cIndex = rb_define_class_under(mBfs, "Index", rb_cObject);

  rb_include_module(cIndex, rb_mEnumerable);

  rb_define_singleton_method(cIndex, "new", be_index_s_new, -1);
  rb_define_singleton_method(cIndex, "open", be_index_s_open, 1);
  rb_define_singleton_method(cIndex, "foreach", be_index_s_foreach, 1);
  rb_define_singleton_method(cIndex, "entries", be_index_s_entries, 1);

  rb_define_method(cIndex, "initialize", be_index_initialize, 1);
  rb_define_method(cIndex, "read", be_index_read, 0);
  rb_define_method(cIndex, "each", be_index_each, 0);
  rb_define_method(cIndex, "rewind", be_index_rewind, 0);
  rb_define_method(cIndex, "close", be_index_close, 0);
  rb_define_method(cIndex, "reverse", be_index_reverse, 0);

  rb_define_singleton_method(cIndex, "create", be_index_s_create, -1);
  rb_define_singleton_method(cIndex, "mkindex", be_index_s_create, -1);
  rb_define_singleton_method(cIndex, "remove", be_index_s_remove, 2);
  rb_define_singleton_method(cIndex, "rmindex", be_index_s_remove, 2);
  rb_define_singleton_method(cIndex, "delete", be_index_s_remove, 2);
  rb_define_singleton_method(cIndex, "stat", be_index_s_stat, 2);
}

/* [<][>][^][v][top][bottom][index][help] */