void logDelete(const char* ns, BSONObj row, bool fromMigrate, TxnContext* txn) { bool logForSharding = !fromMigrate && shouldLogTxnOpForSharding(OP_STR_DELETE, ns, row); if (logTxnOpsForReplication() || logForSharding) { BSONObjBuilder b; if (isLocalNs(ns)) { return; } appendOpType(OP_STR_DELETE, &b); appendNsStr(ns, &b); appendMigrate(fromMigrate, &b); b.append(KEY_STR_ROW, row); BSONObj logObj = b.obj(); if (logTxnOpsForReplication()) { txn->logOpForReplication(logObj); } if (logForSharding) { txn->logOpForSharding(logObj); } } }
void TxnOplog::writeOpsDirectlyToOplog(GTID gtid, uint64_t timestamp, uint64_t hash) { dassert(logTxnOpsForReplication()); dassert(_logTxnToOplog); // build array of in memory ops BSONArrayBuilder b; for (deque<BSONObj>::iterator it = _m.begin(); it != _m.end(); it++) { b.append(*it); } BSONArray a = b.arr(); // log ops _logTxnToOplog(gtid, timestamp, hash, a); }
void logCommand(const char* ns, BSONObj row, TxnContext* txn) { // We do not need to log for sharding because commands are only logged right now if they // take a write lock, and we have a read lock the whole time we're logging things for // sharding. TODO: If this changes, we need to start logging commands. if (logTxnOpsForReplication()) { BSONObjBuilder b; if (isLocalNs(ns)) { return; } appendOpType(OP_STR_COMMAND, &b); appendNsStr(ns, &b); b.append(KEY_STR_ROW, row); txn->logOpForReplication(b.obj()); } }
void logInsertForCapped( const char* ns, BSONObj pk, BSONObj row, TxnContext* txn ) { if (logTxnOpsForReplication()) { BSONObjBuilder b; if (isLocalNs(ns)) { return; } appendOpType(OP_STR_CAPPED_INSERT, &b); appendNsStr(ns, &b); b.append(KEY_STR_PK, pk); b.append(KEY_STR_ROW, row); txn->logOpForReplication(b.obj()); } }
void TxnContext::logOpForReplication(BSONObj op) { dassert(logTxnOpsForReplication()); _txnOps.appendOp(op); }
void TxnContext::commit(int flags) { verify(!_retired); bool gotGTID = false; GTID gtid; // do this in case we are writing the first entry // we put something in that can be distinguished from // an initialized GTID that has never been touched gtid.inc_primary(); // handle work related to logging of transaction for replication // this piece must be done before the _txn.commit try { if (hasParent()) { // This does something // a bit dangerous in that it may spill parent's stuff // with this child transaction that is committing. If something // goes wrong and this child transaction aborts, we will miss // some ops // // This ought to be ok, because we are in this try/catch block // where if something goes wrong, we will crash the server. // NOTHING better go wrong here, unless under bad rare // circumstances _txnOps.finishChildCommit(); } else if (!_txnOps.empty()) { uint64_t timestamp = 0; uint64_t hash = 0; if (!_initiatingRS) { dassert(txnGTIDManager); txnGTIDManager->getGTIDForPrimary(>id, ×tamp, &hash); } else { dassert(!txnGTIDManager); timestamp = curTimeMillis64(); } gotGTID = true; // In this case, the transaction we are committing has // no parent, so we must write the transaction's // logged operations to the opLog, as part of this transaction dassert(logTxnOpsForReplication()); dassert(_logTxnToOplog); _txnOps.rootCommit(gtid, timestamp, hash); } // handle work related to logging of transaction for chunk migrations if (!_txnOpsForSharding.empty()) { if (hasParent()) { transferOpsForShardingToParent(); } else { writeTxnOpsToMigrateLog(); } } _clientCursorRollback.preComplete(); _txn.commit(flags); // if the commit of this transaction got a GTID, then notify // the GTIDManager that the commit is now done. if (gotGTID && !_initiatingRS) { dassert(txnGTIDManager); // save the GTID for the client so that // getLastError will know what GTID slaves // need to be caught up to. cc().setLastOp(gtid); txnGTIDManager->noteLiveGTIDDone(gtid); } } catch (std::exception &e) { log() << "exception during critical section of txn commit, aborting system: " << e.what() << endl; printStackTrace(); logflush(); ::abort(); } // These rollback items must be processed after the ydb transaction completes. if (hasParent()) { _cappedRollback.transfer(_parent->_cappedRollback); _nsIndexRollback.transfer(_parent->_nsIndexRollback); } else { _cappedRollback.commit(); _nsIndexRollback.commit(); } _retired = true; }