| 1840 | |
| 1841 | |
| 1842 | void Master::doRegistryGc() |
| 1843 | { |
| 1844 | // Schedule next periodic GC. |
| 1845 | scheduleRegistryGc(); |
| 1846 | |
| 1847 | // Determine which unreachable agents to GC from the registry, if |
| 1848 | // any. We do this by examining the master's in-memory copy of the |
| 1849 | // unreachable list and checking two criteria, "age" and "count". To |
| 1850 | // check the "count" criteria, we remove elements from the beginning |
| 1851 | // of the list until it contains at most "registry_max_agent_count" |
| 1852 | // elements (note that `slaves.unreachable` is a `LinkedHashMap`, |
| 1853 | // which provides iteration over keys in insertion-order). To check |
| 1854 | // the "age" criteria, we remove any element in the list whose age |
| 1855 | // is more than "registry_max_agent_age". Note that for the latter, |
| 1856 | // we check the entire list, not just the beginning: this avoids |
| 1857 | // requiring that the list be kept sorted by timestamp. |
| 1858 | // |
| 1859 | // We build a candidate list of SlaveIDs to remove. We then try to |
| 1860 | // remove this list from the registry. Note that all the slaveIDs we |
| 1861 | // want to remove might not be found in the registrar's copy of the |
| 1862 | // unreachable list; this can occur if there is a concurrent write |
| 1863 | // (e.g., an unreachable agent we want to GC reregisters |
| 1864 | // concurrently). In this situation, we skip removing any elements |
| 1865 | // we don't find. |
| 1866 | |
| 1867 | auto prune = [this](const LinkedHashMap<SlaveID, TimeInfo>& slaves) { |
| 1868 | size_t count = slaves.size(); |
| 1869 | TimeInfo currentTime = protobuf::getCurrentTime(); |
| 1870 | hashset<SlaveID> toRemove; |
| 1871 | |
| 1872 | foreachpair (const SlaveID& slaveId, |
| 1873 | const TimeInfo& removalTime, |
| 1874 | slaves) { |
| 1875 | // Count-based GC. |
| 1876 | CHECK(toRemove.size() <= count); |
| 1877 | |
| 1878 | size_t liveCount = count - toRemove.size(); |
| 1879 | if (liveCount > flags.registry_max_agent_count) { |
| 1880 | toRemove.insert(slaveId); |
| 1881 | continue; |
| 1882 | } |
| 1883 | |
| 1884 | // Age-based GC. |
| 1885 | Duration age = Nanoseconds( |
| 1886 | currentTime.nanoseconds() - removalTime.nanoseconds()); |
| 1887 | |
| 1888 | if (age > flags.registry_max_agent_age) { |
| 1889 | toRemove.insert(slaveId); |
| 1890 | } |
| 1891 | } |
| 1892 | |
| 1893 | return toRemove; |
| 1894 | }; |
| 1895 | |
| 1896 | hashset<SlaveID> toRemoveUnreachable = prune(slaves.unreachable); |
| 1897 | hashset<SlaveID> toRemoveGone = prune(slaves.gone); |
| 1898 | |
| 1899 | if (toRemoveUnreachable.empty() && toRemoveGone.empty()) { |
nothing calls this directly
no test coverage detected