Alexandria  2.27.0
SDC-CH common library for the Euclid project
LRUFileManager.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012-2021 Euclid Science Ground Segment
3  *
4  * This library is free software; you can redistribute it and/or modify it under
5  * the terms of the GNU Lesser General Public License as published by the Free
6  * Software Foundation; either version 3.0 of the License, or (at your option)
7  * any later version.
8  *
9  * This library is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12  * details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this library; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
21 #include <sys/resource.h>
22 
23 namespace Euclid {
24 namespace FilePool {
25 
26 LRUFileManager::LRUFileManager(unsigned limit) : m_limit(limit) {
27  if (m_limit == 0) {
28  struct rlimit rlim;
29  getrlimit(RLIMIT_NOFILE, &rlim);
30  assert(rlim.rlim_cur > 3);
31  m_limit = rlim.rlim_cur - 3; // Account for stdout, stderr and stdin
32  }
33 }
34 
36  closeAll();
37 }
38 
39 void LRUFileManager::notifyIntentToOpen(bool /*write*/) {
40  // Only one thread can be making space
43 
44  while (m_files.size() >= m_limit) {
45  bool closed = false;
46  for (auto& id : m_sorted_ids) {
47  auto& meta = m_files[id];
48  auto close_call = meta->m_request_close;
49  lock.unlock();
50  closed = close_call();
51  lock.lock();
52  // If the file was closed, the iterator on m_sorted_ids has been invalidated!
53  if (closed)
54  break;
55  }
56  if (!closed) {
57  throw Elements::Exception() << "Limit reached and failed to close any existing file descriptor";
58  }
59  }
60 }
61 
66  --m_current_pos[id];
67 }
68 
71  auto iter = m_current_pos[id];
72  m_current_pos.erase(id);
73  m_sorted_ids.erase(iter);
74 }
75 
77  // Update count
78  FileMetadata* f_ptr = reinterpret_cast<FileMetadata*>(id);
79  f_ptr->m_last_used = Clock::now();
80  ++f_ptr->m_used_count;
81 
82  // Bring it to the back, since it is the last used
84  auto iter = m_current_pos[id];
85  auto ptr = std::move(*iter);
86  m_sorted_ids.erase(iter);
89  --m_current_pos[id];
90 }
91 
92 unsigned int LRUFileManager::getLimit() const {
93  return m_limit;
94 }
95 
96 unsigned int LRUFileManager::getUsed() const {
97  return m_sorted_ids.size();
98 }
99 
100 unsigned int LRUFileManager::getAvailable() const {
101  return m_limit - m_sorted_ids.size();
102 }
103 
104 } // namespace FilePool
105 } // namespace Euclid
intptr_t FileId
Opaque FileId, its concrete type should only be assumed to be copyable and hashable.
Definition: FileManager.h:65
std::map< FileId, std::unique_ptr< FileMetadata > > m_files
Definition: FileManager.h:176
std::map< FileId, std::list< FileId >::iterator > m_current_pos
std::list< FileId > m_sorted_ids
Sorted from less to more recent.
void notifyClosedFile(FileId id) override
void notifyUsed(FileId id) override
LRUFileManager(unsigned limit=500)
void notifyOpenedFile(FileId id) override
void notifyIntentToOpen(bool write) override
T emplace_back(T... args)
T end(T... args)
T erase(T... args)
T move(T... args)
T size(T... args)