|
3 | 3 | #include "PrefilteringIndexReader.h" |
4 | 4 | #include "MemoryMapped.h" |
5 | 5 |
|
| 6 | +#include <sys/mman.h> |
| 7 | + |
6 | 8 | int touchdb(int argc, const char **argv, const Command& command) { |
7 | 9 | Parameters& par = Parameters::getInstance(); |
8 | 10 | par.parseParameters(argc, argv, command, true, 0, 0); |
9 | 11 |
|
10 | | - std::string db = par.db1; |
| 12 | + const char* mlockError = "Consider granting the `CAP_IPC_LOCK` capability to this binary (e.g., `setcap cap_ipc_lock=+ep <program>`, or run as root) or raising the locked-memory limit so `mlock(2)` can succeed. Check your current limit with `ulimit -l` and increase it via `ulimit -l <KB>` for the shell, `LimitMEMLOCK=infinity` in your systemd unit, or persistent user limits in `/etc/security/limits.conf` (e.g., `youruser hard memlock unlimited`)\n"; |
11 | 13 |
|
| 14 | + std::string db = par.db1; |
12 | 15 | std::string indexDB = PrefilteringIndexReader::searchForIndex(db); |
13 | 16 | if (indexDB.empty() == false) { |
14 | 17 | db = indexDB; |
| 18 | + if (par.idList != "") { |
| 19 | + std::string idx = db + ".index"; |
| 20 | + DBReader<unsigned int> reader(db.c_str(), idx.c_str(), 1, DBReader<unsigned int>::USE_DATA | DBReader<unsigned int>::USE_INDEX); |
| 21 | + reader.open(DBReader<unsigned int>::NOSORT); |
| 22 | + |
| 23 | + std::vector<std::string> ids = Util::split(par.idList, ","); |
| 24 | + for (size_t i = 0; i < ids.size(); ++i) { |
| 25 | + size_t id = reader.getId(Util::fast_atoi<unsigned int>(ids[i].c_str())); |
| 26 | + if (id == UINT_MAX) { |
| 27 | + Debug(Debug::WARNING) << "Key " << ids[i] << " not found in database\n"; |
| 28 | + continue; |
| 29 | + } |
| 30 | + size_t currDataOffset = reader.getOffset(id); |
| 31 | + size_t nextDataOffset = reader.findNextOffsetid(id); |
| 32 | + size_t dataSize = nextDataOffset - currDataOffset; |
| 33 | + char* data = reader.getDataUncompressed(id); |
| 34 | + Util::touchMemory(data, dataSize); |
| 35 | + if (par.touchLock) { |
| 36 | + int res = mlock(data, dataSize); |
| 37 | + if (res != 0) { |
| 38 | + Debug(Debug::ERROR) << "Could not lock memory " << strerror(errno) << "\n"; |
| 39 | + Debug(Debug::ERROR) << mlockError; |
| 40 | + reader.close(); |
| 41 | + return EXIT_FAILURE; |
| 42 | + } |
| 43 | + } |
| 44 | + } |
| 45 | + |
| 46 | + if (par.touchLock) { |
| 47 | + Debug(Debug::INFO) << "Touched and locked " << ids.size() << " entries. Process will not exit until killed.\n"; |
| 48 | + pause(); |
| 49 | + } else { |
| 50 | + Debug(Debug::INFO) << "Touched " << ids.size() << " entries\n"; |
| 51 | + } |
| 52 | + |
| 53 | + reader.close(); |
| 54 | + return EXIT_SUCCESS; |
| 55 | + } |
15 | 56 | } |
16 | 57 |
|
17 | 58 | MemoryMapped map(db, MemoryMapped::WholeFile, MemoryMapped::CacheHint::SequentialScan); |
18 | 59 | Util::touchMemory(reinterpret_cast<const char*>(map.getData()), map.mappedSize()); |
| 60 | + if (par.touchLock) { |
| 61 | + int res = mlock(map.getData(), map.mappedSize()); |
| 62 | + if (res != 0) { |
| 63 | + Debug(Debug::ERROR) << "Could not lock memory " << strerror(errno) << "\n"; |
| 64 | + Debug(Debug::ERROR) << mlockError; |
| 65 | + return EXIT_FAILURE; |
| 66 | + } |
| 67 | + Debug(Debug::INFO) << "Touched and locked database. Process will not exit until killed.\n"; |
| 68 | + pause(); |
| 69 | + } |
19 | 70 |
|
20 | 71 | return EXIT_SUCCESS; |
21 | 72 | } |
0 commit comments