int couchbase_set(cachedb_con *connection,str *attr,
		str *val,int expires)
{
	lcb_t instance;
	lcb_error_t oprc;
	lcb_store_cmd_t cmd;
	const lcb_store_cmd_t *commands[1];
	struct timeval start;

	start_expire_timer(start,couch_exec_threshold);
	instance = COUCHBASE_CON(connection);

	commands[0] = &cmd;
	memset(&cmd, 0, sizeof(cmd));
	cmd.v.v0.operation = LCB_SET;
	cmd.v.v0.key = attr->s;
	cmd.v.v0.nkey = attr->len;
	cmd.v.v0.bytes = val->s;
	cmd.v.v0.nbytes = val->len;
	cmd.v.v0.exptime = expires;

	oprc = lcb_store(instance, NULL, 1, commands);

	if (oprc != LCB_SUCCESS) {
		LM_ERR("Set request failed - %s\n", lcb_strerror(instance, oprc));
		//Attempt reconnect
		if(couchbase_conditional_reconnect(connection, oprc) != 1) {
			stop_expire_timer(start,couch_exec_threshold,
			"cachedb_couchbase set",attr->s,attr->len,0);
			return -2;
		}

		//Try again
		instance = COUCHBASE_CON(connection);
		oprc = lcb_store(instance, NULL, 1, commands);

		if (oprc != LCB_SUCCESS) {
			LM_ERR("Set command retry failed - %s\n", lcb_strerror(instance, oprc));
			stop_expire_timer(start,couch_exec_threshold,
			"cachedb_couchbase set",attr->s,attr->len,0);
			return -2;
		}
		LM_ERR("Set command successfully retried\n");
	}
	LM_DBG("Succesfully stored\n");
	stop_expire_timer(start,couch_exec_threshold,
	"cachedb_couchbase set",attr->s,attr->len,0);
	return 1;
}
/** Store a document by key in Couchbase
 *
 * Setup and execute a Couchbase set operation and wait for the result.
 *
 * @param  instance Couchbase connection instance.
 * @param  key      Document key to store in the database.
 * @param  document Document body to store in the database.
 * @param  expire   Expiration time for the document (0 = never)
 * @return          Couchbase error object.
 */
lcb_error_t couchbase_set_key(lcb_t instance, const char *key, const char *document, int expire)
{
	lcb_error_t error;                  /* couchbase command return */
	lcb_store_cmd_t cmd;                /* store command stuct */
	const lcb_store_cmd_t *commands[1]; /* store commands array */

	/* init commands */
	commands[0] = &cmd;
	memset(&cmd, 0, sizeof(cmd));

	/* populate command struct */
	cmd.v.v0.key = key;
	cmd.v.v0.nkey = strlen(cmd.v.v0.key);
	cmd.v.v0.bytes = document;
	cmd.v.v0.nbytes = strlen(cmd.v.v0.bytes);
	cmd.v.v0.exptime = expire;
	cmd.v.v0.operation = LCB_SET;

	/* store key/document in couchbase */
	if ((error = lcb_store(instance, NULL, 1, commands)) == LCB_SUCCESS) {
		/* enter event loop on success */
		lcb_wait(instance);
	}

	/* return error */
	return error;
}
static void test_get1(void)
{
    lcb_error_t err;
    struct rvbuf rv;
    lcb_store_cmd_t storecmd;
    const lcb_store_cmd_t *storecmds[] = { &storecmd };
    lcb_get_cmd_t getcmd;
    const lcb_get_cmd_t *getcmds[] = { &getcmd };

    memset(&storecmd, 0, sizeof(storecmd));
    storecmd.v.v0.key = "foo";
    storecmd.v.v0.nkey = strlen(storecmd.v.v0.key);
    storecmd.v.v0.bytes = "bar";
    storecmd.v.v0.nbytes = strlen(storecmd.v.v0.bytes);
    storecmd.v.v0.operation = LCB_SET;

    (void)lcb_set_store_callback(session, store_callback);
    (void)lcb_set_get_callback(session, get_callback);

    err = lcb_store(session, &rv, 1, storecmds);
    lcb_assert(err == LCB_SUCCESS);
    io->v.v0.run_event_loop(io);
    lcb_assert(rv.error == LCB_SUCCESS);

    memset(&rv, 0, sizeof(rv));
    memset(&getcmd, 0, sizeof(getcmd));
    getcmd.v.v0.key = "foo";
    getcmd.v.v0.nkey = strlen(getcmd.v.v0.key);
    err = lcb_get(session, &rv, 1, getcmds);
    lcb_assert(err == LCB_SUCCESS);
    io->v.v0.run_event_loop(io);
    lcb_assert(rv.error == LCB_SUCCESS);
    lcb_assert(rv.nbytes == strlen("bar"));
    lcb_assert(memcmp(rv.bytes, "bar", 3) == 0);
}
static void test_set2(void)
{
    lcb_error_t err;
    struct rvbuf rv;
    lcb_size_t ii;
    lcb_store_cmd_t cmd;
    const lcb_store_cmd_t *cmds[] = { &cmd };

    memset(&cmd, 0, sizeof(cmd));
    cmd.v.v0.key = "foo";
    cmd.v.v0.nkey = strlen(cmd.v.v0.key);
    cmd.v.v0.bytes = "bar";
    cmd.v.v0.nbytes = strlen(cmd.v.v0.bytes);
    cmd.v.v0.operation = LCB_SET;

    (void)lcb_set_store_callback(session, mstore_callback);
    rv.errors = 0;
    rv.counter = 0;
    for (ii = 0; ii < 10; ++ii, ++rv.counter) {
        err = lcb_store(session, &rv, 1, cmds);
        lcb_assert(err == LCB_SUCCESS);
    }
    io->v.v0.run_event_loop(io);
    lcb_assert(rv.errors == 0);
}
Beispiel #5
0
static void process_file(const char *fname)
{
    char *ptr = NULL;
    size_t size;
    cJSON *json, *id;
    lcb_error_t ret;
    int error = 0;
    lcb_store_cmd_t cmd;
    const lcb_store_cmd_t* const cmds[1] = { &cmd };

    if (fname[0] == '.') {
        if (strcmp(fname, ".dump_stats") == 0) {
            fprintf(stdout, "Dumping stats:\n");
            lcb_get_timings(instance, stdout, timings_callback);
            fprintf(stdout, "----\n");
            remove(fname);
        }
        return;
    }

    if (loadit(fname, &ptr, &size) == -1) {
        /* Error message already printed */
        return;
    }

    if ((json = cJSON_Parse(ptr)) == NULL) {
        invalid_file(INVALID_JSON, fname);
        free(ptr);
        return;
    }

    id = cJSON_GetObjectItem(json, "_id");
    if (id == NULL || id->type != cJSON_String) {
        invalid_file(UNKNOWN_JSON, fname);
        free(ptr);
        return;
    }

    memset(&cmd, 0, sizeof(cmd));
    cmd.v.v0.key = id->valuestring;
    cmd.v.v0.nkey = strlen(id->valuestring);
    cmd.v.v0.bytes = ptr;
    cmd.v.v0.nbytes = size;
    cmd.v.v0.operation = LCB_SET;

    ret = lcb_store(instance, &error, 1, cmds);
    if (ret == LCB_SUCCESS) {
        lcb_wait(instance);
    } else {
        error = 1;
    }

    free(ptr);
    if (error) {
        fprintf(stderr, "Failed to store %s: %s\n", fname,
                lcb_strerror(instance, ret));
    } else {
        remove(fname);
    }
}
int _tmain(int argc, _TCHAR* argv[])
{
	// initializing

	struct lcb_create_st cropts = { 0 };
	cropts.version = 3;
	cropts.v.v3.connstr = "couchbase://localhost/default";
	lcb_error_t err;
	lcb_t instance;
	err = lcb_create(&instance, &cropts);
	if (err != LCB_SUCCESS) {
		printf("Couldn't create instance!\n");
		exit(1);
	}

	// connecting

	lcb_connect(instance);
	lcb_wait(instance);
	if ((err = lcb_get_bootstrap_status(instance)) != LCB_SUCCESS) {
		printf("Couldn't bootstrap!\n");
		exit(1);
	}

	// installing callbacks

	lcb_set_store_callback(instance, storage_callback);
	lcb_set_get_callback(instance, get_callback);


	// scheduling operations

	lcb_store_cmd_t scmd;
	const lcb_store_cmd_t *scmdlist = &scmd;
	scmd.v.v0.key = "Hello";
	scmd.v.v0.nkey = 5;
	scmd.v.v0.bytes = "Couchbase";
	scmd.v.v0.nbytes = 9;
	scmd.v.v0.operation = LCB_SET;
	err = lcb_store(instance, NULL, 1, &scmdlist);
	if (err != LCB_SUCCESS) {
		printf("Couldn't schedule storage operation!\n");
		exit(1);
	}
	lcb_wait(instance); //storage_callback is invoked here

	lcb_get_cmd_t gcmd = { 0 };
	const lcb_get_cmd_t *gcmdlist = &gcmd;
	gcmd.v.v0.key = "Hello";
	gcmd.v.v0.nkey = 5;
	err = lcb_get(instance, NULL, 1, &gcmdlist);
	if (err != LCB_SUCCESS) {
		printf("Couldn't schedule get operation!\n");
		exit(1);
	}
	lcb_wait(instance); // get_callback is invoked here
	lcb_destroy(instance);
	return 0;
}
Beispiel #7
0
lcb_error_t form_command_fset(lcb_error_t err, lcb_t instance, const char *const key) {
	lcb_store_cmd_t cmd;
	const lcb_store_cmd_t* commands[1];
	commands[0] = &cmd;
	memset(&cmd, 0, sizeof(cmd));
	cmd.v.v0.operation = LCB_FSET;
	cmd.v.v0.key = "fra";
	cmd.v.v0.key = key;
	cmd.v.v0.nkey = 3;
	cmd.v.v0.bytes = "123";
	cmd.v.v0.nbytes = 3;
	cmd.v.v0.flags = 1; // offset
	cmd.v.v0.exptime = (lcb_time_t)1; // length
	err = lcb_store(instance, NULL, 1, commands);
	return err;
}
Beispiel #8
0
lcb_error_t form_command(lcb_error_t err, lcb_t instance, const char * const key, const int count) {
	lcb_store_cmd_t cmd;
	const lcb_store_cmd_t* commands[1];
	commands[0] = &cmd;
	memset(&cmd, 0, sizeof(cmd));
	cmd.v.v0.operation = LCB_SET;
	cmd.v.v0.key = "foo";
    if (key) cmd.v.v0.key = key;
	cmd.v.v0.nkey = 3;
	cmd.v.v0.bytes = "bar";
	cmd.v.v0.nbytes = 3;
    print_timestamp();
    for (int i=0; i < count; i++)
        err = lcb_store(instance, NULL, 1, commands);
	return err;
}
static void test_spurious_saslerr(void)
{
    int iterations = 50;
    struct rvbuf rvs[50];
    int i;
    lcb_error_t err;
    lcb_store_cmd_t storecmd;
    const lcb_store_cmd_t *storecmds[] = { &storecmd };
    lcb_set_store_callback(session, mstore_callback);

    memset(rvs, 0, sizeof(rvs));

    for (i = 0; i < iterations; i++) {
        rvs[i].counter = 999; /*don't trigger a stop_event_loop*/
        memset(&storecmd, 0, sizeof(storecmd));
        storecmd.v.v0.key = "KEY";
        storecmd.v.v0.nkey = strlen(storecmd.v.v0.key);
        storecmd.v.v0.bytes = "KEY";
        storecmd.v.v0.nbytes = strlen(storecmd.v.v0.bytes);
        storecmd.v.v0.operation = LCB_SET;
        err = lcb_store(session, rvs + i, 1, storecmds);
        if (err != LCB_SUCCESS) {
            err_exit("Store operation failed");
        }
    }
    lcb_wait(session);

    for (i = 0; i < iterations; i++) {
        char *errinfo = NULL;
        if (rvs[i].errors != LCB_SUCCESS) {
            errinfo = "Did not get success response";
        } else if (rvs[i].nkey != 3) {
            errinfo = "Did not get expected key length";
        } else if (memcmp(rvs[i].key, "KEY", 3) != 0) {
            errinfo = "Weird key size";
        }
        if (errinfo) {
            err_exit("%s", errinfo);
        }
    }
}
static void test_set1(void)
{
    lcb_error_t err;
    struct rvbuf rv;
    lcb_store_cmd_t cmd;
    const lcb_store_cmd_t *cmds[] = { &cmd };

    memset(&cmd, 0, sizeof(cmd));
    cmd.v.v0.key = "foo";
    cmd.v.v0.nkey = strlen(cmd.v.v0.key);
    cmd.v.v0.bytes = "bar";
    cmd.v.v0.nbytes = strlen(cmd.v.v0.bytes);
    cmd.v.v0.operation = LCB_SET;
    (void)lcb_set_store_callback(session, store_callback);
    err = lcb_store(session, &rv, 1, cmds);
    lcb_assert(err == LCB_SUCCESS);
    io->v.v0.run_event_loop(io);
    lcb_assert(rv.error == LCB_SUCCESS);
    lcb_assert(rv.operation == LCB_SET);
    lcb_assert(memcmp(rv.key, "foo", 3) == 0);
}
int couchbase_set(cachedb_con *connection,str *attr,
		str *val,int expires)
{
	lcb_t instance;
	lcb_error_t oprc;
	lcb_store_cmd_t cmd;
	const lcb_store_cmd_t *commands[1];

	last_error = LCB_SUCCESS;

	instance = COUCHBASE_CON(connection);

	commands[0] = &cmd;
	memset(&cmd, 0, sizeof(cmd));
	cmd.v.v0.operation = LCB_SET;
	cmd.v.v0.key = attr->s;
	cmd.v.v0.nkey = attr->len;
	cmd.v.v0.bytes = val->s;
	cmd.v.v0.nbytes = val->len;
	cmd.v.v0.exptime = expires;
	oprc = lcb_store(instance, NULL, 1, commands);

	if (oprc != LCB_SUCCESS) {
		LM_ERR("Failed to send the insert query - %s\n", lcb_strerror(instance, oprc));
		couchbase_conditional_reconnect(connection, oprc);
		return -2;
	}

	lcb_wait(instance);

	oprc = lcb_get_last_error(instance);
	if (last_error != LCB_SUCCESS) {
		couchbase_conditional_reconnect(connection, last_error);
		return -1;
	}

	LM_DBG("Succesfully stored\n");
	return 1;
}
Beispiel #12
0
Datei: cb.c Projekt: muut/cberl
ERL_NIF_TERM cb_store(ErlNifEnv* env, handle_t* handle, void* obj)
{
    store_args_t* args = (store_args_t*)obj;

    struct libcouchbase_callback cb;

    lcb_error_t ret;

    lcb_store_cmd_t cmd;
    const lcb_store_cmd_t *commands[1];

    commands[0] = &cmd;
    memset(&cmd, 0, sizeof(cmd));
    cmd.v.v0.operation = args->operation;
    cmd.v.v0.key = args->key;
    cmd.v.v0.nkey = args->nkey;
    cmd.v.v0.bytes = args->bytes;
    cmd.v.v0.nbytes = args->nbytes;
    cmd.v.v0.flags = args->flags;
    cmd.v.v0.exptime = args->exp;
    cmd.v.v0.cas = args->cas;

    ret = lcb_store(handle->instance, &cb, 1, commands);

    free(args->key);
    free(args->bytes);

    if (ret != LCB_SUCCESS) {
        return return_lcb_error(env, ret);
    }

    lcb_wait(handle->instance);

    if (cb.error != LCB_SUCCESS) {
        return return_lcb_error(env, cb.error);
    }
    return A_OK(env);
}
Beispiel #13
0
PHP_COUCHBASE_LOCAL
void php_couchbase_cas_impl(INTERNAL_FUNCTION_PARAMETERS, int oo)
{
	zval *value;
	time_t exp = {0};
	unsigned int flags = 0;
	size_t payload_len = 0;
	unsigned long long cas_v = 0;
	char *key, *payload, *cas = NULL;
	long klen = 0, expire = 0, cas_len = 0;
	php_couchbase_res *couchbase_res;
	long replicate_to = 0;
	long persist_to = 0;
	lcb_error_t retval;
	php_couchbase_ctx *ctx;
	lcb_store_cmd_t cmd;
	const lcb_store_cmd_t *const commands[] = { &cmd };
	int argf = oo ? PHP_COUCHBASE_ARG_F_OO : PHP_COUCHBASE_ARG_F_FUNCTIONAL;

	PHP_COUCHBASE_GET_PARAMS(couchbase_res, argf, "ssz|lll", &cas, &cas_len,
							 &key, &klen, &value, &expire, &persist_to,
							 &replicate_to);

	if (pcbc_check_expiry(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo,
						  expire, &exp) == -1) {
		/* Incorrect expiry time */
		return;
	}

	if (validate_simple_observe_clause(couchbase_res->handle,
									   persist_to,
									   replicate_to TSRMLS_CC) == -1) {
		/* Exception already thrown */
		return;
	}

	if (klen == 0) {
		couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo,
							   cb_illegal_key_exception,
							   "Failed to schedule set request: Empty key");
		return;
	}

	if (cas_len == 0) {
		couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo,
							   cb_exception,
							   "Illegal CAS specified");
		return;
	}

	if (cas) {
		char *end;
		cas_v = strtoull(cas, &end, 10);
		if (*end != '\0') {
			couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo,
								   cb_exception,
								   "Illegal CAS specified");
			return;
		}
	}

	ctx = ecalloc(1, sizeof(php_couchbase_ctx));
	ctx->res = couchbase_res;
	ctx->rv = return_value;

	payload = php_couchbase_zval_to_payload(value, &payload_len, &flags,
											couchbase_res->serializer,
											couchbase_res->compressor
											TSRMLS_CC);
	if (payload == NULL) {
		RETURN_FALSE;
	}

	if (couchbase_res->prefix_key_len) {
		klen = spprintf(&key, 0, "%s_%s", couchbase_res->prefix_key, key);
	}

	memset(&cmd, 0, sizeof(cmd));
	cmd.v.v0.operation = LCB_SET;
	cmd.v.v0.key = key;
	cmd.v.v0.nkey = klen;
	cmd.v.v0.bytes = payload;
	cmd.v.v0.nbytes = payload_len;
	cmd.v.v0.flags = flags;
	cmd.v.v0.exptime = exp;
	cmd.v.v0.cas = (uint64_t)cas_v;

	retval = lcb_store(couchbase_res->handle, ctx, 1, commands);

	efree(payload);
	if (couchbase_res->prefix_key_len) {
		efree(key);
	}

	if (retval != LCB_SUCCESS) {
		efree(ctx);
		couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo,
							   cb_lcb_exception,
							   "Failed to schedule cas request: %s",
							   lcb_strerror(couchbase_res->handle, retval));
		return;
	}

	++couchbase_res->seqno;
	pcbc_start_loop(couchbase_res);
	zval_dtor(return_value);

	if (LCB_SUCCESS == ctx->res->rc) {
		ZVAL_TRUE(return_value);
	} else if (LCB_KEY_EEXISTS == ctx->res->rc) {
		ZVAL_FALSE(return_value);
	} else {
		couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo,
							   cb_lcb_exception,
							   "Failed to store a value to server: %s",
							   lcb_strerror(couchbase_res->handle,
											ctx->res->rc));
	}
	efree(ctx);
}
Beispiel #14
0
int main(void)
{
  struct lcb_create_st create_options;
  memset(&create_options, 0, sizeof create_options);
  create_options.version = 3;
  create_options.v.v3.connstr = "couchbase://10.141.95.101/default";
  // create_options.v.v3.passwd = "testbucket";
  lcb_error_t err;

  lcb_t instance = NULL;
  err = lcb_create(&instance, &create_options);
  if (err != LCB_SUCCESS) {
    fprintf(stderr, "Failed to create a couchbase instance: %s\n", lcb_strerror(instance,err));
    return 1;
  }
  // Default timeout values and settings:
  //http://developer.couchbase.com/documentation/server/current/sdks/c-2.4/options.html
  //Enable details error codes:
  lcb_cntl_string(instance,"detailed_errcodes","1");

  //Connecting
  lcb_connect(instance);
  lcb_wait(instance);
  if ( (err = lcb_get_bootstrap_status(instance)) != LCB_SUCCESS ) {
    printf("Couldn't bootstrap. Exiting!\n");
    exit(1);
  }

  // installing callbacks
  lcb_set_store_callback(instance, storage_callback);
  lcb_set_durability_callback(instance, durability_callback);

  // scheduling set operations with elements that expire
  lcb_store_cmd_t scmd = { 0 };
  const lcb_store_cmd_t *scmdlist = &scmd;
/*
    INSERT, Loop through x number of keys and insert them with expiry
*/
  for( int counter=1; counter <= NUMBER_OF_DOCUMENTS; counter++){
      // Setting keys and values
      const char *doc = "{\"json\" : \"data\" }";
      char key [12];
      sprintf(key, "%s%d", "test", counter);
      scmd.v.v0.key = key;
      scmd.v.v0.nkey = strlen(key);
      scmd.v.v0.bytes = doc;
      scmd.v.v0.nbytes = strlen(doc);
      scmd.v.v0.exptime = 300; //expiry of 5 minutes
      scmd.v.v0.operation = LCB_SET;

      err = lcb_store(instance, NULL, 1, (const lcb_store_cmd_t * const *)&scmdlist);
      if (err != LCB_SUCCESS) {
        printf("Couldn't schedule storage operation!\n");
        exit(1);
      }
      lcb_wait(instance);

      //Durability is invoked here
      lcb_durability_opts_t options;
      lcb_durability_cmd_t cmd = { 0 };
      const lcb_durability_cmd_t *cmdp = &cmd;
      cmd.v.v0.key = key;
      cmd.v.v0.nkey = strlen(key);
      options.v.v0.persist_to = 1;
      options.v.v0.replicate_to = 1;

      err = lcb_durability_poll(instance,NULL,&options,1,&cmdp);
      if (err != LCB_SUCCESS) {
        printf("couldn't schedule durability operation %s \n", lcb_strerror(instance, err));
      }
    lcb_wait(instance);
  }
  //closing the connection
  lcb_destroy(instance);
  return 0;
}
Beispiel #15
0
    static inline VALUE
cb_bucket_store(lcb_storage_t cmd, int argc, VALUE *argv, VALUE self)
{
    struct cb_bucket_st *bucket = DATA_PTR(self);
    struct cb_context_st *ctx;
    VALUE rv, proc, exc, obs = Qnil;
    lcb_error_t err;
    struct cb_params_st params;

    if (!cb_bucket_connected_bang(bucket, storage_opcode_to_sym(cmd))) {
        return Qnil;
    }
    memset(&params, 0, sizeof(struct cb_params_st));
    rb_scan_args(argc, argv, "0*&", &params.args, &proc);
    if (!bucket->async && proc != Qnil) {
        rb_raise(rb_eArgError, "synchronous mode doesn't support callbacks");
    }
    params.type = cb_cmd_store;
    params.bucket = bucket;
    params.cmd.store.operation = cmd;
    cb_params_build(&params);
    obs = params.cmd.store.observe;
    ctx = cb_context_alloc(bucket);
    if (!bucket->async) {
        ctx->rv = rb_hash_new();
        ctx->observe_options = obs;
    }
    ctx->proc = proc;
    ctx->nqueries = params.cmd.store.num;
    err = lcb_store(bucket->handle, (const void *)ctx,
            params.cmd.store.num, params.cmd.store.ptr);
    cb_params_destroy(&params);
    exc = cb_check_error(err, "failed to schedule set request", Qnil);
    if (exc != Qnil) {
        cb_context_free(ctx);
        rb_exc_raise(exc);
    }
    bucket->nbytes += params.npayload;
    if (bucket->async) {
        cb_maybe_do_loop(bucket);
        return Qnil;
    } else {
        if (ctx->nqueries > 0) {
            /* we have some operations pending */
            lcb_wait(bucket->handle);
        }
        exc = ctx->exception;
        rv = ctx->rv;
        cb_context_free(ctx);
        if (exc != Qnil) {
            rb_exc_raise(exc);
        }
        exc = bucket->exception;
        if (exc != Qnil) {
            bucket->exception = Qnil;
            rb_exc_raise(exc);
        }
        if (RTEST(obs)) {
            rv = rb_funcall(bucket->self, cb_id_observe_and_wait, 2, rv, obs);
        }
        if (params.cmd.store.num > 1) {
            return rv;  /* return as a hash {key => cas, ...} */
        } else {
            VALUE vv = Qnil;
            rb_hash_foreach(rv, cb_first_value_i, (VALUE)&vv);
            return vv;
        }
    }
}
static void test_touch1(void)
{
    lcb_error_t err;
    struct rvbuf rv;
    char *key = "fooX", *val = "bar";
    lcb_size_t nkey = strlen(key), nval = strlen(val);
    char **keys;
    lcb_size_t *nkeys, ii;
    lcb_time_t *ttls;
    lcb_store_cmd_t storecmd;
    const lcb_store_cmd_t *storecmds[] = { &storecmd };
    lcb_touch_cmd_t *touchcmds[26];

    (void)lcb_set_store_callback(session, store_callback);
    (void)lcb_set_touch_callback(session, touch_callback);

    keys = malloc(26 * sizeof(char *));
    nkeys = malloc(26 * sizeof(lcb_size_t));
    ttls = malloc(26 * sizeof(lcb_time_t));
    if (keys == NULL || nkeys == NULL || ttls == NULL) {
        err_exit("Failed to allocate memory for keys");
    }
    for (ii = 0; ii < 26; ii++) {
        nkeys[ii] = nkey;
        keys[ii] = strdup(key);
        ttls[ii] = 1;

        if (keys[ii] == NULL) {
            err_exit("Failed to allocate memory for key");
        }

        keys[ii][3] = (char)(ii + 'a');
        memset(&storecmd, 0, sizeof(storecmd));
        storecmd.v.v0.key = keys[ii];
        storecmd.v.v0.nkey = nkey;
        storecmd.v.v0.bytes = val;
        storecmd.v.v0.nbytes = nval;
        storecmd.v.v0.operation = LCB_SET;
        err = lcb_store(session, &rv, 1, storecmds);
        lcb_assert(err == LCB_SUCCESS);
        io->v.v0.run_event_loop(io);
        lcb_assert(rv.error == LCB_SUCCESS);
        memset(&rv, 0, sizeof(rv));

        touchcmds[ii] = calloc(1, sizeof(lcb_touch_cmd_t));
        if (touchcmds[ii] == NULL) {
            err_exit("Failed to allocate memory for touch command");
        }
        touchcmds[ii]->v.v0.key = keys[ii];
        touchcmds[ii]->v.v0.nkey = nkey;
    }

    rv.counter = 26;
    err = lcb_touch(session, &rv, 26, (const lcb_touch_cmd_t * const *)touchcmds);
    lcb_assert(err == LCB_SUCCESS);
    io->v.v0.run_event_loop(io);
    lcb_assert(rv.error == LCB_SUCCESS);
    for (ii = 0; ii < 26; ii++) {
        free(keys[ii]);
        free(touchcmds[ii]);
    }
    free(keys);
    free(ttls);
    free(nkeys);
}
Beispiel #17
0
PHP_COUCHBASE_LOCAL
void php_couchbase_store_multi_impl_oo(INTERNAL_FUNCTION_PARAMETERS)
{
	lcb_error_t retval;
	php_couchbase_res *couchbase_res;
	php_couchbase_ctx *ctx;
	time_t exp = {0};
	long expire = 0;
	zval *akeys;
	long persist_to = 0;
	long replicate_to = 0;
	struct observe_entry *entries;
	int numkeys;
	lcb_store_cmd_t *cmds;
	lcb_store_cmd_t **commands;
	int ii;

	PHP_COUCHBASE_GET_PARAMS(couchbase_res, PHP_COUCHBASE_ARG_F_OO, "a|lll",
							 &akeys, &expire, &persist_to, &replicate_to);

	if (pcbc_check_expiry(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1,
						  expire, &exp) == -1) {
		/* Incorrect expiry time */
		return;
	}

	if (validate_simple_observe_clause(couchbase_res->handle,
									   persist_to,
									   replicate_to TSRMLS_CC) == -1) {
		/* Exception already thrown */
		return;
	}

	numkeys = zend_hash_num_elements(Z_ARRVAL_P(akeys));
	if (numkeys == 0) {
		zend_throw_exception(cb_illegal_key_exception,
							 "No items specified",
							 0 TSRMLS_CC);
		return ;
	}

	entries = ecalloc(numkeys, sizeof(struct observe_entry));
	commands = ecalloc(numkeys, sizeof(lcb_store_cmd_t *));
	cmds = ecalloc(numkeys, sizeof(lcb_store_cmd_t));
	/* link the command pointers */
	for (ii = 0; ii < numkeys; ++ii) {
		commands[ii] = cmds + ii;
	}

	ctx = ecalloc(1, sizeof(php_couchbase_ctx));
	ctx->res = couchbase_res;
	ctx->rv	= return_value;
	array_init(ctx->rv);

	for (ii = 0, zend_hash_internal_pointer_reset(Z_ARRVAL_P(akeys));
			zend_hash_has_more_elements(Z_ARRVAL_P(akeys)) == SUCCESS;
			zend_hash_move_forward(Z_ARRVAL_P(akeys)), ++ii) {
		char *key = NULL;
		uint klen;
		size_t payload_len = 0;
		char *payload;
		unsigned int flags = 0;
		zval **ppzval;

		if (zend_hash_get_current_key_type(Z_ARRVAL_P(akeys)) != HASH_KEY_IS_STRING) {
			int xx;
			for (xx = 0; xx < ii; ++xx) {
				efree((void *)cmds[xx].v.v0.bytes);
			}
			efree(commands);
			efree(cmds);
			efree(ctx);
			release_entry_array(entries,  xx);

			zend_throw_exception(cb_illegal_key_exception,
								 "Invalid key specified (not a string)",
								 0 TSRMLS_CC);
			return ;
		}

		zend_hash_get_current_key(Z_ARRVAL_P(akeys), &key, NULL, 0);
		if ((klen = strlen(key)) == 0) {
			int xx;
			for (xx = 0; xx < ii; ++xx) {
				efree((void *)cmds[xx].v.v0.bytes);
			}
			efree(commands);
			efree(cmds);
			efree(ctx);
			release_entry_array(entries,  xx);

			zend_throw_exception(cb_illegal_key_exception,
								 "Invalid key specified (empty string)",
								 0 TSRMLS_CC);
			return ;
		}

		if (zend_hash_get_current_data(Z_ARRVAL_P(akeys),
									   (void **)&ppzval) == FAILURE) {
			int xx;
			for (xx = 0; xx < ii; ++xx) {
				efree((void *)cmds[xx].v.v0.bytes);
			}
			efree(commands);
			efree(cmds);
			efree(ctx);
			release_entry_array(entries,  xx);

			zend_throw_exception(cb_exception,
								 "Failed to get data for key",
								 0 TSRMLS_CC);
			return ;
		}

		payload = php_couchbase_zval_to_payload(*ppzval, &payload_len, &flags,
												couchbase_res->serializer,
												couchbase_res->compressor
												TSRMLS_CC);

		if (payload == NULL) {
			/* Shouldn't we call an exception? */
			RETURN_FALSE;
		}

		if (couchbase_res->prefix_key_len) {
			char *new_key;
			klen = spprintf(&new_key, 0, "%s_%s", couchbase_res->prefix_key, key);
			key = new_key;
		}

		entries[ii].nkey = klen;
		entries[ii].key = emalloc(klen);
		memcpy(entries[ii].key, key, klen);
		cmds[ii].v.v0.operation = LCB_SET;
		cmds[ii].v.v0.key = entries[ii].key;
		cmds[ii].v.v0.nkey = klen;
		cmds[ii].v.v0.bytes = payload;
		cmds[ii].v.v0.nbytes = payload_len;
		cmds[ii].v.v0.flags = flags;
		cmds[ii].v.v0.exptime = exp;

		if (couchbase_res->prefix_key_len) {
			efree(key);
		}
	}

	retval = lcb_store(couchbase_res->handle, ctx, numkeys,
					   (const lcb_store_cmd_t * const *)commands);
	couchbase_res->seqno += numkeys;
	pcbc_start_loop(couchbase_res);

	/*
	 * Time to release the payloads...
	 */
	for (ii = 0; ii < numkeys; ++ii) {
		efree((void *)cmds[ii].v.v0.bytes);
	}
	efree(cmds);
	efree(commands);

	if (LCB_SUCCESS != retval) {
		efree(ctx);
		couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1,
							   cb_lcb_exception,
							   "Failed to schedule set request: %s",
							   lcb_strerror(couchbase_res->handle, retval));
		release_entry_array(entries,  numkeys);
		RETURN_FALSE;
	}

	/*
	 * The item was stored successfully. Did the user want to wait until
	 * it was persisted/replicated?
	 */
	if (persist_to != 0 || replicate_to != 0) {
		int ii = 0;
		for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(return_value));
				zend_hash_has_more_elements(Z_ARRVAL_P(return_value)) == SUCCESS;
				zend_hash_move_forward(Z_ARRVAL_P(return_value)), ++ii) {
			zval **curr_cas;
			zend_hash_get_current_data(Z_ARRVAL_P(return_value),
									   (void **)&curr_cas);
			if (Z_STRLEN_PP(curr_cas)) {
				entries[ii].cas = strtoull(Z_STRVAL_PP(curr_cas), 0, 10);
			} else {
				/* @todo what to do here? */
				fprintf(stderr, "wtf!\n");
			}
		}

		retval = simple_observe(couchbase_res->handle, entries, numkeys,
								persist_to, replicate_to);
		couchbase_res->rc = retval;

		if (retval != LCB_SUCCESS) {
			if (retval == LCB_ETIMEDOUT) {
				zend_throw_exception(cb_timeout_exception,
									 "Timed out waiting for the objects to persist",
									 0 TSRMLS_CC);
			} else {
				char errmsg[256];
				snprintf(errmsg, sizeof(errmsg),
						 "An error occured while waiting for the objects to persist: %s",
						 lcb_strerror(couchbase_res->handle, retval));
				zend_throw_exception(cb_lcb_exception, errmsg, 0 TSRMLS_CC);
			}
		} else {
			int currsize = 4096;
			char *errmsg = malloc(currsize);
			int offset = sprintf(errmsg, "The following documents was mutated:");
			int errors = 0;

			for (ii = 0; ii < numkeys; ++ii) {
				if (entries[ii].mutated) {
					if ((offset + entries[ii].nkey + 3) > currsize) {
						char *p = realloc(errmsg, currsize * 2);
						if (p) {
							currsize *= 2;
							errmsg = p;
						}
					}

					if ((offset + entries[ii].nkey + 3) < currsize) {
						offset += sprintf(errmsg + offset, " \"");
						memcpy(errmsg + offset, entries[ii].key,
							   entries[ii].nkey);
						offset += entries[ii].nkey;
						offset += sprintf(errmsg + offset, "\"");
					}
					errors = 1;
				}
			}

			if (errors) {
				zend_throw_exception(cb_key_mutated_exception, errmsg,
									 0 TSRMLS_CC);
			}

			free(errmsg);
		}
	}

	release_entry_array(entries,  numkeys);
	efree(ctx);
}
Beispiel #18
0
int main(int argc, char*argv[]) 
{
	//couchbase error type
	lcb_error_t err;
	//couchbase type
	lcb_t instance;
	// couchbase create struct? its a struct with options to create what? a cb cluster, bucket or something else?
	struct lcb_create_st create_options = {0};
	memset(&create_options,0,sizeof(create_options));
	// set command type, and creating a list of store commands?
	lcb_store_cmd_t scmd = {0};
	const lcb_store_cmd_t *scmdlist[1];
	// get command type, and list of get commands!
	lcb_get_cmd_t gcmd = {0};
	const lcb_get_cmd_t *gcmdlist[1];

	create_options.version = 3; // cb version 3?

	if (argc < 2) 
	{
		fprintf(stderr, "Usage: %s couchbase://host/bucket [password] \n",argv[0] );
		exit(EXIT_FAILURE);		
	}

	create_options.v.v3.connstr = argv[1];
	if (argc >=3)
	{
		create_options.v.v3.passwd = argv[2];
	}
	
	//fprintf(stderr, "\n %s,%s,%s\n",create_options.v.v3.connstr,create_options.v.v3.passwd,"test" );
	/*
	create_options.version = 3;
	create_options.v.v3.connstr = "couchbase://192.168.56.101/pramod";
	create_options.v.v3.passwd = "couchbase";
	*/
	err = lcb_create(&instance, &create_options);
	if(err != LCB_SUCCESS)
	{
		die(instance, "Couldn't create couchbase handle", err);
	}

	err = lcb_connect(instance);
	if(err != LCB_SUCCESS) 
	{
		die(instance, "Couldn't schedule connection", err);
	}
	lcb_wait(instance);	// It says this will be blocking wait and won't execute in a async fashion


	err = lcb_get_bootstrap_status(instance);
	if (err != LCB_SUCCESS) 
	{
		die(instance, "Couldn't bootstrap from cluster", err);
	}
	// Assign the handlers to be called for the operations types
	lcb_set_get_callback(instance, get_callback);
	lcb_set_store_callback(instance, store_callback);
	//what are these callbacks for ? I thought callbacks are for getting results of asynchronous exectution of jobs?
	

	// what is happening in here? setting values? to the source command ? 
	//let my try to wrap this up in a loop to set a 1000 values?

	
	scmd.v.v0.operation = LCB_SET;
	scmd.v.v0.key = "foo";		scmd.v.v0.nkey = 3 ;
	scmd.v.v0.bytes = "barbeque";	scmd.v.v0.nbytes = 8;
	scmdlist[0] = &scmd;

	err = lcb_store(instance, NULL, 1, scmdlist);	// so here is where the data is getting written!!
	if (err != LCB_SUCCESS) 
	{
		die (instance, "Coudn't schedule storage operations", err);
	}

	// the store_callback is involed from lcb_wait()
	fprintf(stderr, "Will wait for storage operation to complete\n");
	lcb_wait(instance);




	//now fetch the items back
	gcmd.v.v0.key = "foo";
	gcmd.v.v0.nkey = 3;
	gcmd.v.v0.exptime = 60;
	gcmdlist[0] = &gcmd;
	err = lcb_get(instance, NULL, 1, gcmdlist);
	if (err != LCB_SUCCESS) 
	{
		die(instance, "Couldn't schedule retrieval operation", err);
	}

	// get callback invoked from here.
	fprintf(stderr, "Will wait to retrieve the set item!\n");
	lcb_wait(instance);

	// close the connection handle after everything is done
	lcb_destroy(instance);
	return 0;
}
Beispiel #19
0
int
couchdb_update(uint64_t key, char *data, size_t len)
{
	char *db_key = NULL;
	lcb_size_t	key_size;
	lcb_error_t	ret;
	int	lock_result = -1;
	lcb_store_cmd_t item;
	const lcb_store_cmd_t *const store_items[] = { &item };
	char *compressed_data = NULL;
	size_t	compressed_len = 0;
	int	res = 0;

	compressed_len = snappy_max_compressed_length(len);
	compressed_data = (char *)malloc(compressed_len);
	if (compressed_data == NULL) {
		syslog(LOG_ERR, "%s: Unable to allocate memory for compressed_data\n", __FUNCTION__);
		return (-ENOMEM);
	}

	if ((res = snappy_compress((const char *)data, len,
 			compressed_data, &compressed_len)) != SNAPPY_OK) {
		free(compressed_data);
		return (-res);
	}

	memset(&item, 0, sizeof(lcb_store_cmd_t));
	db_key = (char *) malloc(MAX_KEY_SIZE);
	if (NULL == db_key) {
		syslog(LOG_ERR, "%s: Unable to allocate memory for db_key\n",
			__FUNCTION__);
		return -ENOMEM;
	}
	sprintf(db_key,"%"PRId64"", key);
	USYSLOG(LOG_INFO, "%s: set1 %"PRId64" %s %s, \n", __FUNCTION__, key,
		(char *) data, db_key);
	key_size = strlen(db_key);

	item.v.v0.key = db_key;
	item.v.v0.nkey = key_size;
	item.v.v0.bytes = compressed_data;
	item.v.v0.nbytes = compressed_len;
	item.v.v0.operation = LCB_REPLACE;

	lock_result = pthread_rwlock_wrlock(&db_rwlock);
	if (lock_result != 0) {
		syslog(LOG_ERR, "%s: Failed to obtain write lock. Error = %d\n",
			__FUNCTION__, errno);
		return -errno;
	}

	ret = lcb_store(couchdb_handle, NULL, 1, store_items);
	if (ret != LCB_SUCCESS) {
		syslog(LOG_ERR, "%s: lcb_store failed with error %s\n",
			__FUNCTION__, lcb_strerror(couchdb_handle, ret));
		return -ret;
	}
	/* Block the thread till this operation completes */
	lcb_wait(couchdb_handle);

	pthread_rwlock_unlock(&db_rwlock);

	return  (1);

}
Beispiel #20
0
int main(void)
{

  // initializing
  struct lcb_create_st create_options;
  memset(&create_options, 0, sizeof create_options);
  create_options.version = 3;
  create_options.v.v3.connstr = "couchbase://10.141.110.101,10.141.110.102,10.141.110.103/testbucket";
  create_options.v.v3.passwd = "testbucket";
  lcb_error_t err;
  lcb_t instance = NULL;
  err = lcb_create(&instance, &create_options);
  if (err != LCB_SUCCESS) {
    fprintf(stderr, "Failed to create a couchbase instance: %s\n", lcb_strerror(instance,err));
    return 1;
  }
// Default timeout values and settings: http://developer.couchbase.com/documentation/server/current/sdks/java-2.2/env-config.html
//Enable details error codes:
//http://developer.couchbase.com/documentation/server/current/sdks/c-2.4/options.html
  lcb_cntl_string(instance,"detailed_errcodes","1");

  //connecting
  lcb_connect(instance);
  lcb_wait(instance);
  if ( (err = lcb_get_bootstrap_status(instance)) != LCB_SUCCESS ) {
    printf("Couldn't bootstrap. Exiting!\n");
    exit(1);
  }
  sleep(20);
  
  // installing callbacks
  lcb_set_store_callback(instance, storage_callback);
  lcb_set_get_callback(instance, get_callback);

  
  // scheduling set operations with elements that expire
  lcb_store_cmd_t scmd = { 0 };
  const lcb_store_cmd_t *scmdlist = &scmd;
/*
    INSERT, Loop through x number of keys and insert them with expiry
*/

  for( int counter=0; counter <NUMBER_OF_DOCUMENTS; counter ++){
      // Setting keys and values
      const char *doc = "{\"json\" : \"data\" }";
      char key [12];
      sprintf(key, "%s%d", "test", counter);
      scmd.v.v0.key = key;
      scmd.v.v0.nkey = strlen(key);
      scmd.v.v0.bytes = doc;
      scmd.v.v0.nbytes = strlen(doc);
//      scmd.v.v0.exptime = 300; //expiry of 5 minutes
      scmd.v.v0.operation = LCB_SET;

      err = lcb_store(instance, NULL, 1, &scmdlist);
      if (err != LCB_SUCCESS) {
        printf("Couldn't schedule storage operation!\n");
        exit(1);
      }
      lcb_wait(instance); //storage_callback is invoked here
  }


/*
    GET section
*/
  lcb_get_cmd_t gcmd = { 0 };
  const lcb_get_cmd_t *gcmdlist = &gcmd;
    for( int counter=0; counter <NUMBER_OF_DOCUMENTS; counter ++){
         char key[12];
//         sleep(3);
         sprintf(key,"%s%d", "test", counter);
         gcmd.v.v0.key = key;
         gcmd.v.v0.nkey = strlen(key);
         fprintf(stderr, "GET : %s\n", key);
//         printf("GET %s\n", key);
         err = lcb_get(instance, NULL, 1, &gcmdlist);
         lcb_wait(instance); // get_callback is invoked here
    }

  //closing the connection
  lcb_destroy(instance);
  return 0;
}
Beispiel #21
0
PHP_COUCHBASE_LOCAL
void php_couchbase_store_impl_oo(INTERNAL_FUNCTION_PARAMETERS, lcb_storage_t op)
{
	lcb_error_t retval;
	php_couchbase_res *couchbase_res;
	php_couchbase_ctx *ctx;
	time_t exp = {0};
	unsigned int flags = 0;
	char *cas = NULL;
	char *payload;
	size_t payload_len = 0;
	unsigned long long cas_v = 0;
	long expire = 0;
	long replicate_to = 0;
	long persist_to = 0;
	long cas_len = 0;
	char *key = NULL;
	zval *value;
	long klen = 0;
	lcb_store_cmd_t cmd;
	const lcb_store_cmd_t *const commands[] = { &cmd };

	if (op == LCB_ADD) {
		PHP_COUCHBASE_GET_PARAMS(couchbase_res, PHP_COUCHBASE_ARG_F_OO,
								 "sz|lll", &key, &klen, &value, &expire,
								 &persist_to, &replicate_to);
	} else {
		PHP_COUCHBASE_GET_PARAMS(couchbase_res, PHP_COUCHBASE_ARG_F_OO,
								 "sz|lsll", &key, &klen, &value, &expire,
								 &cas, &cas_len, &persist_to, &replicate_to);
	}

	if (pcbc_check_expiry(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1,
						  expire, &exp) == -1) {
		/* Incorrect expiry time */
		return;
	}

	if (validate_simple_observe_clause(couchbase_res->handle,
									   persist_to,
									   replicate_to TSRMLS_CC) == -1) {
		/* Exception already thrown */
		return;
	}

	if (!klen) {
		zend_throw_exception(cb_illegal_key_exception,
							 "Failed to schedule set request: Empty key",
							 0 TSRMLS_CC);
		return ;
	}

	if (cas) {
		char *e;
		cas_v = (lcb_cas_t)strtoull(cas, &e, 10);
		if (*e != '\0') {
			couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1,
								   cb_illegal_key_exception,
								   "Invalid CAS specified");
			return;
		}
	}

	payload = php_couchbase_zval_to_payload(value, &payload_len, &flags,
											couchbase_res->serializer,
											couchbase_res->compressor
											TSRMLS_CC);
	if (payload == NULL) {
		/* ?? I guess we should throw an exception here? */
		RETURN_FALSE;
	}

	if (couchbase_res->prefix_key_len) {
		klen = spprintf(&key, 0, "%s_%s", couchbase_res->prefix_key, key);
	}

	ctx = ecalloc(1, sizeof(php_couchbase_ctx));
	ctx->res = couchbase_res;
	ctx->rv = return_value;
	couchbase_res->seqno += 1;

	memset(&cmd, 0, sizeof(cmd));
	cmd.v.v0.operation = op;
	cmd.v.v0.key = key;
	cmd.v.v0.nkey = klen;
	cmd.v.v0.bytes = payload;
	cmd.v.v0.nbytes = payload_len;
	cmd.v.v0.flags = flags;
	cmd.v.v0.exptime = exp;
	cmd.v.v0.cas = (uint64_t)cas_v;

	retval = lcb_store(couchbase_res->handle, ctx, 1, commands);

	efree(payload);
	if (couchbase_res->prefix_key_len) {
		efree(key);
	}

	if (retval != LCB_SUCCESS) {
		char errmsg[256];
		efree(ctx);
		sprintf(errmsg, "Failed to schedule set request: %s",
				lcb_strerror(couchbase_res->handle, retval));
		zend_throw_exception(cb_lcb_exception, errmsg, 0 TSRMLS_CC);
		return ;
	}

	pcbc_start_loop(couchbase_res);
	if (LCB_SUCCESS != ctx->res->rc) {
		RETVAL_FALSE;
		switch (op) {
		case LCB_ADD:
			if (LCB_KEY_EEXISTS == ctx->res->rc) {
				break;
			}
		case LCB_APPEND:
		case LCB_PREPEND:
			if (LCB_NOT_STORED == ctx->res->rc) {
				break;
			}
		case LCB_REPLACE:
		case LCB_SET:
			if (LCB_KEY_ENOENT == ctx->res->rc) {
				break;
			}
			if (cas && LCB_KEY_EEXISTS == ctx->res->rc) {
				break;
			}
		default: {
			char errmsg[256];
			sprintf(errmsg, "Failed to store value to server: %s",
					lcb_strerror(couchbase_res->handle, ctx->res->rc));
			zend_throw_exception(cb_lcb_exception, errmsg, 0 TSRMLS_CC);
		}

		break;
		}
	} else {
		/*
		 * The item was stored successfully. Did the user want to wait until
		 * it was persisted/replicated?
		 */
		if (persist_to != 0 || replicate_to != 0) {
			struct observe_entry entry;
			memset(&entry, 0, sizeof(entry));
			entry.key = key;
			entry.nkey = klen;
			entry.cas = strtoull(Z_STRVAL_P(return_value), 0, 10);

			retval = simple_observe(couchbase_res->handle, &entry, 1,
									persist_to, replicate_to);
			couchbase_res->rc = retval;
			if (retval != LCB_SUCCESS) {
				if (retval == LCB_ETIMEDOUT) {
					zend_throw_exception(cb_timeout_exception,
										 "Timed out waiting for the objects to persist",
										 0 TSRMLS_CC);
				} else {
					char errmsg[512];
					snprintf(errmsg, sizeof(errmsg), "observe failed for: %s",
							 klen, key, lcb_strerror(couchbase_res->handle,
													 retval));
					zend_throw_exception(cb_lcb_exception, errmsg, 0 TSRMLS_CC);
				}
			} else {
				/* @todo checkfor timeout!!! */
				if (entry.mutated) {
					zend_throw_exception(cb_key_mutated_exception,
										 "The document was mutated",
										 0 TSRMLS_CC);
				}
			}
		}
	}
	efree(ctx);
}
Beispiel #22
0
PHP_COUCHBASE_LOCAL
void php_couchbase_store_impl(INTERNAL_FUNCTION_PARAMETERS, lcb_storage_t op, int multi)
{
	lcb_error_t retval;
	php_couchbase_res *couchbase_res;
	php_couchbase_ctx *ctx;
	time_t exp = {0};
	unsigned int flags = 0;
	char *payload, *cas = NULL;
	size_t payload_len = 0;
	unsigned long long cas_v = 0;
	long expire = 0, cas_len = 0;
	char *key = NULL;

	if (!multi) {
		char *key = NULL;
		zval *value;
		long klen = 0;
		PHP_COUCHBASE_GET_PARAMS(couchbase_res,
								 PHP_COUCHBASE_ARG_F_FUNCTIONAL,
								 "sz|ls",
								 &key, &klen,
								 &value,
								 &expire,
								 &cas, &cas_len);

		if (pcbc_check_expiry(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0,
							  expire, &exp) == -1) {
			/* Incorrect expiry time */
			return;
		}

		if (!klen) {
			couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0,
								   cb_illegal_key_exception,
								   "No key specified: Empty key");
			return;
		}

		if (cas) {
			char *e;
			cas_v = (lcb_cas_t)strtoull(cas, &e, 10);
			if (*e != '\0') {
				couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0,
									   cb_illegal_key_exception,
									   "Invalid CAS specified");
				return;
			}
		}

		payload = php_couchbase_zval_to_payload(value, &payload_len,
												&flags,
												couchbase_res->serializer,
												couchbase_res->compressor
												TSRMLS_CC);
		if (payload == NULL) {
			RETURN_FALSE;
		}

		if (couchbase_res->prefix_key_len) {
			klen = spprintf(&key, 0, "%s_%s", couchbase_res->prefix_key, key);
		}

		ctx = ecalloc(1, sizeof(php_couchbase_ctx));
		ctx->res = couchbase_res;
		ctx->rv	 = return_value;
		couchbase_res->seqno += 1;

		{
			lcb_store_cmd_t cmd;
			lcb_store_cmd_t *commands[] = { &cmd };
			memset(&cmd, 0, sizeof(cmd));
			cmd.v.v0.operation = op;
			cmd.v.v0.key = key;
			cmd.v.v0.nkey = klen;
			cmd.v.v0.bytes = payload;
			cmd.v.v0.nbytes = payload_len;
			cmd.v.v0.flags = flags;
			cmd.v.v0.exptime = exp;
			cmd.v.v0.cas = (uint64_t)cas_v;

			retval = lcb_store(couchbase_res->handle, ctx,
							   1, (const lcb_store_cmd_t * const *)commands);
		}

		efree(payload);
		if (couchbase_res->prefix_key_len) {
			efree(key);
		}
		if (LCB_SUCCESS != retval) {
			efree(ctx);
			couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0,
								   cb_lcb_exception,
								   "Failed to schedule set request: %s",
								   lcb_strerror(couchbase_res->handle, retval));
			return;
		}

	} else { /* multi */
		zval *akeys, **ppzval;
		char *key = NULL;
		uint klen = 0;
		ulong idx;
		int key_type, nkey = 0;

		PHP_COUCHBASE_GET_PARAMS(couchbase_res,
								 PHP_COUCHBASE_ARG_F_FUNCTIONAL,
								 "a|l",
								 &akeys, &expire);

		if (pcbc_check_expiry(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0,
							  expire, &exp) == -1) {
			/* Incorrect expiry time */
			return;
		}

		ctx = ecalloc(1, sizeof(php_couchbase_ctx));
		ctx->res = couchbase_res;
		ctx->rv	 = return_value;
		array_init(ctx->rv);

		for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(akeys));
				zend_hash_has_more_elements(Z_ARRVAL_P(akeys)) == SUCCESS;
				zend_hash_move_forward(Z_ARRVAL_P(akeys))) {
			if (zend_hash_get_current_data(Z_ARRVAL_P(akeys), (void **)&ppzval) == FAILURE) {
				continue;
			}
			switch ((key_type = zend_hash_get_current_key(Z_ARRVAL_P(akeys), &key, &idx, 0))) {
			case HASH_KEY_IS_LONG:
				spprintf(&key, 0, "%ld", idx);
				break;
			case HASH_KEY_IS_STRING:
				break;
			default:
				continue;
			}

			if (!(klen = strlen(key))) {
				continue;
			}

			payload = php_couchbase_zval_to_payload(*ppzval, &payload_len,
													&flags,
													couchbase_res->serializer,
													couchbase_res->compressor
													TSRMLS_CC);
			if (payload == NULL) {
				RETURN_FALSE;
			}

			if (couchbase_res->prefix_key_len) {
				char *new_key;
				klen = spprintf(&new_key, 0, "%s_%s", couchbase_res->prefix_key, key);
				if (key_type == HASH_KEY_IS_LONG) {
					efree(key);
				}
				key = new_key;
			}

			{
				lcb_store_cmd_t cmd;
				lcb_store_cmd_t *commands[] = { &cmd };
				memset(&cmd, 0, sizeof(cmd));
				cmd.v.v0.operation = op;
				cmd.v.v0.key = key;
				cmd.v.v0.nkey = klen;
				cmd.v.v0.bytes = payload;
				cmd.v.v0.nbytes = payload_len;
				cmd.v.v0.flags = flags;
				cmd.v.v0.exptime = exp;

				retval = lcb_store(couchbase_res->handle, ctx,
								   1, (const lcb_store_cmd_t * const *)commands);
			}

			efree(payload);
			if (couchbase_res->prefix_key_len || HASH_KEY_IS_LONG == key_type) {
				efree(key);
			}
			if (LCB_SUCCESS != retval) {
				efree(ctx);
				couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0,
									   cb_lcb_exception,
									   "Failed to schedule set request: %s",
									   lcb_strerror(couchbase_res->handle,
													retval));
				return;
			}
			nkey++;
		}
		if (!nkey) {
			efree(ctx);
			return;
		}
		couchbase_res->seqno += nkey;
	}
	{
		pcbc_start_loop(couchbase_res);
		if (IS_ARRAY != Z_TYPE_P(return_value)) {
			if (LCB_SUCCESS != ctx->res->rc) {
				RETVAL_FALSE;
				switch (op) {
				case LCB_ADD:
					if (LCB_KEY_EEXISTS == ctx->res->rc) {
						break;
					}
				case LCB_APPEND:
				case LCB_PREPEND:
					if (LCB_NOT_STORED == ctx->res->rc) {
						break;
					}
				case LCB_REPLACE:
				case LCB_SET:
					if (LCB_KEY_ENOENT == ctx->res->rc) {
						break;
					}
					if (cas && LCB_KEY_EEXISTS == ctx->res->rc) {
						break;
					}
				default:
					couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0,
										   cb_lcb_exception,
										   "Failed to store a value to server: %s",
										   lcb_strerror(couchbase_res->handle,
														ctx->res->rc));
					break;
				}
			}
		}

		efree(ctx);
	}
}
ngx_int_t
ngx_lcb_process(ngx_http_request_t *r)
{
    lcb_error_t err = LCB_NOT_SUPPORTED;
    ngx_http_variable_value_t *vv;
    ngx_str_t key, val;
    enum ngx_lcb_cmd opcode;
    ngx_http_core_loc_conf_t *clcf;
    ngx_lcb_connection_t *conn;
    lcb_cas_t cas = 0;
    lcb_uint32_t flags = 0, exptime = 0;
    ngx_int_t need_free_value = 0;

    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
    conn = ngx_http_get_couchbase_connection(clcf->name);
    if (conn == NULL) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                      "couchbase: connection not found: \"%V\"", &clcf->name);
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    /* setup command: use variable or fallback to HTTP method */
    vv = ngx_http_get_indexed_variable(r, ngx_lcb_cmd_idx);
    if (vv == NULL) {
        ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }
    if (vv->not_found || vv->len == 0) {
        if (r->method & (NGX_HTTP_GET | NGX_HTTP_HEAD)) {
            opcode = ngx_lcb_cmd_get;
        } else if (r->method == NGX_HTTP_POST) {
            opcode = ngx_lcb_cmd_add;
        } else if (r->method == NGX_HTTP_PUT) {
            opcode = ngx_lcb_cmd_set;
        } else if (r->method == NGX_HTTP_DELETE) {
            opcode = ngx_lcb_cmd_delete;
        } else {
            ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
                          "ngx_memc: $memc_cmd variable requires explicit "
                          "assignment for HTTP request method %V",
                          &r->method_name);
            ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
            return NGX_HTTP_BAD_REQUEST;
        }
    } else {
        if (ngx_strncmp(vv->data, "get", 3) == 0) {
            opcode = ngx_lcb_cmd_get;
        } else if (ngx_strncmp(vv->data, "add", 3) == 0) {
            opcode = ngx_lcb_cmd_add;
        } else if (ngx_strncmp(vv->data, "replace", 7) == 0) {
            opcode = ngx_lcb_cmd_replace;
        } else if (ngx_strncmp(vv->data, "set", 3) == 0) {
            opcode = ngx_lcb_cmd_set;
        } else if (ngx_strncmp(vv->data, "append", 6) == 0) {
            opcode = ngx_lcb_cmd_append;
        } else if (ngx_strncmp(vv->data, "prepend", 7) == 0) {
            opcode = ngx_lcb_cmd_prepend;
        } else if (ngx_strncmp(vv->data, "delete", 6) == 0) {
            opcode = ngx_lcb_cmd_delete;
        } else {
            ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
                          "ngx_memc: unknown $couchbase_cmd \"%v\"", vv);
            ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
            return NGX_HTTP_BAD_REQUEST;
        }
    }

    /* setup key: use variable or fallback to URI */
    vv = ngx_http_get_indexed_variable(r, ngx_lcb_key_idx);
    if (vv == NULL) {
        ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }
    if (vv->not_found || vv->len == 0) {
        size_t loc_len;

        loc_len = r->valid_location ? clcf->name.len : 0;
        key.data = r->uri.data + loc_len;
        key.len = r->uri.len - loc_len;
    } else {
        u_char *dst, *src;
        key.data = ngx_palloc(r->pool, vv->len);
        if (key.data == NULL) {
            ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
            return NGX_HTTP_INTERNAL_SERVER_ERROR;
        }
        dst = key.data;
        src = vv->data;
        ngx_unescape_uri(&dst, &src, vv->len, 0);
        *dst = 0;
        key.len = dst - key.data;
    }

    /* setup value: use variable or fallback to HTTP body */
    ngx_str_null(&val);
    if (opcode >= ngx_lcb_cmd_add && opcode <= ngx_lcb_cmd_prepend) {
        vv = ngx_http_get_indexed_variable(r, ngx_lcb_val_idx);
        if (vv == NULL) {
            ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
            return NGX_HTTP_INTERNAL_SERVER_ERROR;
        }
        if (vv->not_found || vv->len == 0) {
            if (r->request_body == NULL || r->request_body->bufs == NULL) {
                ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                              "neither the \"$couchbase_value\" variable "
                              "nor the request body is available");
                ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
                return NGX_HTTP_BAD_REQUEST;
            } else {
                /* copy body to the buffer */
                ngx_chain_t *cl;
                u_char *p;

                val.len = 0;
                for (cl = r->request_body->bufs; cl; cl = cl->next) {
                    val.len += ngx_buf_size(cl->buf);
                }
                p = val.data = ngx_palloc(r->pool, val.len);
                if (p == NULL) {
                    ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
                    return NGX_HTTP_INTERNAL_SERVER_ERROR;
                }
                for (cl = r->request_body->bufs; cl; cl = cl->next) {
                    p = ngx_copy(p, cl->buf->pos, cl->buf->last - cl->buf->pos);
                }
                vv = NULL;
            }
        } else {
            u_char *dst, *src;
            val.data = ngx_palloc(r->pool, vv->len);
            if (val.data == NULL) {
                ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
                return NGX_HTTP_INTERNAL_SERVER_ERROR;
            }
            need_free_value = 1;
            dst = val.data;
            src = vv->data;
            ngx_unescape_uri(&dst, &src, vv->len, 0);
            *dst = 0;
            val.len = dst - val.data;
        }
    }

    /* setup CAS value */
    vv = ngx_http_get_indexed_variable(r, ngx_lcb_cas_idx);
    if (vv == NULL) {
        ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }
    if (!vv->not_found && vv->len > 0) {
        if (ngx_lcb_atocas(vv->data, vv->len, &cas) != NGX_OK) {
            ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
            return NGX_HTTP_BAD_REQUEST;
        }
    }

    /* setup flags value */
    vv = ngx_http_get_indexed_variable(r, ngx_lcb_flags_idx);
    if (vv == NULL) {
        ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }
    if (!vv->not_found && vv->len > 0) {
        flags = ngx_atoi(vv->data, vv->len);
    }

    /* setup expiration value */
    vv = ngx_http_get_indexed_variable(r, ngx_lcb_exptime_idx);
    if (vv == NULL) {
        ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }
    if (!vv->not_found && vv->len > 0) {
        exptime = ngx_atoi(vv->data, vv->len);
    }

    switch (opcode) {
    case ngx_lcb_cmd_get: {
        lcb_get_cmd_t cmd;
        const lcb_get_cmd_t *commands[1];

        commands[0] = &cmd;
        memset(&cmd, 0, sizeof(cmd));
        cmd.v.v0.key = key.data;
        cmd.v.v0.nkey = key.len;
        cmd.v.v0.exptime = exptime;
        err = lcb_get(conn->lcb, r, 1, commands);
        ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                       "couchbase(%p): get request \"%*s\"",
                       (void *)conn->lcb, cmd.v.v0.nkey, cmd.v.v0.key);
    }
    break;
    case ngx_lcb_cmd_add:
    case ngx_lcb_cmd_replace:
    case ngx_lcb_cmd_set:
    case ngx_lcb_cmd_append:
    case ngx_lcb_cmd_prepend: {
        lcb_store_cmd_t cmd;
        const lcb_store_cmd_t *commands[1];

        commands[0] = &cmd;
        memset(&cmd, 0, sizeof(cmd));

        cmd.v.v0.operation = opcode;
        cmd.v.v0.key = key.data;
        cmd.v.v0.nkey = key.len;
        cmd.v.v0.bytes = val.data;
        cmd.v.v0.nbytes = val.len;
        cmd.v.v0.cas = cas;
        cmd.v.v0.flags = flags;
        cmd.v.v0.exptime = exptime;
        err = lcb_store(conn->lcb, r, 1, commands);
        ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                       "couchbase(%p): store request \"%*s\", operation: 0x%02xd",
                       (void *)conn->lcb, cmd.v.v0.nkey, cmd.v.v0.key, cmd.v.v0.operation);
    }
    break;
    case ngx_lcb_cmd_delete: {
        lcb_remove_cmd_t cmd;
        const lcb_remove_cmd_t *commands[1];

        commands[0] = &cmd;
        memset(&cmd, 0, sizeof(cmd));
        cmd.v.v0.key = key.data;
        cmd.v.v0.nkey = key.len;
        err = lcb_remove(conn->lcb, r, 1, commands);
        ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                       "couchbase(%p): remove request \"%*s\"",
                       (void *)conn->lcb, cmd.v.v0.nkey, cmd.v.v0.key);
    }
    break;
    }
    if (need_free_value) {
        ngx_pfree(r->pool, val.data);
    }
    if (err != LCB_SUCCESS) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                      "couchbase: failed to schedule couchbase request: %s",
                      lcb_strerror(conn->lcb, err));
        ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
        return NGX_ERROR;
    }
    return NGX_OK;
}
Beispiel #24
0
int main(int argc, char *argv[])
{
    lcb_error_t err;
    lcb_t instance;
    struct lcb_create_st create_options;
    struct lcb_create_io_ops_st io_opts;

    io_opts.version = 0;
    io_opts.v.v0.type = LCB_IO_OPS_DEFAULT;
    io_opts.v.v0.cookie = NULL;

    memset(&create_options, 0, sizeof(create_options));
    err = lcb_create_io_ops(&create_options.v.v0.io, &io_opts);
    if (err != LCB_SUCCESS) {
        fprintf(stderr, "Failed to create IO instance: %s\n",
                lcb_strerror(NULL, err));
        return 1;
    }

    if (argc > 1) {
        create_options.v.v0.host = argv[1];
    }
    if (argc > 2) {
        create_options.v.v0.user = argv[2];
        create_options.v.v0.bucket = argv[2];
    }
    if (argc > 3) {
        create_options.v.v0.passwd = argv[3];
    }
    err = lcb_create(&instance, &create_options);
    if (err != LCB_SUCCESS) {
        fprintf(stderr, "Failed to create libcouchbase instance: %s\n",
                lcb_strerror(NULL, err));
        return 1;
    }
    (void)lcb_set_error_callback(instance, error_callback);
    /* Initiate the connect sequence in libcouchbase */
    if ((err = lcb_connect(instance)) != LCB_SUCCESS) {
        fprintf(stderr, "Failed to initiate connect: %s\n",
                lcb_strerror(NULL, err));
        lcb_destroy(instance);
        return 1;
    }
    (void)lcb_set_get_callback(instance, get_callback);
    (void)lcb_set_store_callback(instance, store_callback);
    /* Run the event loop and wait until we've connected */
    lcb_wait(instance);
    {
        lcb_store_cmd_t cmd;
        const lcb_store_cmd_t *commands[1];

        commands[0] = &cmd;
        memset(&cmd, 0, sizeof(cmd));
        cmd.v.v0.operation = LCB_SET;
        cmd.v.v0.key = "foo";
        cmd.v.v0.nkey = 3;
        cmd.v.v0.bytes = "bar";
        cmd.v.v0.nbytes = 3;
        err = lcb_store(instance, NULL, 1, commands);
        if (err != LCB_SUCCESS) {
            fprintf(stderr, "Failed to store: %s\n", lcb_strerror(NULL, err));
            return 1;
        }
    }
    lcb_wait(instance);
    {
        lcb_get_cmd_t cmd;
        const lcb_get_cmd_t *commands[1];
        commands[0] = &cmd;
        memset(&cmd, 0, sizeof(cmd));
        cmd.v.v0.key = "foo";
        cmd.v.v0.nkey = 3;
        err = lcb_get(instance, NULL, 1, commands);
        if (err != LCB_SUCCESS) {
            fprintf(stderr, "Failed to get: %s\n", lcb_strerror(NULL, err));
            return 1;
        }
    }
    lcb_wait(instance);
    lcb_destroy(instance);

    return 0;
}