1
1
#include " datashard_impl.h"
2
2
#include " datashard_pipeline.h"
3
- #include " execution_unit_ctors.h"
4
3
4
+ #include " ydb/core/tx/datashard/datashard_write_operation.h"
5
5
#include < ydb/core/tablet/tablet_exception.h>
6
6
7
7
namespace NKikimr {
@@ -24,7 +24,7 @@ class TCheckWriteUnit: public TExecutionUnit {
24
24
25
25
TCheckWriteUnit::TCheckWriteUnit (TDataShard &dataShard,
26
26
TPipeline &pipeline)
27
- : TExecutionUnit(EExecutionUnitKind::CheckDataTx , false , dataShard, pipeline)
27
+ : TExecutionUnit(EExecutionUnitKind::CheckWrite , false , dataShard, pipeline)
28
28
{
29
29
}
30
30
@@ -45,126 +45,37 @@ EExecutionStatus TCheckWriteUnit::Execute(TOperation::TPtr op,
45
45
Y_ABORT_UNLESS (!op->IsAborted ());
46
46
47
47
if (CheckRejectDataTx (op, ctx)) {
48
- op->Abort (EExecutionUnitKind::FinishPropose );
48
+ op->Abort (EExecutionUnitKind::FinishProposeWrite );
49
49
50
50
return EExecutionStatus::Executed;
51
51
}
52
52
53
- // TODO: remove this return
54
- return EExecutionStatus::Executed;
55
-
56
- TActiveTransaction *tx = dynamic_cast <TActiveTransaction*>(op.Get ());
57
- Y_VERIFY_S (tx, " cannot cast operation of kind " << op->GetKind ());
58
- auto dataTx = tx->GetDataTx ();
59
- Y_ABORT_UNLESS (dataTx);
60
- Y_ABORT_UNLESS (dataTx->Ready () || dataTx->RequirePrepare ());
61
-
62
- if (dataTx->Ready ()) {
63
- DataShard.IncCounter (COUNTER_MINIKQL_PROGRAM_SIZE, dataTx->ProgramSize ());
64
- } else {
65
- Y_ABORT_UNLESS (dataTx->RequirePrepare ());
66
- LOG_DEBUG_S (ctx, NKikimrServices::TX_DATASHARD,
67
- " Require prepare Tx " << op->GetTxId () << " at " << DataShard.TabletID ()
68
- << " : " << dataTx->GetErrors ());
69
- }
53
+ TWriteOperation* writeOp = dynamic_cast <TWriteOperation*>(op.Get ());
54
+ Y_VERIFY_S (writeOp, " cannot cast operation of kind " << op->GetKind ());
55
+ auto writeTx = writeOp->WriteTx ();
56
+ Y_ABORT_UNLESS (writeTx);
57
+ Y_ABORT_UNLESS (writeTx->Ready () || writeTx->RequirePrepare ());
70
58
71
59
// Check if we are out of space and tx wants to update user
72
60
// or system table.
73
61
if (DataShard.IsAnyChannelYellowStop ()
74
- && (dataTx ->HasWrites () || !op->IsImmediate ())) {
62
+ && (writeTx ->HasWrites () || !op->IsImmediate ())) {
75
63
TString err = TStringBuilder ()
76
64
<< " Cannot perform transaction: out of disk space at tablet "
77
65
<< DataShard.TabletID () << " txId " << op->GetTxId ();
78
66
79
67
DataShard.IncCounter (COUNTER_PREPARE_OUT_OF_SPACE);
80
68
81
- BuildResult (op)-> AddError (NKikimrTxDataShard::TError::OUT_OF_SPACE , err);
82
- op->Abort (EExecutionUnitKind::FinishPropose );
69
+ writeOp-> SetError (NKikimrDataEvents::TEvWriteResult::STATUS_INTERNAL_ERROR , err);
70
+ op->Abort (EExecutionUnitKind::FinishProposeWrite );
83
71
84
- LOG_LOG_S_THROTTLE (DataShard.GetLogThrottler (TDataShard::ELogThrottlerType::CheckDataTxUnit_Execute ), ctx, NActors::NLog::PRI_ERROR, NKikimrServices::TX_DATASHARD, err);
72
+ LOG_LOG_S_THROTTLE (DataShard.GetLogThrottler (TDataShard::ELogThrottlerType::CheckWriteUnit_Execute ), ctx, NActors::NLog::PRI_ERROR, NKikimrServices::TX_DATASHARD, err);
85
73
86
74
return EExecutionStatus::Executed;
87
75
}
88
76
89
- if (tx->IsMvccSnapshotRead ()) {
90
- auto snapshot = tx->GetMvccSnapshot ();
91
- if (DataShard.IsFollower ()) {
92
- TString err = TStringBuilder ()
93
- << " Operation " << *op << " cannot read from snapshot " << snapshot
94
- << " using data tx on a follower " << DataShard.TabletID ();
95
-
96
- BuildResult (op, NKikimrTxDataShard::TEvProposeTransactionResult::BAD_REQUEST)
97
- ->AddError (NKikimrTxDataShard::TError::BAD_ARGUMENT, err);
98
- op->Abort (EExecutionUnitKind::FinishPropose);
99
-
100
- LOG_ERROR_S (ctx, NKikimrServices::TX_DATASHARD, err);
101
-
102
- return EExecutionStatus::Executed;
103
- } else if (!DataShard.IsMvccEnabled ()) {
104
- TString err = TStringBuilder ()
105
- << " Operation " << *op << " reads from snapshot " << snapshot
106
- << " with MVCC feature disabled at " << DataShard.TabletID ();
107
-
108
- BuildResult (op, NKikimrTxDataShard::TEvProposeTransactionResult::BAD_REQUEST)
109
- ->AddError (NKikimrTxDataShard::TError::BAD_ARGUMENT, err);
110
- op->Abort (EExecutionUnitKind::FinishPropose);
111
-
112
- LOG_ERROR_S (ctx, NKikimrServices::TX_DATASHARD, err);
113
-
114
- return EExecutionStatus::Executed;
115
- } else if (snapshot < DataShard.GetSnapshotManager ().GetLowWatermark ()) {
116
- TString err = TStringBuilder ()
117
- << " Operation " << *op << " reads from stale snapshot " << snapshot
118
- << " at " << DataShard.TabletID ();
119
-
120
- BuildResult (op, NKikimrTxDataShard::TEvProposeTransactionResult::BAD_REQUEST)
121
- ->AddError (NKikimrTxDataShard::TError::SNAPSHOT_NOT_EXIST, err);
122
- op->Abort (EExecutionUnitKind::FinishPropose);
123
-
124
- LOG_ERROR_S (ctx, NKikimrServices::TX_DATASHARD, err);
125
-
126
- ;
127
- }
128
- }
129
-
130
- TEngineBay::TSizes txReads;
131
-
132
- if (op->IsDataTx ()) {
133
- bool hasTotalKeysSizeLimit = !!dataTx->PerShardKeysSizeLimitBytes ();
134
- txReads = dataTx->CalcReadSizes (hasTotalKeysSizeLimit);
135
-
136
- if (txReads.ReadSize > DataShard.GetTxReadSizeLimit ()) {
137
- TString err = TStringBuilder ()
138
- << " Transaction read size " << txReads.ReadSize << " exceeds limit "
139
- << DataShard.GetTxReadSizeLimit () << " at tablet " << DataShard.TabletID ()
140
- << " txId " << op->GetTxId ();
141
-
142
- BuildResult (op, NKikimrTxDataShard::TEvProposeTransactionResult::BAD_REQUEST)
143
- ->AddError (NKikimrTxDataShard::TError::READ_SIZE_EXECEEDED, err);
144
- op->Abort (EExecutionUnitKind::FinishPropose);
145
-
146
- LOG_ERROR_S (ctx, NKikimrServices::TX_DATASHARD, err);
147
-
148
- return EExecutionStatus::Executed;
149
- }
150
-
151
- if (hasTotalKeysSizeLimit
152
- && txReads.TotalKeysSize > *dataTx->PerShardKeysSizeLimitBytes ()) {
153
- TString err = TStringBuilder ()
154
- << " Transaction total keys size " << txReads.TotalKeysSize
155
- << " exceeds limit " << *dataTx->PerShardKeysSizeLimitBytes ()
156
- << " at tablet " << DataShard.TabletID () << " txId " << op->GetTxId ();
157
-
158
- BuildResult (op, NKikimrTxDataShard::TEvProposeTransactionResult::BAD_REQUEST)
159
- ->AddError (NKikimrTxDataShard::TError::READ_SIZE_EXECEEDED, err);
160
- op->Abort (EExecutionUnitKind::FinishPropose);
161
-
162
- LOG_ERROR_S (ctx, NKikimrServices::TX_DATASHARD, err);
163
-
164
- return EExecutionStatus::Executed;
165
- }
166
-
167
- for (const auto & key : dataTx->TxInfo ().Keys ) {
77
+ {
78
+ for (const auto & key : writeTx->TxInfo ().Keys ) {
168
79
if (key.IsWrite && DataShard.IsUserTable (key.Key ->TableId )) {
169
80
ui64 keySize = 0 ;
170
81
for (const auto & cell : key.Key ->Range .From ) {
@@ -176,9 +87,8 @@ EExecutionStatus TCheckWriteUnit::Execute(TOperation::TPtr op,
176
87
<< " bytes which exceeds limit " << NLimits::MaxWriteKeySize
177
88
<< " bytes at " << DataShard.TabletID ();
178
89
179
- BuildResult (op, NKikimrTxDataShard::TEvProposeTransactionResult::BAD_REQUEST)
180
- ->AddError (NKikimrTxDataShard::TError::BAD_ARGUMENT, err);
181
- op->Abort (EExecutionUnitKind::FinishPropose);
90
+ writeOp->SetError (NKikimrDataEvents::TEvWriteResult::STATUS_BAD_REQUEST, err);
91
+ op->Abort (EExecutionUnitKind::FinishProposeWrite);
182
92
183
93
LOG_ERROR_S (ctx, NKikimrServices::TX_DATASHARD, err);
184
94
@@ -193,8 +103,8 @@ EExecutionStatus TCheckWriteUnit::Execute(TOperation::TPtr op,
193
103
<< " Transaction write column value of " << col.ImmediateUpdateSize
194
104
<< " bytes is larger than the allowed threshold" ;
195
105
196
- BuildResult (op, NKikimrTxDataShard::TEvProposeTransactionResult::EXEC_ERROR)-> AddError (NKikimrTxDataShard::TError::BAD_ARGUMENT , err);
197
- op->Abort (EExecutionUnitKind::FinishPropose );
106
+ writeOp-> SetError (NKikimrDataEvents::TEvWriteResult::STATUS_BAD_REQUEST , err);
107
+ op->Abort (EExecutionUnitKind::FinishProposeWrite );
198
108
199
109
LOG_ERROR_S (ctx, NKikimrServices::TX_DATASHARD, err);
200
110
@@ -216,10 +126,10 @@ EExecutionStatus TCheckWriteUnit::Execute(TOperation::TPtr op,
216
126
217
127
DataShard.IncCounter (COUNTER_PREPARE_OUT_OF_SPACE);
218
128
219
- BuildResult (op)-> AddError (NKikimrTxDataShard::TError::OUT_OF_SPACE , err);
220
- op->Abort (EExecutionUnitKind::FinishPropose );
129
+ writeOp-> SetError (NKikimrDataEvents::TEvWriteResult::STATUS_INTERNAL_ERROR , err);
130
+ op->Abort (EExecutionUnitKind::FinishProposeWrite );
221
131
222
- LOG_LOG_S_THROTTLE (DataShard.GetLogThrottler (TDataShard::ELogThrottlerType::CheckDataTxUnit_Execute ), ctx, NActors::NLog::PRI_ERROR, NKikimrServices::TX_DATASHARD, err);
132
+ LOG_LOG_S_THROTTLE (DataShard.GetLogThrottler (TDataShard::ELogThrottlerType::CheckWriteUnit_Execute ), ctx, NActors::NLog::PRI_ERROR, NKikimrServices::TX_DATASHARD, err);
223
133
224
134
return EExecutionStatus::Executed;
225
135
}
@@ -229,96 +139,20 @@ EExecutionStatus TCheckWriteUnit::Execute(TOperation::TPtr op,
229
139
}
230
140
}
231
141
232
- if (op->IsReadTable ()) {
233
- const auto & record = dataTx->GetReadTableTransaction ();
234
- const auto & userTables = DataShard.GetUserTables ();
235
-
236
- TMaybe<TString> schemaChangedError;
237
- if (auto it = userTables.find (record.GetTableId ().GetTableId ()); it != userTables.end ()) {
238
- const auto & tableInfo = *it->second ;
239
- for (const auto & columnRecord : record.GetColumns ()) {
240
- if (auto * columnInfo = tableInfo.Columns .FindPtr (columnRecord.GetId ())) {
241
- // TODO: column types don't change when bound by id, but we may want to check anyway
242
- } else {
243
- schemaChangedError = TStringBuilder () << " ReadTable cannot find column "
244
- << columnRecord.GetName () << " (" << columnRecord.GetId () << " )" ;
245
- break ;
246
- }
247
- }
248
- // TODO: validate key ranges?
249
- } else {
250
- schemaChangedError = TStringBuilder () << " ReadTable cannot find table "
251
- << record.GetTableId ().GetOwnerId () << " :" << record.GetTableId ().GetTableId ();
252
- }
253
-
254
- if (schemaChangedError) {
255
- BuildResult (op, NKikimrTxDataShard::TEvProposeTransactionResult::ERROR)
256
- ->AddError (NKikimrTxDataShard::TError::SCHEME_CHANGED, *schemaChangedError);
257
- op->Abort (EExecutionUnitKind::FinishPropose);
258
- return EExecutionStatus::Executed;
259
- }
260
-
261
- if (record.HasSnapshotStep () && record.HasSnapshotTxId ()) {
262
- if (!op->IsImmediate ()) {
263
- BuildResult (op, NKikimrTxDataShard::TEvProposeTransactionResult::BAD_REQUEST)->AddError (
264
- NKikimrTxDataShard::TError::BAD_ARGUMENT,
265
- " ReadTable from snapshot must be an immediate transaction" );
266
- op->Abort (EExecutionUnitKind::FinishPropose);
267
- return EExecutionStatus::Executed;
268
- }
269
-
270
- const TSnapshotKey key (
271
- record.GetTableId ().GetOwnerId (),
272
- record.GetTableId ().GetTableId (),
273
- record.GetSnapshotStep (),
274
- record.GetSnapshotTxId ());
275
-
276
- if (!DataShard.GetSnapshotManager ().AcquireReference (key)) {
277
- // TODO: try upgrading to mvcc snapshot when available
278
- BuildResult (op, NKikimrTxDataShard::TEvProposeTransactionResult::BAD_REQUEST)->AddError (
279
- NKikimrTxDataShard::TError::SNAPSHOT_NOT_EXIST,
280
- TStringBuilder ()
281
- << " Shard " << DataShard.TabletID ()
282
- << " has no snapshot " << key);
283
- op->Abort (EExecutionUnitKind::FinishPropose);
284
- return EExecutionStatus::Executed;
285
- }
286
-
287
- op->SetAcquiredSnapshotKey (key);
288
- op->SetUsingSnapshotFlag ();
289
- }
290
- }
291
-
292
142
if (!op->IsImmediate ()) {
293
143
if (!Pipeline.AssignPlanInterval (op)) {
294
- TString err = TStringBuilder ()
295
- << " Can't propose tx " << op->GetTxId () << " at blocked shard "
296
- << DataShard.TabletID ();
297
- BuildResult (op)->AddError (NKikimrTxDataShard::TError::SHARD_IS_BLOCKED, err);
298
- op->Abort (EExecutionUnitKind::FinishPropose);
144
+ TString err = TStringBuilder () << " Can't propose tx " << op->GetTxId () << " at blocked shard " << DataShard.TabletID ();
145
+
146
+ writeOp->SetError (NKikimrDataEvents::TEvWriteResult::STATUS_INTERNAL_ERROR, err);
147
+ op->Abort (EExecutionUnitKind::FinishProposeWrite);
299
148
300
149
LOG_NOTICE_S (ctx, NKikimrServices::TX_DATASHARD, err);
301
150
302
151
return EExecutionStatus::Executed;
303
152
}
304
153
305
- auto &res = BuildResult (op);
306
- res->SetPrepared (op->GetMinStep (), op->GetMaxStep (), op->GetReceivedAt ());
307
-
308
- if (op->IsDataTx ()) {
309
- res->Record .SetReadSize (txReads.ReadSize );
310
- res->Record .SetReplySize (txReads.ReplySize );
311
-
312
- for (const auto & rs : txReads.OutReadSetSize ) {
313
- auto entry = res->Record .AddOutgoingReadSetInfo ();
314
- entry->SetShardId (rs.first );
315
- entry->SetSize (rs.second );
316
- }
317
- }
318
-
319
- LOG_DEBUG_S (ctx, NKikimrServices::TX_DATASHARD,
320
- " Prepared " << op->GetKind () << " transaction txId " << op->GetTxId ()
321
- << " at tablet " << DataShard.TabletID ());
154
+ writeOp->SetWriteResult (NEvents::TDataEvents::TEvWriteResult::BuildPrepared (writeOp->WriteTx ()->TabletId (), op->GetTxId (), {op->GetMinStep (), op->GetMaxStep (), {}}));
155
+ LOG_DEBUG_S (ctx, NKikimrServices::TX_DATASHARD, " Prepared " << *op << " at " << DataShard.TabletID ());
322
156
}
323
157
324
158
return EExecutionStatus::Executed;
0 commit comments