EXPORT RM_ENTRY(rmc_start_transaction) { ClearParamPool(); ISC_STATUS *stat = AllocStatusPool(); short* dbCount = (short *)CobolToShort(&arg_vector[2]); // Create the transaction existence block from the Cobol parameter list. Because // of limits imposed by the converted parameter pool we can ony support up to // MAX_PARAMS transactions. if (*dbCount > MAX_PARAMS) *dbCount = MAX_PARAMS; ISC_TEB *teb = (ISC_TEB *)malloc(sizeof(ISC_TEB) * *dbCount); for (int i = 0; i < *dbCount; i++) { teb[i].dbb_ptr = (isc_db_handle *)arg_vector[(i * 3) + 3].a_address; teb[i].tpb_len = (int)*CobolToInt(&arg_vector[(i * 3) + 4]); teb[i].tpb_ptr = arg_vector[(i * 3) + 5].a_address; } isc_start_multiple(stat, (isc_tr_handle *)arg_vector[1].a_address, *dbCount, teb); free(teb); StatusToCobol(&arg_vector[0], stat); return (0); }
ISC_STATUS API_ROUTINE_VARARG gds__start_transaction(ISC_STATUS* status_vector, FB_API_HANDLE* tra_handle, SSHORT count, ...) { // This infamous structure is defined several times in different places struct teb_t { FB_API_HANDLE* teb_database; int teb_tpb_length; UCHAR* teb_tpb; }; teb_t tebs[16]; teb_t* teb = tebs; if (count > FB_NELEM(tebs)) teb = (teb_t*) gds__alloc(((SLONG) sizeof(teb_t) * count)); // FREE: later in this module if (!teb) { // NOMEM: status_vector[0] = isc_arg_gds; status_vector[1] = isc_virmemexh; status_vector[2] = isc_arg_end; return status_vector[1]; } const teb_t* const end = teb + count; va_list ptr; va_start(ptr, count); for (teb_t* teb_iter = teb; teb_iter < end; ++teb_iter) { teb_iter->teb_database = va_arg(ptr, FB_API_HANDLE*); teb_iter->teb_tpb_length = va_arg(ptr, int); teb_iter->teb_tpb = va_arg(ptr, UCHAR *); } va_end(ptr); const ISC_STATUS status = isc_start_multiple(status_vector, tra_handle, count, teb); if (teb != tebs) gds__free(teb); return status; }
ISC_STATUS API_ROUTINE gds__start_multiple(ISC_STATUS * status_vector, FB_API_HANDLE* tra_handle, SSHORT db_count, void *teb_vector) { return isc_start_multiple(status_vector, tra_handle, db_count, (SCHAR*) teb_vector); }