X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=plocate.cpp;h=a1cd97a4a4645c08880b014d4799f9d4c33182f6;hb=fd6198891d6fd9642effc0843fef6f23b991af3e;hp=7cc4f5a4eb2587f4bb685aaa83155e8951f06dd2;hpb=cb87fdb5ede1d5a9fa0a5a309d9ccf98f42fe0b7;p=plocate diff --git a/plocate.cpp b/plocate.cpp index 7cc4f5a..a1cd97a 100644 --- a/plocate.cpp +++ b/plocate.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -57,6 +58,7 @@ bool check_existence = false; int64_t limit_matches = numeric_limits::max(); int64_t limit_left = numeric_limits::max(); bool stdout_is_tty = false; +bool literal_printing = false; static bool in_forked_child = false; steady_clock::time_point start; @@ -64,7 +66,7 @@ ZSTD_DDict *ddict = nullptr; class Corpus { public: - Corpus(int fd, IOUringEngine *engine); + Corpus(int fd, const char *filename_for_errors, IOUringEngine *engine); ~Corpus(); void find_trigram(uint32_t trgm, function cb); void get_compressed_filename_block(uint32_t docid, function cb) const; @@ -82,7 +84,7 @@ public: Header hdr; }; -Corpus::Corpus(int fd, IOUringEngine *engine) +Corpus::Corpus(int fd, const char *filename_for_errors, IOUringEngine *engine) : fd(fd), engine(engine) { if (flush_cache) { @@ -96,11 +98,11 @@ Corpus::Corpus(int fd, IOUringEngine *engine) complete_pread(fd, &hdr, sizeof(hdr), /*offset=*/0); if (memcmp(hdr.magic, "\0plocate", 8) != 0) { - fprintf(stderr, "plocate.db is corrupt or an old version; please rebuild it.\n"); + fprintf(stderr, "%s: database is corrupt or not a plocate database; please rebuild it.\n", filename_for_errors); exit(1); } if (hdr.version != 0 && hdr.version != 1) { - fprintf(stderr, "plocate.db has version %u, expected 0 or 1; please rebuild it.\n", hdr.version); + fprintf(stderr, "%s: has version %u, expected 0 or 1; please rebuild it.\n", filename_for_errors, hdr.version); exit(1); } if (hdr.version == 0) { @@ -347,7 +349,7 @@ uint64_t scan_all_docids(const vector &needles, int fd, const Corpus &co dprintf("Using %u worker threads for linear scan.\n", num_threads); unique_ptr threads(new WorkerThread[num_threads]); for (unsigned i = 0; i < num_threads; ++i) { - threads[i].t = thread([&threads, &mu, &queue_added, &queue_removed, &work_queue, &done, &offsets, &needles, &access_rx_cache, engine{ corpus.engine }, &matched, i] { + threads[i].t = thread([&threads, &mu, &queue_added, &queue_removed, &work_queue, &done, &offsets, &needles, &access_rx_cache, &matched, i] { // regcomp() takes a lock on the regex, so each thread will need its own. const vector *use_needles = &needles; vector recompiled_needles; @@ -378,7 +380,8 @@ uint64_t scan_all_docids(const vector &needles, int fd, const Corpus &co for (uint32_t docid = io_docid; docid < last_docid; ++docid) { size_t relative_offset = offsets[docid] - offsets[io_docid]; size_t len = offsets[docid + 1] - offsets[docid]; - scan_file_block(*use_needles, { &compressed[relative_offset], len }, engine, &access_rx_cache, docid, &receiver, &matched); + // IOUringEngine isn't thread-safe, so we do any needed stat()s synchronously (nullptr engine). + scan_file_block(*use_needles, { &compressed[relative_offset], len }, /*engine=*/nullptr, &access_rx_cache, docid, &receiver, &matched); } } }); @@ -486,7 +489,7 @@ uint64_t do_search_file(const vector &needles, const std::string &filena } IOUringEngine engine(/*slop_bytes=*/16); // 16 slop bytes as described in turbopfor.h. - Corpus corpus(fd, &engine); + Corpus corpus(fd, filename.c_str(), &engine); dprintf("Corpus init done after %.1f ms.\n", 1e3 * duration(steady_clock::now() - start).count()); vector trigram_groups; @@ -807,6 +810,7 @@ void usage() " -i, --ignore-case search case-insensitively\n" " -l, --limit LIMIT stop after LIMIT matches\n" " -0, --null delimit matches by NUL instead of newline\n" + " -N, --literal do not quote filenames, even if printing to a tty\n" " -r, --regexp interpret patterns as basic regexps (slow)\n" " --regex interpret patterns as extended regexps (slow)\n" " -w, --wholename search the entire path name (default; see -b)\n" @@ -833,11 +837,13 @@ int main(int argc, char **argv) static const struct option long_options[] = { { "help", no_argument, 0, 'h' }, { "count", no_argument, 0, 'c' }, + { "all", no_argument, 0, 'A' }, { "basename", no_argument, 0, 'b' }, { "database", required_argument, 0, 'd' }, { "existing", no_argument, 0, 'e' }, { "ignore-case", no_argument, 0, 'i' }, { "limit", required_argument, 0, 'l' }, + { "literal", no_argument, 0, 'N' }, { "null", no_argument, 0, '0' }, { "version", no_argument, 0, 'V' }, { "regexp", no_argument, 0, 'r' }, @@ -852,11 +858,14 @@ int main(int argc, char **argv) setlocale(LC_ALL, ""); for (;;) { int option_index = 0; - int c = getopt_long(argc, argv, "bcd:ehil:n:0rwVD", long_options, &option_index); + int c = getopt_long(argc, argv, "Abcd:ehil:n:N0rwVD", long_options, &option_index); if (c == -1) { break; } switch (c) { + case 'A': + // Ignored. + break; case 'b': match_basename = true; break; @@ -883,6 +892,9 @@ int main(int argc, char **argv) exit(1); } break; + case 'N': + literal_printing = true; + break; case '0': print_nul = true; break;