// come back with a fin response pack_and_data_t *process_client_fin(pack_and_data_t *pin) { packet_head_t *fin_pkt = pin->ph; uint32_t cid = fin_pkt->card_id; uint32_t acd = fin_pkt->auth_code; uint32_t txn_id = fin_pkt->transaction_id; account_entry_t * ae = get_account(cid, acd); if(ae == NULL) { ERRNO = ERRNO_MP_NOT_FOUND; return NULL; } txn_entry_t * te = get_transaction(ae, txn_id); if(te == NULL) { // err no set by get_txn return NULL; } if(finalize_transaction(te) != OK) { // finalize transaction sets huge errno for double fin return NULL; } return create_basic_response(cid, acd, txn_id, FIN, fin_pkt->op_code, OK, 0); }
acct_txn_entry_t * get_acct_txn_reg(uint32_t cid, uint32_t acd, uint32_t txn_id) { account_entry_t * ae = get_account(cid, acd); if(ae == NULL) { ERRNO = ERRNO_MP_NOT_FOUND; return NULL; } txn_entry_t * te = get_transaction(ae, txn_id); if(te == NULL) { ERRNO = ERRNO_MP_NOT_FOUND; return NULL; } acct_txn_entry_t *aet = (acct_txn_entry_t *) malloc(sizeof(acct_txn_entry_t)); if(aet == NULL) { ERRNO = ERRNO_MP_ALLOC; return NULL; } aet->ae = ae; aet->txn = te; return aet; };
// set last message, from transaction or default if none specified. msg_index is used for error reporting only void DialogState::setLastReceivedMessage(const string &msg, const string &name, int msg_index) { DEBUG_IN("name = '%s' Message Length = %d", name.c_str(), msg.length()); // set default transactions's last message { TransactionState &txn = get_transaction("", msg_index); txn.setLastReceivedMessage(msg); } // set per-transaction message if (!name.empty()) { TransactionState &txn = get_transaction(name, msg_index); txn.setLastReceivedMessage(msg); DEBUG("Set last message for transaction %s", name.c_str()); } }
bool leveldb_common::duplicate_exists(const hash_digest& tx_hash, uint32_t block_height, uint32_t tx_index) { leveldb_tx_info tx; if (!get_transaction(tx, tx_hash, false, false)) return false; BITCOIN_ASSERT(block_height == 91842 || block_height == 91880); return true; }
pack_and_data_t * process_client_refund_op(pack_and_data_t * pin) { packet_head_t *rf_pkt = pin->ph; packet_data_refund_t *rcd = pin->data; uint32_t cid = rf_pkt->card_id; uint32_t acd = rf_pkt->auth_code; uint32_t txn_id = rf_pkt->transaction_id; acct_txn_entry_t * aet = get_acct_txn_reg(cid, acd, txn_id); if(aet == NULL) { return NULL; } txn_entry_t * ref_txn = get_transaction(aet->ae, rcd->transaction_id); if(ref_txn == NULL) { ERRNO = ERRNO_MP_NOT_FOUND; return NULL; } packet_data_purchase_t *log_pur_data = ref_txn->data; #if PATCHED if(log_pur_data == NULL) { return NULL; } #endif if(log_pur_data->purchase_id != rcd->purchase_id) { // the purchase id refund request doesn't match up... ERRNO = ERRNO_MP_NOT_FOUND; return NULL; } uint32_t proposed_post_refund = aet->ae->balance + log_pur_data->cost; if(proposed_post_refund <= 0xFFFFFFFF && proposed_post_refund >= aet->ae->balance) { aet->ae->balance = proposed_post_refund; } else { ERRNO = ERRNO_MP_REFUND_FULL; return NULL; } add_transaction_log_entry(aet->ae, pin); remove_transaction_log_entry(aet->ae,ref_txn); free(aet); return create_basic_response(cid, acd, txn_id, OPS, REFUND, OK, 0); }
txn_entry_t * add_transaction_log_entry(account_entry_t * ae, pack_and_data_t *pad){ // we parse packet header here, again, and dump the whole transaction log into the linked list node packet_head_t *ph = pad->ph; void *txn_data = pad->data; txn_entry_t *le = get_transaction(ae, ph->transaction_id); if(le == NULL){ return NULL; } if(le->p == NULL) le->p = (packet_head_t *) malloc(sizeof(packet_head_t)); if(le->p == NULL) return NULL; // copy in original packet header and packet data ... cgc_memcpy(le->p, (void *) ph, sizeof(packet_head_t)); size_t data_sz = pad->pay_data_l; le->data_sz = data_sz; if(data_sz != 0){ le->data = malloc(data_sz); if(txn_data == NULL) return NULL; cgc_memcpy(le->data, txn_data, data_sz); } return le; }
// get last message, from transaction or default if none specified. msg_index is used for error reporting only const string &DialogState::getLastReceivedMessage(const string &name, int msg_index) { DEBUG_IN("name = %s", name.c_str()); TransactionState &txn = get_transaction(name, msg_index); return txn.getLastReceivedMessage(); }
static int start_this_handle(journal_t *journal, handle_t *handle) { transaction_t *transaction; int needed; int nblocks = handle->h_buffer_credits; transaction_t *new_transaction = NULL; int ret = 0; if (nblocks > journal->j_max_transaction_buffers) { printk(KERN_ERR "JBD: %s wants too many credits (%d > %d)\n", current->comm, nblocks, journal->j_max_transaction_buffers); ret = -ENOSPC; goto out; } alloc_transaction: if (!journal->j_running_transaction) { new_transaction = kzalloc(sizeof(*new_transaction), GFP_NOFS|__GFP_NOFAIL); if (!new_transaction) { ret = -ENOMEM; goto out; } } jbd_debug(3, "New handle %p going live.\n", handle); repeat: /* * We need to hold j_state_lock until t_updates has been incremented, * for proper journal barrier handling */ spin_lock(&journal->j_state_lock); repeat_locked: if (is_journal_aborted(journal) || (journal->j_errno != 0 && !(journal->j_flags & JFS_ACK_ERR))) { spin_unlock(&journal->j_state_lock); ret = -EROFS; goto out; } /* Wait on the journal's transaction barrier if necessary */ if (journal->j_barrier_count) { spin_unlock(&journal->j_state_lock); wait_event(journal->j_wait_transaction_locked, journal->j_barrier_count == 0); goto repeat; } if (!journal->j_running_transaction) { if (!new_transaction) { spin_unlock(&journal->j_state_lock); goto alloc_transaction; } get_transaction(journal, new_transaction); new_transaction = NULL; } transaction = journal->j_running_transaction; /* * If the current transaction is locked down for commit, wait for the * lock to be released. */ if (transaction->t_state == T_LOCKED) { DEFINE_WAIT(wait); prepare_to_wait(&journal->j_wait_transaction_locked, &wait, TASK_UNINTERRUPTIBLE); spin_unlock(&journal->j_state_lock); schedule(); finish_wait(&journal->j_wait_transaction_locked, &wait); goto repeat; } /* * If there is not enough space left in the log to write all potential * buffers requested by this operation, we need to stall pending a log * checkpoint to free some more log space. */ spin_lock(&transaction->t_handle_lock); needed = transaction->t_outstanding_credits + nblocks; if (needed > journal->j_max_transaction_buffers) { /* * If the current transaction is already too large, then start * to commit it: we can then go back and attach this handle to * a new transaction. */ DEFINE_WAIT(wait); jbd_debug(2, "Handle %p starting new commit...\n", handle); spin_unlock(&transaction->t_handle_lock); prepare_to_wait(&journal->j_wait_transaction_locked, &wait, TASK_UNINTERRUPTIBLE); __log_start_commit(journal, transaction->t_tid); spin_unlock(&journal->j_state_lock); schedule(); finish_wait(&journal->j_wait_transaction_locked, &wait); goto repeat; } /* * The commit code assumes that it can get enough log space * without forcing a checkpoint. This is *critical* for * correctness: a checkpoint of a buffer which is also * associated with a committing transaction creates a deadlock, * so commit simply cannot force through checkpoints. * * We must therefore ensure the necessary space in the journal * *before* starting to dirty potentially checkpointed buffers * in the new transaction. * * The worst part is, any transaction currently committing can * reduce the free space arbitrarily. Be careful to account for * those buffers when checkpointing. */ /* * @@@ AKPM: This seems rather over-defensive. We're giving commit * a _lot_ of headroom: 1/4 of the journal plus the size of * the committing transaction. Really, we only need to give it * committing_transaction->t_outstanding_credits plus "enough" for * the log control blocks. * Also, this test is inconsitent with the matching one in * journal_extend(). */ if (__log_space_left(journal) < jbd_space_needed(journal)) { jbd_debug(2, "Handle %p waiting for checkpoint...\n", handle); spin_unlock(&transaction->t_handle_lock); __log_wait_for_space(journal); goto repeat_locked; } /* OK, account for the buffers that this operation expects to * use and add the handle to the running transaction. */ handle->h_transaction = transaction; transaction->t_outstanding_credits += nblocks; transaction->t_updates++; transaction->t_handle_count++; jbd_debug(4, "Handle %p given %d credits (total %d, free %d)\n", handle, nblocks, transaction->t_outstanding_credits, __log_space_left(journal)); spin_unlock(&transaction->t_handle_lock); spin_unlock(&journal->j_state_lock); lock_map_acquire(&handle->h_lockdep_map); out: if (unlikely(new_transaction)) /* It's usually NULL */ kfree(new_transaction); return ret; }
static int start_this_handle(journal_t *journal, handle_t *handle) { transaction_t *transaction; int needed; int nblocks = handle->h_buffer_credits; jfs_debug(4, "New handle %p going live.\n", handle); repeat: lock_journal(journal); if ((journal->j_flags & JFS_ABORT) || (journal->j_errno != 0 && !(journal->j_flags & JFS_ACK_ERR))) { unlock_journal(journal); return -EROFS; } /* Wait on the journal's transaction barrier if necessary */ if (journal->j_barrier_count) { unlock_journal(journal); sleep_on(&journal->j_wait_transaction_locked); goto repeat; } repeat_locked: if (!journal->j_running_transaction) get_transaction(journal); /* @@@ Error? */ J_ASSERT(journal->j_running_transaction); transaction = journal->j_running_transaction; /* If the current transaction is locked down for commit, wait * for the lock to be released. */ if (transaction->t_state == T_LOCKED) { unlock_journal(journal); jfs_debug(3, "Handle %p stalling...\n", handle); sleep_on(&journal->j_wait_transaction_locked); goto repeat; } /* If there is not enough space left in the log to write all * potential buffers requested by this operation, we need to * stall pending a log checkpoint to free some more log * space. */ needed = transaction->t_outstanding_credits + nblocks; if (needed > journal->j_max_transaction_buffers) { /* If the current transaction is already too large, then * start to commit it: we can then go back and attach * this handle to a new transaction. */ jfs_debug(2, "Handle %p starting new commit...\n", handle); log_start_commit(journal, transaction); unlock_journal(journal); sleep_on(&journal->j_wait_transaction_locked); lock_journal(journal); goto repeat_locked; } /* * The commit code assumes that it can get enough log space * without forcing a checkpoint. This is *critical* for * correctness: a checkpoint of a buffer which is also * associated with a committing transaction creates a deadlock, * so commit simply cannot force through checkpoints. * * We must therefore ensure the necessary space in the journal * *before* starting to dirty potentially checkpointed buffers * in the new transaction. * * The worst part is, any transaction currently committing can * reduce the free space arbitrarily. Be careful to account for * those buffers when checkpointing. */ needed = journal->j_max_transaction_buffers; if (journal->j_committing_transaction) needed += journal->j_committing_transaction->t_outstanding_credits; if (log_space_left(journal) < needed) { jfs_debug(2, "Handle %p waiting for checkpoint...\n", handle); log_wait_for_space(journal, needed); goto repeat_locked; } /* OK, account for the buffers that this operation expects to * use and add the handle to the running transaction. */ handle->h_transaction = transaction; transaction->t_outstanding_credits += nblocks; transaction->t_updates++; jfs_debug(4, "Handle %p given %d credits (total %d, free %d)\n", handle, nblocks, transaction->t_outstanding_credits, log_space_left(journal)); unlock_journal(journal); return 0; }