Example #1
0
// Put batch request on a separate batch queue.
int
as_batch(as_transaction* tr)
{
	as_msg* msg = &tr->msgp->msg;

	as_msg_field* nsfp = as_msg_field_get(msg, AS_MSG_FIELD_TYPE_NAMESPACE);
	if (! nsfp) {
		cf_warning(AS_BATCH, "Batch namespace is required.");
		return -1;
	}

	as_msg_field* dfp = as_msg_field_get(msg, AS_MSG_FIELD_TYPE_DIGEST_RIPE_ARRAY);
	if (! dfp) {
		cf_warning(AS_BATCH, "Batch digests are required.");
		return -1;
	}

	uint n_digests = dfp->field_sz / sizeof(cf_digest);

	if (n_digests > g_config.batch_max_requests) {
		cf_warning(AS_BATCH, "Batch request size %u exceeds max %u.", n_digests, g_config.batch_max_requests);
		return -1;
	}

	batch_transaction btr;
	btr.trid = tr->trid;
	btr.end_time = tr->end_time;
	btr.get_data = !(msg->info1 & AS_MSG_INFO1_GET_NOBINDATA);

	btr.ns = as_namespace_get_bymsgfield(nsfp);
	if (! btr.ns) {
		cf_warning(AS_BATCH, "Batch namespace is required.");
		return -1;
	}

	// Create the master digest table.
	btr.digests = (batch_digests*) cf_malloc(sizeof(batch_digests) + (sizeof(batch_digest) * n_digests));
	if (! btr.digests) {
		cf_warning(AS_BATCH, "Failed to allocate memory for batch digests.");
		return -1;
	}

	batch_digests* bmd = btr.digests;
	bmd->n_digests = n_digests;
	uint8_t* digest_field_data = dfp->data;

	for (int i = 0; i < n_digests; i++) {
		bmd->digest[i].done = false;
		bmd->digest[i].node = 0;
		memcpy(&bmd->digest[i].keyd, digest_field_data, sizeof(cf_digest));
		digest_field_data += sizeof(cf_digest);
	}

	btr.binlist = as_binlist_from_op(msg);
	btr.fd_h = tr->proto_fd_h;
	tr->proto_fd_h = 0;
	btr.fd_h->last_used = cf_getms();

	cf_atomic_int_incr(&g_config.batch_initiate);
	cf_queue_push(g_batch_queue, &btr);
	return 0;
}
Example #2
0
// Put batch request on a separate batch queue.
int
as_batch_direct_queue_task(as_transaction* tr)
{
	cf_atomic_int_incr(&g_config.batch_initiate);

	if (g_config.n_batch_threads <= 0) {
		cf_warning(AS_BATCH, "batch-threads has been disabled.");
		return AS_PROTO_RESULT_FAIL_BATCH_DISABLED;
	}

	as_msg* msg = &tr->msgp->msg;

	as_msg_field* nsfp = as_msg_field_get(msg, AS_MSG_FIELD_TYPE_NAMESPACE);
	if (! nsfp) {
		cf_warning(AS_BATCH, "Batch namespace is required.");
		return AS_PROTO_RESULT_FAIL_NAMESPACE;
	}

	as_msg_field* dfp = as_msg_field_get(msg, AS_MSG_FIELD_TYPE_DIGEST_RIPE_ARRAY);
	if (! dfp) {
		cf_warning(AS_BATCH, "Batch digests are required.");
		return AS_PROTO_RESULT_FAIL_PARAMETER;
	}

	uint n_digests = dfp->field_sz / sizeof(cf_digest);

	if (n_digests > g_config.batch_max_requests) {
		cf_warning(AS_BATCH, "Batch request size %u exceeds max %u.", n_digests, g_config.batch_max_requests);
		return AS_PROTO_RESULT_FAIL_BATCH_MAX_REQUESTS;
	}

	batch_transaction btr;
	btr.trid = tr->trid;
	btr.end_time = tr->end_time;
	btr.get_data = !(msg->info1 & AS_MSG_INFO1_GET_NOBINDATA);
	btr.complete = false;

	btr.ns = as_namespace_get_bymsgfield(nsfp);
	if (! btr.ns) {
		cf_warning(AS_BATCH, "Batch namespace is required.");
		return AS_PROTO_RESULT_FAIL_NAMESPACE;
	}

	// Create the master digest table.
	btr.digests = (batch_digests*) cf_malloc(sizeof(batch_digests) + (sizeof(batch_digest) * n_digests));
	if (! btr.digests) {
		cf_warning(AS_BATCH, "Failed to allocate memory for batch digests.");
		return AS_PROTO_RESULT_FAIL_UNKNOWN;
	}

	batch_digests* bmd = btr.digests;
	bmd->n_digests = n_digests;
	uint8_t* digest_field_data = dfp->data;

	for (int i = 0; i < n_digests; i++) {
		bmd->digest[i].done = false;
		bmd->digest[i].node = 0;
		memcpy(&bmd->digest[i].keyd, digest_field_data, sizeof(cf_digest));
		digest_field_data += sizeof(cf_digest);
	}

	btr.binlist = as_binlist_from_op(msg);
	btr.fd_h = tr->proto_fd_h;
	tr->proto_fd_h = 0;
	btr.fd_h->last_used = cf_getms();

	int status = as_thread_pool_queue_task_fixed(&batch_direct_thread_pool, &btr);
	
	if (status) {
		cf_warning(AS_BATCH, "Batch enqueue failed");
		return AS_PROTO_RESULT_FAIL_UNKNOWN;		
	}
	return 0;
}