aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsnaury <snaury@ydb.tech>2023-04-05 18:46:24 +0300
committersnaury <snaury@ydb.tech>2023-04-05 18:46:24 +0300
commitfd86d9a7713285bdfb8f09300f04bac908f451e5 (patch)
tree75ac22abea6024ad2748746c083fb50df426562a
parent2eb21fc7d5f358ba19d86ed2bab01f64219814aa (diff)
downloadydb-fd86d9a7713285bdfb8f09300f04bac908f451e5.tar.gz
Support different element sizes in persisted tx artifacts
-rw-r--r--ydb/core/tx/datashard/datashard_active_transaction.cpp11
-rw-r--r--ydb/core/tx/datashard/datashard_impl.h2
-rw-r--r--ydb/core/tx/datashard/datashard_trans_queue.cpp30
3 files changed, 36 insertions, 7 deletions
diff --git a/ydb/core/tx/datashard/datashard_active_transaction.cpp b/ydb/core/tx/datashard/datashard_active_transaction.cpp
index 8f334f8b1ff..6f72f6d367d 100644
--- a/ydb/core/tx/datashard/datashard_active_transaction.cpp
+++ b/ydb/core/tx/datashard/datashard_active_transaction.cpp
@@ -582,12 +582,19 @@ void TActiveTransaction::DbStoreLocksAccessLog(TDataShard * self,
using Schema = TDataShard::Schema;
NIceDb::TNiceDb db(txc.DB);
- TVector<TSysTables::TLocksTable::TPersistentLock> vec;
+
+ using TLocksVector = TVector<TSysTables::TLocksTable::TPersistentLock>;
+ TLocksVector vec;
vec.reserve(LocksAccessLog().Locks.size());
for (auto &pr : LocksAccessLog().Locks)
vec.emplace_back(pr.second);
+
+ // Historically C++ column type was TVector<TLock>
+ const char* vecDataStart = reinterpret_cast<const char*>(vec.data());
+ size_t vecDataSize = vec.size() * sizeof(TLocksVector::value_type);
+ TStringBuf vecData(vecDataStart, vecDataSize);
db.Table<Schema::TxArtifacts>().Key(GetTxId())
- .Update(NIceDb::TUpdate<Schema::TxArtifacts::Locks>(vec));
+ .Update(NIceDb::TUpdate<Schema::TxArtifacts::Locks>(vecData));
LOG_TRACE_S(ctx, NKikimrServices::TX_DATASHARD,
"Storing " << vec.size() << " locks for txid=" << GetTxId()
diff --git a/ydb/core/tx/datashard/datashard_impl.h b/ydb/core/tx/datashard/datashard_impl.h
index 39a24478c6c..04124acae01 100644
--- a/ydb/core/tx/datashard/datashard_impl.h
+++ b/ydb/core/tx/datashard/datashard_impl.h
@@ -642,7 +642,7 @@ class TDataShard
// Specify which tx artifacts have been stored to local DB and can be
// reused on tx replay. See TActiveTransaction::EArtifactFlags.
struct Flags : Column<2, NScheme::NTypeIds::Uint64> {};
- struct Locks : Column<3, NScheme::NTypeIds::String> { using Type = TVector<TSysTables::TLocksTable::TPersistentLock>; };
+ struct Locks : Column<3, NScheme::NTypeIds::String> { using Type = TStringBuf; };
using TKey = TableKey<TxId>;
using TColumns = TableColumns<TxId, Flags, Locks>;
diff --git a/ydb/core/tx/datashard/datashard_trans_queue.cpp b/ydb/core/tx/datashard/datashard_trans_queue.cpp
index 4e529eb25d7..a23b9fcbb81 100644
--- a/ydb/core/tx/datashard/datashard_trans_queue.cpp
+++ b/ydb/core/tx/datashard/datashard_trans_queue.cpp
@@ -360,11 +360,33 @@ bool TTransQueue::LoadTxDetails(NIceDb::TNiceDb &db,
artifactFlags = 0;
if (!artifactsRow.EndOfSet()) {
artifactFlags = artifactsRow.GetValue<Schema::TxArtifacts::Flags>();
- auto persistentLocks = artifactsRow.GetValueOrDefault<Schema::TxArtifacts::Locks>({});
locks.clear();
- locks.reserve(persistentLocks.size());
- for (const auto& persistentLock : persistentLocks) {
- locks.push_back(TSysTables::TLocksTable::TLock::FromPersistent(persistentLock));
+
+ // Deserialize persisted locks from database
+ // Unfortunately there was a bad version briefly deployed to clusters
+ // that had an additional field in the locks structure, so we have to
+ // guess an element data size. Luckily there's always either 0 or 1
+ // locks in the column, so guessing is not really ambiguous.
+ TStringBuf data = artifactsRow.GetValueOrDefault<Schema::TxArtifacts::Locks>({});
+ if (!data.empty()) {
+ size_t elementSize = sizeof(TSysTables::TLocksTable::TPersistentLock);
+ if ((data.size() % elementSize) != 0) {
+ size_t badElementSize = elementSize + 8;
+ Y_VERIFY_S((data.size() % badElementSize) == 0,
+ "Unexpected Schema::TxArtifacts::Locks column size " << data.size()
+ << " (expected divisible by " << elementSize << " or " << badElementSize << ")");
+ elementSize = badElementSize;
+ }
+
+ const char* p = data.data();
+ size_t count = data.size() / elementSize;
+ locks.reserve(count);
+
+ for (size_t i = 0; i < count; ++i) {
+ locks.push_back(TSysTables::TLocksTable::TLock::FromPersistent(
+ ReadUnaligned<TSysTables::TLocksTable::TPersistentLock>(p)));
+ p += elementSize;
+ }
}
}