diff --git a/xapian-core/backends/chert/chert_database.cc b/xapian-core/backends/chert/chert_database.cc
index ff60d96..538554d 100644
a
|
b
|
ChertDatabase::set_revision_number(chert_revision_number_t new_revision)
|
472 | 472 | } |
473 | 473 | } |
474 | 474 | |
| 475 | void |
| 476 | ChertDatabase::request_document(Xapian::docid did) const |
| 477 | { |
| 478 | record_table.readahead_for_record(did); |
| 479 | } |
| 480 | |
| 481 | void |
| 482 | ChertDatabase::readahead_for_query(const Xapian::Query &query) |
| 483 | { |
| 484 | Xapian::TermIterator t; |
| 485 | for (t = query.get_terms_begin(); t != Xapian::TermIterator(); ++t) { |
| 486 | const string & term = *t; |
| 487 | postlist_table.readahead_key(term); |
| 488 | } |
| 489 | } |
| 490 | |
475 | 491 | bool |
476 | 492 | ChertDatabase::reopen() |
477 | 493 | { |
diff --git a/xapian-core/backends/chert/chert_database.h b/xapian-core/backends/chert/chert_database.h
index b7375d1..8445e60 100644
a
|
b
|
class ChertDatabase : public Xapian::Database::Internal {
|
219 | 219 | chert_revision_number_t * startrev, |
220 | 220 | chert_revision_number_t * endrev) const; |
221 | 221 | public: |
| 222 | |
| 223 | void request_document(Xapian::docid /*did*/) const; |
| 224 | void readahead_for_query(const Xapian::Query &query); |
222 | 225 | /** Create and open a chert database. |
223 | 226 | * |
224 | 227 | * @exception Xapian::DatabaseCorruptError is thrown if there is no |
diff --git a/xapian-core/backends/chert/chert_record.cc b/xapian-core/backends/chert/chert_record.cc
index 55ba264..000ec8d 100644
a
|
b
|
ChertRecordTable::get_doccount() const
|
66 | 66 | } |
67 | 67 | |
68 | 68 | void |
| 69 | ChertRecordTable::readahead_for_record(Xapian::docid did) const |
| 70 | { |
| 71 | readahead_key(make_key(did)); |
| 72 | } |
| 73 | |
| 74 | void |
69 | 75 | ChertRecordTable::replace_record(const string & data, Xapian::docid did) |
70 | 76 | { |
71 | 77 | LOGCALL_VOID(DB, "ChertRecordTable::replace_record", data | did); |
diff --git a/xapian-core/backends/chert/chert_record.h b/xapian-core/backends/chert/chert_record.h
index 0f6607d..48917ca 100644
a
|
b
|
class ChertRecordTable : public ChertTable {
|
65 | 65 | */ |
66 | 66 | void replace_record(const string & data, Xapian::docid did); |
67 | 67 | |
| 68 | void readahead_for_record(Xapian::docid did) const; |
| 69 | |
68 | 70 | /** Delete a record from the table. |
69 | 71 | */ |
70 | 72 | void delete_record(Xapian::docid did); |
diff --git a/xapian-core/backends/chert/chert_table.cc b/xapian-core/backends/chert/chert_table.cc
index a18bb5a..b603db3 100644
a
|
b
|
static inline byte *zeroed_new(size_t size)
|
167 | 167 | |
168 | 168 | #define BYTE_PAIR_RANGE (1 << 2 * CHAR_BIT) |
169 | 169 | |
| 170 | void |
| 171 | ChertTable::readahead_block(uint4 n) const |
| 172 | { |
| 173 | if (rare(handle == -2)) |
| 174 | ChertTable::throw_database_closed(); |
| 175 | |
| 176 | /* Use the base bit_map_size not the bitmap's size, because |
| 177 | * the latter is uninitialised in readonly mode. |
| 178 | */ |
| 179 | Assert(n / CHAR_BIT < base.get_bit_map_size()); |
| 180 | |
| 181 | io_readahead_block(handle, block_size, n); |
| 182 | } |
| 183 | |
170 | 184 | /// read_block(n, p) reads block n of the DB file to address p. |
171 | 185 | void |
172 | 186 | ChertTable::read_block(uint4 n, byte * p) const |
… |
… |
ChertTable::del(const string &key)
|
1134 | 1148 | } |
1135 | 1149 | |
1136 | 1150 | bool |
| 1151 | ChertTable::readahead_key(const string &key) const |
| 1152 | { |
| 1153 | LOGCALL(DB, bool, "ChertTable::readahead_key", key); |
| 1154 | Assert(!key.empty()); |
| 1155 | |
| 1156 | form_key(key); |
| 1157 | |
| 1158 | const byte * p; |
| 1159 | int c; |
| 1160 | |
| 1161 | Key ktkey = kt.key(); |
| 1162 | |
| 1163 | // We'll only readahead the first level, since descending the B-tree would |
| 1164 | // require actual reads that would likely hurt performance more than help. |
| 1165 | p = C[level].p; |
| 1166 | c = find_in_block(p, ktkey, false, C[level].c); |
| 1167 | uint4 n = Item(p, c).block_given_by(); |
| 1168 | |
| 1169 | readahead_block(n); |
| 1170 | RETURN(true); |
| 1171 | } |
| 1172 | |
| 1173 | bool |
1137 | 1174 | ChertTable::get_exact_entry(const string &key, string & tag) const |
1138 | 1175 | { |
1139 | 1176 | LOGCALL(DB, bool, "ChertTable::get_exact_entry", key | tag); |
diff --git a/xapian-core/backends/chert/chert_table.h b/xapian-core/backends/chert/chert_table.h
index 2ea61ec..dd5c6c2 100644
a
|
b
|
class XAPIAN_VISIBILITY_DEFAULT ChertTable {
|
334 | 334 | */ |
335 | 335 | void close(bool permanent=false); |
336 | 336 | |
| 337 | bool readahead_key(const string &key) const; |
| 338 | |
337 | 339 | /** Determine whether the btree exists on disk. |
338 | 340 | */ |
339 | 341 | bool exists() const; |
… |
… |
class XAPIAN_VISIBILITY_DEFAULT ChertTable {
|
627 | 629 | bool find(Cursor *) const; |
628 | 630 | int delete_kt(); |
629 | 631 | void read_block(uint4 n, byte *p) const; |
| 632 | void readahead_block(uint4 n) const; |
630 | 633 | void write_block(uint4 n, const byte *p) const; |
631 | 634 | XAPIAN_NORETURN(void set_overwritten() const); |
632 | 635 | void block_to_cursor(Cursor *C_, int j, uint4 n) const; |
diff --git a/xapian-core/backends/database.cc b/xapian-core/backends/database.cc
index e98b32a..7cc8d6d 100644
a
|
b
|
Database::Internal::keep_alive()
|
50 | 50 | } |
51 | 51 | |
52 | 52 | |
| 53 | void |
| 54 | Database::Internal::readahead_for_query (const Xapian::Query & query) |
| 55 | { |
| 56 | (void)query; |
| 57 | throw Xapian::UnimplementedError("This backend doesn't support readaheads"); |
| 58 | } |
| 59 | |
53 | 60 | Xapian::doccount |
54 | 61 | Database::Internal::get_value_freq(Xapian::valueno) const |
55 | 62 | { |
diff --git a/xapian-core/backends/database.h b/xapian-core/backends/database.h
index a0e7b43..351e9a7 100644
a
|
b
|
class Database::Internal : public Xapian::Internal::intrusive_base {
|
105 | 105 | */ |
106 | 106 | virtual void keep_alive(); |
107 | 107 | |
| 108 | virtual void readahead_for_query (const Xapian::Query & query); |
| 109 | |
108 | 110 | ////////////////////////////////////////////////////////////////// |
109 | 111 | // Database statistics: |
110 | 112 | // ==================== |
diff --git a/xapian-core/common/io_utils.cc b/xapian-core/common/io_utils.cc
index fefef8e..9dc267f 100644
a
|
b
|
throw_block_error(const char * s, off_t b, int e)
|
105 | 105 | } |
106 | 106 | |
107 | 107 | void |
| 108 | io_readahead_block(int fd, size_t n, off_t b) |
| 109 | { |
| 110 | off_t o = b * n; |
| 111 | posix_fadvise(fd, o, n, POSIX_FADV_WILLNEED); |
| 112 | } |
| 113 | |
| 114 | void |
108 | 115 | io_read_block(int fd, char * p, size_t n, off_t b) |
109 | 116 | { |
110 | 117 | off_t o = b * n; |
diff --git a/xapian-core/common/io_utils.h b/xapian-core/common/io_utils.h
index 89d5d46..8b470ef 100644
a
|
b
|
inline void io_write(int fd, const unsigned char * p, size_t n) {
|
82 | 82 | io_write(fd, reinterpret_cast<const char *>(p), n); |
83 | 83 | } |
84 | 84 | |
| 85 | /// Readahead block b size n bytes from file descriptor fd |
| 86 | void io_readahead_block(int fd, size_t n, off_t b); |
| 87 | |
85 | 88 | /// Read block b size n bytes into buffer p from file descriptor fd. |
86 | 89 | void io_read_block(int fd, char * p, size_t n, off_t b); |
87 | 90 | |
diff --git a/xapian-core/include/xapian/database.h b/xapian-core/include/xapian/database.h
index 78f14d9..ab0339e 100644
a
|
b
|
|
36 | 36 | #include <xapian/attributes.h> |
37 | 37 | #include <xapian/intrusive_ptr.h> |
38 | 38 | #include <xapian/types.h> |
| 39 | #include <xapian/query.h> |
39 | 40 | #include <xapian/positioniterator.h> |
40 | 41 | #include <xapian/postingiterator.h> |
41 | 42 | #include <xapian/termiterator.h> |
diff --git a/xapian-core/matcher/multimatch.cc b/xapian-core/matcher/multimatch.cc
index ef8525e..a221cd6 100644
a
|
b
|
MultiMatch::MultiMatch(const Xapian::Database &db_,
|
332 | 332 | is_remote[i] = true; |
333 | 333 | } else { |
334 | 334 | smatch = new LocalSubMatch(subdb, query, qlen, subrsets[i], weight); |
| 335 | subdb->readahead_for_query(query); |
335 | 336 | } |
336 | 337 | #else |
337 | 338 | // Avoid unused parameter warnings. |