예제 #1
0
/*
 * Code to init the fields in a transaction.  Use this instead of memset.
 *
 * NB: DO NOT SHUFFLE INIT ORDER .. it is based on elements found in the
 *     structure.
 */
void
as_transaction_init(as_transaction *tr, cf_digest *keyd, cl_msg *msgp)
{
	tr->msgp                      = msgp;
	if (keyd) {
		tr->keyd                  = *keyd;
		tr->preprocessed          = true;
	} else {
		tr->keyd                  = cf_digest_zero;
		tr->preprocessed          = false;
	}
	tr->flag                      = 0;
	tr->generation                = 0;
	tr->result_code               = AS_PROTO_RESULT_OK;
	tr->proto_fd_h                = 0;
	tr->start_time                = cf_getns();
	tr->end_time                  = 0;

	AS_PARTITION_RESERVATION_INIT(tr->rsv);

	tr->microbenchmark_time       = 0;
	tr->microbenchmark_is_resolve = false;

	tr->proxy_node                = 0;
	tr->proxy_msg                 = 0;

	UREQ_DATA_INIT(&tr->udata);

	tr->batch_shared              = 0;
	tr->batch_index               = 0;

	tr->void_time                 = 0;
}
예제 #2
0
// Build response to batch request.
static void
batch_build_response(batch_transaction* btr, cf_buf_builder** bb_r)
{
	as_namespace* ns = btr->ns;
	batch_digests *bmds = btr->digests;
	bool get_data = btr->get_data;
	uint32_t yield_count = 0;

	for (int i = 0; i < bmds->n_digests; i++)
	{
		batch_digest *bmd = &bmds->digest[i];

		if (bmd->done == false) {
			// try to get the key
			as_partition_reservation rsv;
			AS_PARTITION_RESERVATION_INIT(rsv);
			cf_node other_node = 0;
			uint64_t cluster_key;

			if (! *bb_r) {
				*bb_r = cf_buf_builder_create_size(1024 * 4);
			}

			int rv = as_partition_reserve_read(ns, as_partition_getid(bmd->keyd), &rsv, &other_node, &cluster_key);

			if (rv == 0) {
				cf_atomic_int_incr(&g_config.batch_tree_count);

				as_index_ref r_ref;
				r_ref.skip_lock = false;
				int rec_rv = as_record_get(rsv.tree, &bmd->keyd, &r_ref, ns);

				if (rec_rv == 0) {
					as_index *r = r_ref.r;

					// Check to see this isn't an expired record waiting to die.
					if (r->void_time && r->void_time < as_record_void_time_get()) {
						as_msg_make_error_response_bufbuilder(&bmd->keyd, AS_PROTO_RESULT_FAIL_NOTFOUND, bb_r, ns->name);
					}
					else {
						// Make sure it's brought in from storage if necessary.
						as_storage_rd rd;
						if (get_data) {
							as_storage_record_open(ns, r, &rd, &r->key);
							rd.n_bins = as_bin_get_n_bins(r, &rd);
						}

						// Note: this array must stay in scope until the
						// response for this record has been built, since in the
						// get data w/ record on device case, it's copied by
						// reference directly into the record descriptor.
						as_bin stack_bins[!get_data || rd.ns->storage_data_in_memory ? 0 : rd.n_bins];

						if (get_data) {
							// Figure out which bins you want - for now, all.
							rd.bins = as_bin_get_all(r, &rd, stack_bins);
							rd.n_bins = as_bin_inuse_count(&rd);
						}

						as_msg_make_response_bufbuilder(r, (get_data ? &rd : NULL), bb_r, !get_data, (get_data ? NULL : ns->name), true, false, btr->binlist);

						if (get_data) {
							as_storage_record_close(r, &rd);
						}
					}
					as_record_done(&r_ref, ns);
				}
				else {
					// TODO - what about empty records?
					cf_debug(AS_BATCH, "batch_build_response: as_record_get returned %d : key %"PRIx64, rec_rv, *(uint64_t *)&bmd->keyd);
					as_msg_make_error_response_bufbuilder(&bmd->keyd, AS_PROTO_RESULT_FAIL_NOTFOUND, bb_r, ns->name);
				}

				bmd->done = true;

				as_partition_release(&rsv);
				cf_atomic_int_decr(&g_config.batch_tree_count);
			}
			else {
				cf_debug(AS_BATCH, "batch_build_response: partition reserve read failed: rv %d", rv);

				as_msg_make_error_response_bufbuilder(&bmd->keyd, AS_PROTO_RESULT_FAIL_NOTFOUND, bb_r, ns->name);

				if (other_node != 0) {
					bmd->node = other_node;
					cf_debug(AS_BATCH, "other_node is: %p.", other_node);
				} else {
					cf_debug(AS_BATCH, "other_node is NULL.");
				}
			}

			yield_count++;
			if (yield_count % g_config.batch_priority == 0) {
				usleep(1);
			}
		}
	}
}
예제 #3
0
/* Create an internal transaction.
 * parameters:
 *     tr_create_data : Details for creating transaction
 *     tr             : to be filled
 *
 * return :  0  on success
 *           -1 on failure
 */
int
as_transaction_create_internal(as_transaction *tr, tr_create_data *  trc_data)
{
	tr_create_data * d = (tr_create_data*) trc_data;

	// Get Defensive 
	memset(tr, 0, sizeof(as_transaction));

	if (d->fd_h) {
		cf_warning(AS_PROTO, "Foreground Internal Transation .. Ignoring");
		return -1;
	} else {
		tr->proto_fd_h = NULL;
	}

	tr->start_time   = cf_getns();
	tr->flag         = AS_TRANSACTION_FLAG_INTERNAL;
	tr->keyd         = d->digest;
	tr->preprocessed = true;
	tr->result_code  = AS_PROTO_RESULT_OK;

	AS_PARTITION_RESERVATION_INIT(tr->rsv);
	UREQ_DATA_INIT(&tr->udata);

	// Get namespace and set lengths.
	int ns_len        = strlen(d->ns->name);
	int set_len       = strlen(d->set);

	// Figure out the size of the message.
	size_t  msg_sz = sizeof(cl_msg);

	msg_sz += sizeof(as_msg_field) + ns_len;

	if (set_len != 0) {
		msg_sz += sizeof(as_msg_field) + set_len;
	}

	msg_sz += sizeof(as_msg_field) + sizeof(cf_digest);
	msg_sz += sizeof(as_msg_field) + sizeof(d->trid);

	// Udf call structure will go as a part of the transaction udata.
	// Do not pack it in the message.
	cf_debug(AS_PROTO, "UDF : Msg size for internal transaction is %d", msg_sz);

	// Allocate space in the buffer.
	uint8_t * buf   = cf_malloc(msg_sz); memset(buf, 0, msg_sz);
	if (!buf) {
		return -1;
	}
	uint8_t * buf_r = buf;

	// Calculation of number of fields:
	// n_fields = ( ns ? 1 : 0 ) + (set ? 1 : 0) + (digest ? 1 : 0) + (trid ? 1 : 0) + (call ? 3 : 0);

	// Write the header in case the request gets proxied. Is it enough ??
	buf = as_msg_write_header(buf, msg_sz, 0, d->msg_type, 0, 0, 0, 0, 2 /*n_fields*/, 0);
	buf = as_msg_write_fields(buf, d->ns->name, ns_len, d->set, set_len, &(d->digest), 0, 0 , 0, 0);

	tr->msgp         = (cl_msg *) buf_r;

	return 0;
}