| 460 | |
| 461 | |
| 462 | void ConfigStorage::compact() |
| 463 | { |
| 464 | SlotsByOffsetArray data(*getDefaultMemoryPool()); |
| 465 | |
| 466 | TraceCSHeader* header = m_sharedMemory->getHeader(); |
| 467 | |
| 468 | const ULONG pid = getpid(); |
| 469 | |
| 470 | ULONG check_used, check_size; |
| 471 | check_used = check_size = sizeof(TraceCSHeader); |
| 472 | |
| 473 | // Track undeleted slots from dead processes |
| 474 | Firebird::SortedArray<ULONG, InlineStorage<ULONG, 16>> deadProcesses; |
| 475 | |
| 476 | // collect used slots, sort them by offset |
| 477 | for (TraceCSHeader::Slot* slot = header->slots; slot < header->slots + header->slots_cnt; slot++) |
| 478 | { |
| 479 | if (slot->used && slot->ses_pid != pid && |
| 480 | ((slot->ses_flags & trs_system) == 0) && // System sessions are shared for multiple connections so they may live without the original process |
| 481 | !ISC_check_process_existence(slot->ses_pid)) |
| 482 | { |
| 483 | // A SUPER server may shut down, but its Storage shared memory continues to live due to an embedded user session. |
| 484 | // The process might allocate multiple slots, so count them carefully. |
| 485 | deadProcesses.add(slot->ses_pid); |
| 486 | |
| 487 | markDeleted(slot); |
| 488 | } |
| 489 | |
| 490 | SlotByOffset item; |
| 491 | item.index = slot - header->slots; |
| 492 | item.offset = slot->offset; |
| 493 | |
| 494 | check_used += slot->used; |
| 495 | check_size += slot->size; |
| 496 | data.add(item); |
| 497 | } |
| 498 | |
| 499 | // Process that created storages disappeared, count it out |
| 500 | fb_assert(header->cnt_uses > deadProcesses.getCount()); |
| 501 | header->cnt_uses -= deadProcesses.getCount(); |
| 502 | deadProcesses.clear(); |
| 503 | |
| 504 | fb_assert(check_used == header->mem_used); |
| 505 | fb_assert(check_size == header->mem_offset); |
| 506 | |
| 507 | // remove unused space between sessions data |
| 508 | ULONG destOffset = sizeof(TraceCSHeader); |
| 509 | for (SlotByOffset* item = data.begin(); item < data.end(); item++) |
| 510 | { |
| 511 | TraceCSHeader::Slot* slot = header->slots + item->index; |
| 512 | if (slot->used == 0) |
| 513 | { |
| 514 | slot->size = 0; |
| 515 | continue; |
| 516 | } |
| 517 | |
| 518 | fb_assert(slot->offset >= destOffset); |
| 519 |
nothing calls this directly
no test coverage detected