// 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; }
// 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; }