| 588 | } |
| 589 | |
| 590 | void PurgeCache() noexcept { |
| 591 | //try remove at least ExceedSoftLimit() oldest connections from cache |
| 592 | //вычисляем долю кеша, которую нужно почистить (в 256 долях) (но не менее 1/32 кеша) |
| 593 | const size_t frac256 = Min<size_t>(256, Max<size_t>(8, (ExceedSoftLimit() << 8) / (CachedConnections.Val() + 1))); |
| 594 | TConnectionRef tmp; |
| 595 | |
| 596 | for (size_t i = 0; i < MaxConnId_.load(std::memory_order_acquire) && !Shutdown_; i++) { |
| 597 | TConnList& tc = Lst_.Get(i); |
| 598 | if (size_t qsize = tc.Size()) { |
| 599 | //в каждой очереди чистим вычисленную долю |
| 600 | size_t purgeCounter = ((qsize * frac256) >> 8); |
| 601 | |
| 602 | if (!purgeCounter && qsize) { |
| 603 | if (qsize == 1) { |
| 604 | // check lifeness |
| 605 | TConnectionRef res; |
| 606 | if (tc.Dequeue(&res)) { |
| 607 | // if connection valid put it back |
| 608 | if (IsNotSocketClosedByOtherSide((*res)->Fd()) && !(*res)->ShutdownReceived()) { |
| 609 | tc.Enqueue(res); |
| 610 | } else { |
| 611 | ActiveConnections.Inc(); |
| 612 | CachedConnections.Dec(); |
| 613 | } |
| 614 | } |
| 615 | } else { |
| 616 | // drop at least one connection from queue with at least 2 connections |
| 617 | purgeCounter = 1; |
| 618 | } |
| 619 | } |
| 620 | |
| 621 | while (purgeCounter-- && tc.Dequeue(&tmp)) { |
| 622 | ActiveConnections.Inc(); |
| 623 | CachedConnections.Dec(); |
| 624 | tmp->Reset(nullptr); |
| 625 | } |
| 626 | } |
| 627 | } |
| 628 | } |
| 629 | |
| 630 | inline TConnList& ConnList(const TResolvedHost& addr) { |
| 631 | return Lst_.Get(addr.Id); |
nothing calls this directly
no test coverage detected