@@ -197,6 +197,76 @@ void TBlobStorageController::Handle(TEvents::TEvUndelivered::TPtr ev) {
197
197
}
198
198
}
199
199
200
+ bool TBlobStorageController::HostConfigEquals (const THostConfigInfo& left, const NKikimrBlobStorage::TDefineHostConfig& right) const {
201
+ if (left.Name != right.GetName ()) {
202
+ return false ;
203
+ }
204
+
205
+ THashMap<TStringBuf, const THostConfigInfo::TDriveInfo*> driveMap;
206
+ for (const auto & [key, info] : left.Drives ) {
207
+ driveMap.emplace (key.Path , &info);
208
+ }
209
+
210
+ TMaybe<TString> defaultPDiskConfig;
211
+ if (right.HasDefaultHostPDiskConfig ()) {
212
+ const bool success = right.GetDefaultHostPDiskConfig ().SerializeToString (&defaultPDiskConfig.ConstructInPlace ());
213
+ Y_ABORT_UNLESS (success);
214
+ }
215
+
216
+ auto checkDrive = [&](const auto & drive) {
217
+ const auto it = driveMap.find (drive.GetPath ());
218
+ if (it == driveMap.end ()) {
219
+ return false ;
220
+ }
221
+
222
+ if (drive.GetType () != it->second ->Type ||
223
+ drive.GetSharedWithOs () != it->second ->SharedWithOs ||
224
+ drive.GetReadCentric () != it->second ->ReadCentric ||
225
+ drive.GetKind () != it->second ->Kind ) {
226
+ return false ;
227
+ }
228
+
229
+ TMaybe<TString> pdiskConfig;
230
+ if (drive.HasPDiskConfig ()) {
231
+ const bool success = drive.GetPDiskConfig ().SerializeToString (&pdiskConfig.ConstructInPlace ());
232
+ Y_ABORT_UNLESS (success);
233
+ } else {
234
+ pdiskConfig = defaultPDiskConfig;
235
+ }
236
+
237
+ if (pdiskConfig != it->second ->PDiskConfig ) {
238
+ return false ;
239
+ }
240
+
241
+ driveMap.erase (it);
242
+ return true ;
243
+ };
244
+
245
+ for (const auto & drive : right.GetDrive ()) {
246
+ if (!checkDrive (drive)) {
247
+ return false ;
248
+ }
249
+ }
250
+
251
+ auto addDrives = [&](const auto & field, NKikimrBlobStorage::EPDiskType type) {
252
+ NKikimrBlobStorage::THostConfigDrive drive;
253
+ drive.SetType (type);
254
+ for (const auto & path : field) {
255
+ if (drive.SetPath (path); !checkDrive (drive)) {
256
+ return false ;
257
+ }
258
+ }
259
+ return true ;
260
+ };
261
+ if (!addDrives (right.GetRot (), NKikimrBlobStorage::EPDiskType::ROT) ||
262
+ !addDrives (right.GetSsd (), NKikimrBlobStorage::EPDiskType::SSD) ||
263
+ !addDrives (right.GetNvme (), NKikimrBlobStorage::EPDiskType::NVME)) {
264
+ return false ;
265
+ }
266
+
267
+ return driveMap.empty ();
268
+ }
269
+
200
270
void TBlobStorageController::ApplyStorageConfig (bool ignoreDistconf) {
201
271
if (!StorageConfig.HasBlobStorageConfig ()) {
202
272
return ;
@@ -211,74 +281,101 @@ void TBlobStorageController::ApplyStorageConfig(bool ignoreDistconf) {
211
281
return ; // not expected to be managed by BSC
212
282
}
213
283
284
+ ui64 expectedBoxId;
214
285
std::optional<ui64> generation;
286
+ bool needToDefineBox = true ;
215
287
if (!Boxes.empty ()) {
216
288
const auto & [boxId, box] = *Boxes.begin ();
217
289
218
- THashSet<THostConfigId> unusedHostConfigs;
219
- for (const auto & [hostConfigId, _] : HostConfigs) {
220
- unusedHostConfigs.insert (hostConfigId);
290
+ expectedBoxId = boxId;
291
+ generation = box.Generation .GetOrElse (1 );
292
+ needToDefineBox = false ;
293
+
294
+ // put all existing hosts of a singular box into the set
295
+ THashSet<std::tuple<TString, ui32, ui64, TMaybe<ui32>>> hosts;
296
+ for (const auto & [key, value] : box.Hosts ) {
297
+ hosts.emplace (key.Fqdn , key.IcPort , value.HostConfigId , value.EnforcedNodeId );
221
298
}
222
- for (const auto & [_, host] : box.Hosts ) {
223
- if (!HostConfigs.contains (host.HostConfigId )) {
224
- return ;
299
+
300
+ // drop matching entries from the new set
301
+ for (const auto & host : bsConfig.GetDefineBox ().GetHost ()) {
302
+ const auto & resolved = HostRecords->GetHostId (host.GetEnforcedNodeId ());
303
+ Y_ABORT_UNLESS (resolved);
304
+ const auto & [fqdn, port] = *resolved;
305
+
306
+ if (!hosts.erase (std::make_tuple (fqdn, port, host.GetHostConfigId (), Nothing ()))) {
307
+ needToDefineBox = true ;
308
+ break ;
225
309
}
226
- unusedHostConfigs.erase (host.HostConfigId );
227
310
}
228
311
229
- if (!unusedHostConfigs .empty ()) {
230
- return ;
312
+ if (!hosts .empty ()) {
313
+ needToDefineBox = true ;
231
314
}
232
-
233
- generation = box.Generation .GetOrElse (0 );
234
315
}
235
316
236
317
auto ev = std::make_unique<TEvBlobStorage::TEvControllerConfigRequest>();
237
318
auto & r = ev->Record ;
238
319
auto *request = r.MutableRequest ();
239
320
for (const auto & hostConfig : bsConfig.GetDefineHostConfig ()) {
321
+ const auto it = HostConfigs.find (hostConfig.GetHostConfigId ());
322
+ if (it != HostConfigs.end () && HostConfigEquals (it->second , hostConfig)) {
323
+ continue ;
324
+ }
325
+
326
+ auto *cmd = request->AddCommand ();
327
+ auto *defineHostConfig = cmd->MutableDefineHostConfig ();
328
+ defineHostConfig->CopyFrom (hostConfig);
329
+ if (it != HostConfigs.end ()) {
330
+ defineHostConfig->SetItemConfigGeneration (it->second .Generation .GetOrElse (1 ));
331
+ }
332
+ }
333
+
334
+ if (needToDefineBox) {
240
335
auto *cmd = request->AddCommand ();
241
- cmd->MutableDefineHostConfig ()->CopyFrom (hostConfig);
242
- }
243
- auto *cmd = request->AddCommand ();
244
- auto *defineBox = cmd->MutableDefineBox ();
245
- defineBox->CopyFrom (bsConfig.GetDefineBox ());
246
- defineBox->SetBoxId (1 );
247
- for (auto & host : *defineBox->MutableHost ()) {
248
- const ui32 nodeId = host.GetEnforcedNodeId ();
249
- host.ClearEnforcedNodeId ();
250
- auto *key = host.MutableKey ();
251
- const auto & resolved = HostRecords->GetHostId (nodeId);
252
- Y_ABORT_UNLESS (resolved);
253
- const auto & [fqdn, port] = *resolved;
254
- key->SetFqdn (fqdn);
255
- key->SetIcPort (port);
256
- }
257
- if (generation) {
258
- defineBox->SetItemConfigGeneration (*generation);
259
- }
260
-
261
- THashSet<THostConfigId> unusedHostConfigs;
262
- for (const auto & [hostConfigId, _] : HostConfigs) {
263
- unusedHostConfigs.insert (hostConfigId);
264
- }
265
- for (const auto & host : defineBox->GetHost ()) {
266
- unusedHostConfigs.erase (host.GetHostConfigId ());
267
- }
268
- for (const THostConfigId hostConfigId : unusedHostConfigs) {
336
+ auto *defineBox = cmd->MutableDefineBox ();
337
+ defineBox->CopyFrom (bsConfig.GetDefineBox ());
338
+ defineBox->SetBoxId (expectedBoxId);
339
+ for (auto & host : *defineBox->MutableHost ()) {
340
+ const ui32 nodeId = host.GetEnforcedNodeId ();
341
+ host.ClearEnforcedNodeId ();
342
+ auto *key = host.MutableKey ();
343
+ const auto & resolved = HostRecords->GetHostId (nodeId);
344
+ Y_ABORT_UNLESS (resolved);
345
+ const auto & [fqdn, port] = *resolved;
346
+ key->SetFqdn (fqdn);
347
+ key->SetIcPort (port);
348
+ }
349
+ if (generation) {
350
+ defineBox->SetItemConfigGeneration (*generation);
351
+ }
352
+ }
353
+
354
+ THashMap<THostConfigId, ui64> unusedHostConfigs;
355
+ for (const auto & [hostConfigId, value] : HostConfigs) {
356
+ unusedHostConfigs.emplace (hostConfigId, value.Generation .GetOrElse (1 ));
357
+ }
358
+ for (const auto & hostConfig : bsConfig.GetDefineHostConfig ()) {
359
+ unusedHostConfigs.erase (hostConfig.GetHostConfigId ());
360
+ }
361
+ for (const auto & [hostConfigId, generation] : unusedHostConfigs) {
269
362
auto *cmd = request->AddCommand ();
270
363
auto *del = cmd->MutableDeleteHostConfig ();
271
364
del->SetHostConfigId (hostConfigId);
272
- del->SetItemConfigGeneration (HostConfigs[hostConfigId]. Generation . GetOrElse ( 0 ) );
365
+ del->SetItemConfigGeneration (generation );
273
366
}
274
367
275
- STLOG (PRI_DEBUG, BS_CONTROLLER, BSC14, " ApplyStorageConfig" , (Request, r));
276
-
277
- Send (SelfId (), ev.release ());
368
+ if (request->CommandSize ()) {
369
+ STLOG (PRI_DEBUG, BS_CONTROLLER, BSC14, " ApplyStorageConfig" , (Request, r));
370
+ Send (SelfId (), ev.release ());
371
+ }
278
372
}
279
373
280
374
void TBlobStorageController::Handle (TEvBlobStorage::TEvControllerConfigResponse::TPtr ev) {
281
- STLOG (PRI_DEBUG, BS_CONTROLLER, BSC15, " TEvControllerConfigResponse" , (Response, ev->Get ()->Record ));
375
+ auto & record = ev->Get ()->Record ;
376
+ auto & response = record.GetResponse ();
377
+ STLOG (response.GetSuccess () ? PRI_DEBUG : PRI_ERROR, BS_CONTROLLER, BSC15, " TEvControllerConfigResponse" ,
378
+ (Response, response));
282
379
}
283
380
284
381
void TBlobStorageController::Handle (TEvBlobStorage::TEvControllerUpdateGroupStat::TPtr& ev) {
0 commit comments