예제 #1
0
/* Create a word database object. */
TCWDB *tcwdbnew(void){
  TCWDB *wdb = tcmalloc(sizeof(*wdb));
  wdb->mmtx = tcmalloc(sizeof(pthread_rwlock_t));
  if(pthread_rwlock_init(wdb->mmtx, NULL) != 0) tcmyfatal("pthread_rwlock_init failed");
  wdb->idx = tcbdbnew();
  if(!tcbdbsetmutex(wdb->idx)) tcmyfatal("tcbdbsetmutex failed");
  wdb->open = false;
  wdb->cc = NULL;
  wdb->icsiz = WDBCCDEFICSIZ;
  wdb->lcnum = 0;
  wdb->dtokens = NULL;
  wdb->dids = NULL;
  wdb->etnum = WDBDEFETNUM;
  wdb->opts = 0;
  wdb->fwmmax = WDBDEFFWMMAX;
  wdb->synccb = NULL;
  wdb->syncopq = NULL;
  wdb->addcb = NULL;
  wdb->addopq = NULL;
  return wdb;
}
예제 #2
0
int main(int argc, char *argv[], char *envp[]) {

	int c;
	char *synchttp_settings_listen = "0.0.0.0";
	int synchttp_settings_port = 2688;
	char *synchttp_settings_datapath = NULL;
	bool synchttp_settings_daemon = false;
	int synchttp_settings_timeout = 60; /* 单位:秒 */
	synchttp_settings_syncinterval = 5; /* 单位:秒 */
	int synchttp_settings_cachenonleaf = 1024; /* 缓存非叶子节点数。单位:条 */
	int synchttp_settings_cacheleaf = 2048; /* 缓存叶子节点数。叶子节点缓存数为非叶子节点数的两倍。单位:条 */
	int synchttp_settings_mappedmemory = 104857600; /* 单位:字节 */
	synchttp_settings_pidfile = "/tmp/synchttp.pid";
	synchttp_settings_auth = NULL; /* 验证密码 */

	/* 启动选项 */
	while ((c = getopt(argc, argv, "l:p:x:t:s:c:m:i:a:w:dh")) != -1) {
		switch (c) {
		case 'l':
			synchttp_settings_listen = strdup(optarg);
			break;
		case 'p':
			synchttp_settings_port = atoi(optarg);
			break;
		case 'x':
			synchttp_settings_datapath = strdup(optarg); /* synchttp数据库文件存放路径 */
			if (access(synchttp_settings_datapath, W_OK) != 0) { /* 如果目录不可写 */
				if (access(synchttp_settings_datapath, R_OK) == 0) { /* 如果目录可读 */
					chmod(synchttp_settings_datapath, S_IWOTH); /* 设置其他用户具可写入权限 */
				} else { /* 如果不存在该目录,则创建 */
					create_multilayer_dir(synchttp_settings_datapath);
				}
				if (access(synchttp_settings_datapath, W_OK) != 0) { /* 如果目录不可写 */
					fprintf(stderr, "synchttp database directory not writable\n");
				}
			}
			break;
		case 't':
			synchttp_settings_timeout = atoi(optarg);
			break;
		case 's':
			synchttp_settings_syncinterval = atoi(optarg);
			break;
		case 'c':
			synchttp_settings_cachenonleaf = atoi(optarg);
			synchttp_settings_cacheleaf = synchttp_settings_cachenonleaf * 2;
			break;
		case 'm':
			synchttp_settings_mappedmemory = atoi(optarg) * 1024 * 1024; /* 单位:M */
			break;
		case 'i':
			synchttp_settings_pidfile = strdup(optarg);
			break;
		case 'a':
			synchttp_settings_auth = strdup(optarg);
			break;
		case 'd':
			synchttp_settings_daemon = true;
			break;
		case 'h':
		default:
			show_help();
			return 1;
		}
	}

	/* 判断是否加了必填参数 -x */
	if (synchttp_settings_datapath == NULL) {
		show_help();
		fprintf(stderr, "Attention: Please use the indispensable argument: -x <path>\n\n");
		exit(1);
	}

	/*curl初始化全局信息*/
	if ((curl_global_init(CURL_GLOBAL_ALL)) != CURLE_OK) {
		fprintf(stderr, "Curl global init fail.\n");
		exit(1);
	}

	/* 数据表路径 */
	int synchttp_settings_dataname_len = 1024;
	char *synchttp_settings_dataname = (char *) tccalloc(1, synchttp_settings_dataname_len);
	sprintf(synchttp_settings_dataname, "%s/synchttp.db", synchttp_settings_datapath);

	/* 打开数据表 */
	synchttp_db_tcbdb = tcbdbnew();
	tcbdbsetmutex(synchttp_db_tcbdb); /* 开启线程互斥锁 */
	tcbdbtune(synchttp_db_tcbdb, 1024, 2048, 50000000, 8, 10, BDBTLARGE);
	tcbdbsetcache(synchttp_db_tcbdb, synchttp_settings_cacheleaf,
			synchttp_settings_cachenonleaf);
	tcbdbsetxmsiz(synchttp_db_tcbdb, synchttp_settings_mappedmemory); /* 内存缓存大小 */

	/* 判断表是否能打开 */
	if (!tcbdbopen(synchttp_db_tcbdb, synchttp_settings_dataname, BDBOWRITER | BDBOCREAT)) {
		fprintf(stderr, "Attention: Unable to open the database.\n\n");
		exit(1);
	}
	/* 释放变量所占内存 */
	free(synchttp_settings_dataname);

	/* 如果加了-d参数,以守护进程运行 */
	if (synchttp_settings_daemon == true) {
		pid_t pid;

		/* Fork off the parent process */
		pid = fork();
		if (pid < 0) {
			exit(EXIT_FAILURE);
		}
		/* If we got a good PID, then
		 we can exit the parent process. */
		if (pid > 0) {
			exit(EXIT_SUCCESS);
		}
	}

	/* 将进程号写入PID文件 */
	FILE *fp_pidfile;
	fp_pidfile = fopen(synchttp_settings_pidfile, "w");
	fprintf(fp_pidfile, "%d\n", getpid());
	fclose(fp_pidfile);

	/* 派生synchttp子进程(工作进程) */
	pid_t synchttp_worker_pid_wait;
	pid_t synchttp_worker_pid = fork();
	/* 如果派生进程失败,则退出程序 */
	if (synchttp_worker_pid < 0) {
		fprintf(stderr, "Error: %s:%d\n", __FILE__, __LINE__);
		exit(EXIT_FAILURE);
	}

	/* synchttp父进程内容 */
	if (synchttp_worker_pid > 0) {
		/* 处理父进程接收到的kill信号 */

		/* 忽略Broken Pipe信号 */
		signal(SIGPIPE, SIG_IGN);

		/* 处理kill信号 */
		signal(SIGINT, kill_signal_master);
		signal(SIGKILL, kill_signal_master);
		signal(SIGQUIT, kill_signal_master);
		signal(SIGTERM, kill_signal_master);
		signal(SIGHUP, kill_signal_master);

		/* 处理段错误信号 */
		signal(SIGSEGV, kill_signal_master);

		/* 如果子进程终止,则重新派生新的子进程 */
		while (1) {
			synchttp_worker_pid_wait = wait(NULL);
			if (synchttp_worker_pid_wait < 0) {
				continue;
			}
			usleep(100000);
			synchttp_worker_pid = fork();
			if (synchttp_worker_pid == 0) {
				break;
			}
		}
	}

	/*****************************************子进程处理************************************/
	/* 忽略Broken Pipe信号 */
	signal(SIGPIPE, SIG_IGN);

	/* 处理kill信号 */
	signal(SIGINT, kill_signal_worker);
	signal(SIGKILL, kill_signal_worker);
	signal(SIGQUIT, kill_signal_worker);
	signal(SIGTERM, kill_signal_worker);
	signal(SIGHUP, kill_signal_worker);

	/* 处理段错误信号 */
	signal(SIGSEGV, kill_signal_worker);

	/*创建消息队列监听进程*/
	pthread_t synchttp_dispatch_tid;
	pthread_create(&synchttp_dispatch_tid, NULL, (void *) synchttp_dispatch, NULL);

	/* 创建定时同步线程,定时将内存中的内容写入磁盘 */
	pthread_t synchttp_worker_tid;
	pthread_create(&synchttp_worker_tid, NULL, (void *) synchttp_worker, NULL);

	/* 外部请求处理部分 */
	struct evhttp *synchttpd;
	event_init();
	synchttpd = evhttp_start(synchttp_settings_listen, synchttp_settings_port);
	if (synchttpd == NULL) {
		fprintf(stderr, "Error: Unable to listen on %s:%d\n\n", synchttp_settings_listen, synchttp_settings_port);
		kill(0, SIGTERM);
		exit(1);
	}
	evhttp_set_timeout(synchttpd, synchttp_settings_timeout);
	evhttp_set_gencb(synchttpd, synchttp_handler, NULL);
	event_dispatch();
	evhttp_free(synchttpd);
}
예제 #3
0
파일: tc.c 프로젝트: chinnurtb/MotionDb
static int control(ErlDrvData handle, unsigned int command, char* buf, int count, char** res, int res_size) {
  tcbdb_drv_t *driver = (tcbdb_drv_t*)handle;
  TCBDB *bdb = driver->bdb;

  int index = 1, tp, sz, version;
  char key[MAX_KEY_SIZE], value[MAX_VALUE_SIZE];
  long key_size, value_size;
  long long long_tmp;
  bool rs;
  const char *value_tmp = NULL;

  ei_x_buff x;
  ei_x_new_with_version(&x);
  if (bdb == NULL && command != OPEN)
    return ei_error(&x, "database_not_opened", res, res_size);

  ei_decode_version(buf, &index, &version);

  switch (command) {
    case OPEN:
      // open(Filepath::string())
      if (bdb == NULL) {
        ei_get_type(buf, &index, &tp, &sz);
        if (tp != ERL_STRING_EXT)
          return ei_error(&x, "invalid_argument", res, res_size);

        TCBDB *bdb = tcbdbnew();
        tcbdbsetmutex(bdb);
        tcbdbsetcache(bdb, 104800, 51200);
        tcbdbsetxmsiz(bdb, 1048576);
        tcbdbtune(bdb, 0, 0, 0, 7, -1, BDBTLARGE);

        char *file = driver_alloc(sz + 1);
        ei_decode_string(buf, &index, file);
        rs = tcbdbopen(bdb, file, BDBOWRITER | BDBOCREAT);
        driver_free(file);
        if (!rs)
          return ei_error(&x, tcbdberrmsg(tcbdbecode(bdb)), res, res_size);
        driver->bdb = bdb;
        ei_x_encode_atom(&x, "ok");
      } else
        return ei_error(&x, "database already opened", res, res_size);
      break;

    case CLOSE:
      tcbdbclose(bdb);
      tcbdbdel(bdb);
      driver->bdb = NULL;
      ei_x_encode_atom(&x, "ok");
      break;

    case PUT:
    case PUTDUP:
    case PUTCAT:
    case PUTKEEP:
      // put({Key::binary(), Value::binary()})
      ei_get_type(buf, &index, &tp, &sz);
      if (tp != ERL_SMALL_TUPLE_EXT || sz != 2)
        return ei_error(&x, "invalid_argument", res, res_size);
      ei_decode_tuple_header(buf, &index, &sz);

      ei_get_type(buf, &index, &tp, &sz);
      if (tp != ERL_BINARY_EXT || sz > MAX_KEY_SIZE)
        return ei_error(&x, "invalid_argument", res, res_size);
      ei_decode_binary(buf, &index, &key[0], &key_size);
      ei_get_type(buf, &index, &tp, &sz);
      if (tp != ERL_BINARY_EXT)
        return ei_error(&x, "invalid_argument", res, res_size);
      if (sz <= MAX_VALUE_SIZE) {
        ei_decode_binary(buf, &index, &value[0], &value_size);
        switch (command) {
          case PUT: rs = tcbdbput(bdb, &key[0], key_size, &value[0], value_size); break;
          case PUTDUP: rs = tcbdbputdup(bdb, &key[0], key_size, &value[0], value_size); break;
          case PUTCAT: rs = tcbdbputcat(bdb, &key[0], key_size, &value[0], value_size); break;
          default: rs = tcbdbputkeep(bdb, &key[0], key_size, &value[0], value_size);
        }
      } else {
        void *p = driver_alloc(sz);
        if (p) {
          ei_decode_binary(buf, &index, p, &value_size);
          switch (command) {
            case PUT: rs = tcbdbput(bdb, &key[0], key_size, p, value_size); break;
            case PUTDUP: rs = tcbdbputdup(bdb, &key[0], key_size, p, value_size); break;
            case PUTCAT: rs = tcbdbputcat(bdb, &key[0], key_size, p, value_size); break;
            default: rs = tcbdbputkeep(bdb, &key[0], key_size, p, value_size);
          }
          driver_free(p);
        } else
          return ei_error(&x, "too long value", res, res_size);
      };
      if (!rs)
        return ei_error(&x, tcbdberrmsg(tcbdbecode(bdb)), res, res_size);
      ei_x_encode_atom(&x, "ok");
      break;

    case GET:
      // get(Key::binary()) -> {ok, Value} | {error, not_found}
      ei_get_type(buf, &index, &tp, &sz);
      if (tp != ERL_BINARY_EXT || sz > MAX_KEY_SIZE)
        return ei_error(&x, "invalid_argument", res, res_size);
      ei_decode_binary(buf, &index, &key[0], &key_size);

      value_tmp = tcbdbget3(bdb, &key[0], key_size, &sz);
      ei_x_encode_tuple_header(&x, 2);
      if (value_tmp != NULL) {
        ei_x_encode_atom(&x, "ok");
        ei_x_encode_binary(&x, value_tmp, sz);
      } else {
        ei_x_encode_atom(&x, "error");
        ei_x_encode_atom(&x, "not_found");
      }
      break;

    case GETDUP:
      // get(Key::binary()) -> {ok, Values}
      ei_get_type(buf, &index, &tp, &sz);
      if (tp != ERL_BINARY_EXT || sz > MAX_KEY_SIZE)
        return ei_error(&x, "invalid_argument", res, res_size);
      ei_decode_binary(buf, &index, &key[0], &key_size);

      TCLIST *vals = tcbdbget4(bdb, key, key_size);
      if (vals) {
        ei_x_encode_tuple_header(&x, 2);
        ei_x_encode_atom(&x, "ok");
        int j;
        for (j=0; j<tclistnum(vals); j++) {
          value_tmp = tclistval(vals, j, &sz);
          ei_x_encode_list_header(&x, 1);
          ei_x_encode_binary(&x, value_tmp, sz);
        }
        tclistdel(vals);
        ei_x_encode_empty_list(&x);
      } else {
        ei_x_encode_tuple_header(&x, 2);
        ei_x_encode_atom(&x, "ok");
        ei_x_encode_empty_list(&x);
      }
      break;

    case REMOVE:
      // remove(Keys::list())
      // remove(Key::binary())
      // remove({Key::binary(), Value::binary()})
      ei_get_type(buf, &index, &tp, &sz);
      if (tp == ERL_LIST_EXT) {
        int count, j;
        ei_decode_list_header(buf, &index, &count);
        for (j=0; j<count; j++) {
          ei_get_type(buf, &index, &tp, &sz);
          if (tp != ERL_BINARY_EXT || sz > MAX_KEY_SIZE)
            return ei_error(&x, "invalid_argument", res, res_size);
          ei_decode_binary(buf, &index, &key[0], &key_size);
          if (!tcbdbout3(bdb, &key[0], key_size))
            return ei_error(&x, tcbdberrmsg(tcbdbecode(bdb)), res, res_size);
        }
        ei_x_encode_atom(&x, "ok");
      } else if (tp == ERL_BINARY_EXT && sz <= MAX_KEY_SIZE) {
        ei_decode_binary(buf, &index, &key[0], &key_size);
        tcbdbout3(bdb, &key[0], key_size);
        ei_x_encode_atom(&x, "ok");
      } else if (tp == ERL_SMALL_TUPLE_EXT && sz == 2) {
        ei_decode_tuple_header(buf, &index, &sz);
        // get key
        ei_get_type(buf, &index, &tp, &sz);
        if (tp != ERL_BINARY_EXT || sz > MAX_KEY_SIZE)
          return ei_error(&x, "invalid_argument", res, res_size);
        ei_decode_binary(buf, &index, &key[0], &key_size);
        // get value
        ei_get_type(buf, &index, &tp, &sz);
        if (tp != ERL_BINARY_EXT || sz > MAX_VALUE_SIZE)
          return ei_error(&x, "invalid_argument", res, res_size);
        ei_decode_binary(buf, &index, &value[0], &value_size);
        // remove by key&value
        BDBCUR *cur = tcbdbcurnew(bdb);
        if (!tcbdbcurjump(cur, &key[0], key_size))
          return ei_error(&x, "record_not_found", res, res_size);
        
        bool removed = false, not_found = false;
        while (!removed && !not_found) {
          int cur_key_size, cur_val_size;
          const void *curkey = tcbdbcurkey3(cur, &cur_key_size);
          if (cur_key_size == key_size && memcmp(curkey, key, key_size) == 0) {
            const void *curval = tcbdbcurval3(cur, &cur_val_size);
            if (cur_val_size == value_size && memcmp(curval, value, value_size) == 0) {
              tcbdbcurout(cur);
              removed = true;
            } else
              if (!tcbdbcurnext(cur))
                not_found = true;
          } else not_found = true;
        }
        if (not_found) ei_x_encode_atom(&x, "not_found");
        else ei_x_encode_atom(&x, "ok");
        
      } else
        return ei_error(&x, "invalid_argument", res, res_size);
      break;

    case RANGE:
      /*
       * range({Prefix::binary(), limit:integer()})
       * range({StartKey::binary(), BeginInclusion::boolean(), EndKey::binary(), EndInclusion::binary(), limit:integer()})
       */
      ei_get_type(buf, &index, &tp, &sz);
      if (tp != ERL_SMALL_TUPLE_EXT || sz < 2)
        return ei_error(&x, "invalid_argument", res, res_size);
      ei_decode_tuple_header(buf, &index, &sz);

      ei_get_type(buf, &index, &tp, &sz);
      if (tp == ERL_BINARY_EXT && sz <= MAX_KEY_SIZE) {
        char keys[MAX_KEY_SIZE], keyf[MAX_KEY_SIZE];
        long keys_size, keyf_size;
        int keys_inc, keyf_inc;
        long max = -1;
        TCLIST *range;

        ei_decode_binary(buf, &index, &keys[0], &keys_size);
        ei_get_type(buf, &index, &tp, &sz);
        if (tp == ERL_ATOM_EXT) {
          // range
          ei_decode_boolean(buf, &index, &keys_inc);
          ei_get_type(buf, &index, &tp, &sz);
          if (tp != ERL_BINARY_EXT || sz > MAX_KEY_SIZE)
            return ei_error(&x, "invalid_argument", res, res_size);
          ei_decode_binary(buf, &index, &keyf[0], &keyf_size);
          ei_get_type(buf, &index, &tp, &sz);
          if (tp != ERL_ATOM_EXT)
            return ei_error(&x, "invalid_argument", res, res_size);
          ei_decode_boolean(buf, &index, &keyf_inc);

          ei_get_type(buf, &index, &tp, &sz);
          if (tp != ERL_INTEGER_EXT)
            return ei_error(&x, "invalid_argument", res, res_size);
          ei_decode_long(buf, &index, &max);

          range = tcbdbrange(bdb, &keys[0], keys_size, keys_inc == 1, &keyf[0], keyf_size, keyf_inc == 1, max);
        } else if (tp == ERL_INTEGER_EXT) {
          // prefix
          ei_get_type(buf, &index, &tp, &sz);
          if (tp != ERL_INTEGER_EXT)
            return ei_error(&x, "invalid_argument", res, res_size);
          ei_decode_long(buf, &index, &max);

          range = tcbdbfwmkeys(bdb, &keys[0], keys_size, max);
        } else
          return ei_error(&x, "invalid_argument", res, res_size);

        const char *key;
        int key_size, value_size;
        int idx, cnt = 0, rcount = tclistnum(range);

        ei_x_encode_tuple_header(&x, 2);
        ei_x_encode_atom(&x, "ok");

        BDBCUR *cur = tcbdbcurnew(bdb);
        for (idx=0; idx<rcount; idx++) {
          key = tclistval(range, idx, &key_size);
          TCLIST *vals = tcbdbget4(bdb, key, key_size);
          if (vals) {
            int j;
            for (j=0; j<tclistnum(vals); j++) {
              ei_x_encode_list_header(&x, 1);
              value_tmp = tclistval(vals, j, &value_size);
              ei_x_encode_binary(&x, value_tmp, value_size);
              if (max >= 0 && ++cnt >= max) break;
            }
            tclistdel(vals);
          }
          idx++;
        }
        tcbdbcurdel(cur);
        tclistdel(range);
        ei_x_encode_empty_list(&x);

      } else
        return ei_error(&x, "invalid_argument", res, res_size);
      break;

    case SYNC:
      // sync()
      if (!tcbdbsync(bdb))
        return ei_error(&x, tcbdberrmsg(tcbdbecode(bdb)), res, res_size);
      ei_x_encode_atom(&x, "ok");
      break;

    case INFO:
      // info()
      ei_x_encode_tuple_header(&x, 3);
      ei_x_encode_atom(&x, "ok");
      long_tmp = tcbdbrnum(bdb);
      ei_x_encode_longlong(&x, long_tmp);
      long_tmp = tcbdbfsiz(bdb);
      ei_x_encode_longlong(&x, long_tmp);
      break;

    case ITERATE:
      // Read(none) -> {ok, Key} | {error, not_found}
      // Read(Key::binary()) -> {ok, Key} | {error, not_found}
      ei_get_type(buf, &index, &tp, &sz);
      BDBCUR *cur = tcbdbcurnew(bdb);
      if (tp == ERL_BINARY_EXT && sz <= MAX_KEY_SIZE) {
        ei_decode_binary(buf, &index, &key[0], &key_size);
        rs = tcbdbcurjump(cur, &key[0], key_size) && tcbdbcurnext(cur);
      } else
        rs = tcbdbcurfirst(cur);
      if (rs) {
        int key_size;
        const char *key = tcbdbcurkey3(cur, &key_size);

        ei_x_encode_tuple_header(&x, 2);
        ei_x_encode_atom(&x, "ok");
        ei_x_encode_binary(&x, key, key_size);
        tcbdbcurdel(cur);
      } else {
        tcbdbcurdel(cur);
        return ei_error(&x, "not_found", res, res_size);
      }
      break;

    case VANISH:
      // vanish() -> ok
      if (!tcbdbvanish(bdb))
        return ei_error(&x, tcbdberrmsg(tcbdbecode(bdb)), res, res_size);
      ei_x_encode_atom(&x, "ok");
      break;

    case BACKUP:
      // backup(path::string()) -> ok | {error, Reason}
      ei_get_type(buf, &index, &tp, &sz);
      if (tp == ERL_STRING_EXT) {
        char *file = driver_alloc(sz + 1);
        ei_decode_string(buf, &index, file);
        if (tcbdbcopy(driver->bdb, file))
          ei_x_encode_atom(&x, "ok");
        else
          return ei_error(&x, tcbdberrmsg(tcbdbecode(bdb)), res, res_size);
      } else
        return ei_error(&x, "invalid_argument", res, res_size);
      break;

    default:
      return ei_error(&x, "invalid_command", res, res_size);
  }

  if (res_size < x.index)
    (*res) = (char *)driver_alloc(x.index);
  int n = x.index;
  memcpy(*res, x.buff, x.index);
  ei_x_free(&x);
  return n;
};
예제 #4
0
/* initialize */
JNIEXPORT void JNICALL Java_tokyocabinet_BDB_initialize
(JNIEnv *env, jobject self){
  TCBDB *bdb = tcbdbnew();
  tcbdbsetmutex(bdb);
  (*env)->SetLongField(env, self, bdb_fid_ptr, (intptr_t)bdb);
}