@@ -95,7 +95,7 @@ Y_UNIT_TEST_SUITE(TTxDataShardBuildIndexScan) {
95
95
CreateShardedTable (server, sender, root, name, opts);
96
96
}
97
97
98
- Y_UNIT_TEST (TestRunScan ) {
98
+ Y_UNIT_TEST (RunScan ) {
99
99
TPortManager pm;
100
100
TServerSettings serverSettings (pm.GetPort (2134 ));
101
101
serverSettings.SetDomainName (" Root" )
@@ -130,8 +130,7 @@ Y_UNIT_TEST_SUITE(TTxDataShardBuildIndexScan) {
130
130
// Alter table: disable shadow data and change compaction policy
131
131
auto policy = NLocalDb::CreateDefaultUserTablePolicy ();
132
132
policy->KeepEraseMarkers = false ;
133
- WaitTxNotification (server,
134
- AsyncAlterAndDisableShadow (server, " /Root" , " table-2" , policy.Get ()));
133
+ WaitTxNotification (server, AsyncAlterAndDisableShadow (server, " /Root" , " table-2" , policy.Get ()));
135
134
136
135
// Shadow data must be visible now
137
136
auto data2 = ReadShardedTable (server, " /Root/table-2" );
@@ -140,6 +139,102 @@ Y_UNIT_TEST_SUITE(TTxDataShardBuildIndexScan) {
140
139
" value = 300, key = 3\n "
141
140
" value = 500, key = 5\n " );
142
141
}
142
+
143
+ Y_UNIT_TEST (ShadowBorrowCompaction) {
144
+ TPortManager pm;
145
+ TServerSettings serverSettings (pm.GetPort (2134 ));
146
+ serverSettings
147
+ .SetDomainName (" Root" )
148
+ .SetUseRealThreads (false );
149
+
150
+ Tests::TServer::TPtr server = new TServer (serverSettings);
151
+ auto &runtime = *server->GetRuntime ();
152
+ auto sender = runtime.AllocateEdgeActor ();
153
+
154
+ runtime.SetLogPriority (NKikimrServices::TX_DATASHARD, NLog::PRI_DEBUG);
155
+ runtime.SetLogPriority (NKikimrServices::FLAT_TX_SCHEMESHARD, NLog::PRI_TRACE);
156
+ runtime.SetLogPriority (NKikimrServices::TABLET_EXECUTOR, NLog::PRI_DEBUG);
157
+
158
+ // Allow manipulating shadow data using normal schemeshard operations
159
+ runtime.GetAppData ().AllowShadowDataInSchemeShardForTests = true ;
160
+
161
+ InitRoot (server, sender);
162
+
163
+ CreateShardedTable (server, sender, " /Root" , " table-1" , 1 , false );
164
+
165
+ // Upsert some initial values
166
+ ExecSQL (server, sender, " UPSERT INTO `/Root/table-1` (key, value) VALUES (1, 100), (2, 200), (3, 300), (4, 400), (5, 500);" );
167
+
168
+ CreateShardedTableForIndex (server, sender, " /Root" , " table-2" , 1 , false );
169
+
170
+ auto observer = runtime.AddObserver <TEvDataShard::TEvCompactBorrowed>([&](TEvDataShard::TEvCompactBorrowed::TPtr& event) {
171
+ Cerr << " Captured TEvDataShard::TEvCompactBorrowed from " << runtime.FindActorName (event->Sender ) << " to " << runtime.FindActorName (event->GetRecipientRewrite ()) << Endl;
172
+ if (runtime.FindActorName (event->Sender ) == " FLAT_SCHEMESHARD_ACTOR" ) {
173
+ event.Reset ();
174
+ }
175
+ });
176
+
177
+ auto snapshot = CreateVolatileSnapshot (server, { " /Root/table-1" });
178
+
179
+ DoBuildIndex (server, sender, " /Root/table-1" , " /Root/table-2" , snapshot, NKikimrTxDataShard::TEvBuildIndexProgressResponse::DONE);
180
+
181
+ // Writes to shadow data should not be visible yet
182
+ auto data = ReadShardedTable (server, " /Root/table-2" );
183
+ UNIT_ASSERT_VALUES_EQUAL (data, " " );
184
+
185
+ // Split index
186
+ auto shards1 = GetTableShards (server, sender, " /Root/table-2" );
187
+ UNIT_ASSERT_VALUES_EQUAL (shards1.size (), 1u );
188
+
189
+ // Split would fail otherwise :(
190
+ SetSplitMergePartCountLimit (server->GetRuntime (), -1 );
191
+
192
+ auto senderSplit = runtime.AllocateEdgeActor ();
193
+ ui64 txId = AsyncSplitTable (server, senderSplit, " /Root/table-2" , shards1.at (0 ), 300 );
194
+ WaitTxNotification (server, senderSplit, txId);
195
+
196
+ auto shards2 = GetTableShards (server, sender, " /Root/table-2" );
197
+ UNIT_ASSERT_VALUES_EQUAL (shards2.size (), 2u );
198
+
199
+ for (auto shardIndex : xrange (2u )) {
200
+ auto stats = WaitTableStats (runtime, shards2.at (shardIndex));
201
+ // Cerr << "Received shard stats:" << Endl << stats.DebugString() << Endl;
202
+
203
+ UNIT_ASSERT_VALUES_EQUAL (stats.GetTableStats ().GetRowCount (), shardIndex == 0 ? 2 : 3 );
204
+
205
+ THashSet<ui64> owners (stats.GetUserTablePartOwners ().begin (), stats.GetUserTablePartOwners ().end ());
206
+ // Note: datashard always adds current shard to part owners, even if there are no parts
207
+ UNIT_ASSERT_VALUES_EQUAL (owners, (THashSet<ui64>{shards1.at (0 ), shards2.at (shardIndex)}));
208
+
209
+ auto tableId = ResolveTableId (server, sender, " /Root/table-2" );
210
+ auto result = CompactBorrowed (runtime, shards2.at (shardIndex), tableId);
211
+ // Cerr << "Compact result " << result.DebugString() << Endl;
212
+ UNIT_ASSERT_VALUES_EQUAL (result.GetTabletId (), shards2.at (shardIndex));
213
+ UNIT_ASSERT_VALUES_EQUAL (result.GetPathId ().GetOwnerId (), tableId.PathId .OwnerId );
214
+ UNIT_ASSERT_VALUES_EQUAL (result.GetPathId ().GetLocalId (), tableId.PathId .LocalPathId );
215
+
216
+ for (int i = 0 ; i < 5 && (owners.size () > 1 || owners.contains (shards1.at (0 ))); ++i) {
217
+ auto stats = WaitTableStats (runtime, shards2.at (shardIndex));
218
+ owners = THashSet<ui64>(stats.GetUserTablePartOwners ().begin (), stats.GetUserTablePartOwners ().end ());
219
+ }
220
+
221
+ UNIT_ASSERT_VALUES_EQUAL (owners, (THashSet<ui64>{shards2.at (shardIndex)}));
222
+ }
223
+
224
+ // Alter table: disable shadow data and change compaction policy
225
+ auto policy = NLocalDb::CreateDefaultUserTablePolicy ();
226
+ policy->KeepEraseMarkers = false ;
227
+ WaitTxNotification (server, AsyncAlterAndDisableShadow (server, " /Root" , " table-2" , policy.Get ()));
228
+
229
+ // Shadow data must be visible now
230
+ auto data2 = ReadShardedTable (server, " /Root/table-2" );
231
+ UNIT_ASSERT_VALUES_EQUAL (data2,
232
+ " value = 100, key = 1\n "
233
+ " value = 200, key = 2\n "
234
+ " value = 300, key = 3\n "
235
+ " value = 400, key = 4\n "
236
+ " value = 500, key = 5\n " );
237
+ }
143
238
}
144
239
145
240
} // namespace NKikimr
0 commit comments