| 204 | } |
| 205 | |
| 206 | bool SiteToSiteClient::confirm(const utils::Identifier& transactionID) { |
| 207 | int ret; |
| 208 | std::shared_ptr<Transaction> transaction = NULL; |
| 209 | |
| 210 | if (peer_state_ != READY) { |
| 211 | bootstrap(); |
| 212 | } |
| 213 | |
| 214 | if (peer_state_ != READY) { |
| 215 | return false; |
| 216 | } |
| 217 | |
| 218 | auto it = this->known_transactions_.find(transactionID); |
| 219 | |
| 220 | if (it == known_transactions_.end()) { |
| 221 | return false; |
| 222 | } |
| 223 | transaction = it->second; |
| 224 | |
| 225 | |
| 226 | if (transaction->getState() == TRANSACTION_STARTED && !transaction->isDataAvailable() && |
| 227 | transaction->getDirection() == RECEIVE) { |
| 228 | transaction->_state = TRANSACTION_CONFIRMED; |
| 229 | return true; |
| 230 | } |
| 231 | |
| 232 | if (transaction->getState() != DATA_EXCHANGED) { |
| 233 | return false; |
| 234 | } |
| 235 | |
| 236 | if (transaction->getDirection() == RECEIVE) { |
| 237 | if (transaction->isDataAvailable()) { |
| 238 | return false; |
| 239 | } |
| 240 | // we received a FINISH_TRANSACTION indicator. Send back a CONFIRM_TRANSACTION message |
| 241 | // to peer so that we can verify that the connection is still open. This is a two-phase commit, |
| 242 | // which helps to prevent the chances of data duplication. Without doing this, we may commit the |
| 243 | // session and then when we send the response back to the peer, the peer may have timed out and may not |
| 244 | // be listening. As a result, it will re-send the data. By doing this two-phase commit, we narrow the |
| 245 | // Critical Section involved in this transaction so that rather than the Critical Section being the |
| 246 | // time window involved in the entire transaction, it is reduced to a simple round-trip conversation. |
| 247 | uint64_t crcValue = transaction->getCRC(); |
| 248 | std::string crc = std::to_string(crcValue); |
| 249 | logger_->log_debug("Site2Site Receive confirm with CRC %llu to transaction %s", crcValue, transactionID.to_string()); |
| 250 | ret = writeResponse(transaction, CONFIRM_TRANSACTION, crc); |
| 251 | if (ret <= 0) |
| 252 | return false; |
| 253 | RespondCode code; |
| 254 | std::string message; |
| 255 | readResponse(transaction, code, message); |
| 256 | if (ret <= 0) |
| 257 | return false; |
| 258 | |
| 259 | if (code == CONFIRM_TRANSACTION) { |
| 260 | logger_->log_debug("Site2Site transaction %s peer confirm transaction", transactionID.to_string()); |
| 261 | transaction->_state = TRANSACTION_CONFIRMED; |
| 262 | return true; |
| 263 | } else if (code == BAD_CHECKSUM) { |
nothing calls this directly
no test coverage detected