The simple "is it in range" check can be inline; complex cases can be
handed through to the normal or transaction handler.
NTDB speed:
Adding 10000 records: 4111-9983(9149) ns (815528 bytes)
Finding 10000 records: 1667-4464(3810) ns (815528 bytes)
Missing 10000 records: 1511-3992(3546) ns (815528 bytes)
Traversing 10000 records: 1698-4254(3724) ns (815528 bytes)
Deleting 10000 records: 3608-7998(7358) ns (815528 bytes)
Re-adding 10000 records: 3259-8504(7805) ns (815528 bytes)
Appending 10000 records: 5393-13579(12356) ns (
1274312 bytes)
Churning 10000 records: 6966-17813(16136) ns (
1274312 bytes)
NTDB speed in transaction:
Adding 10000 records: 916-2230(2004) ns (815528 bytes)
Finding 10000 records: 330-866(770) ns (815528 bytes)
Missing 10000 records: 196-520(471) ns (815528 bytes)
Traversing 10000 records: 356-879(800) ns (815528 bytes)
Deleting 10000 records: 505-1267(1108) ns (815528 bytes)
Re-adding 10000 records: 658-1681(1477) ns (815528 bytes)
Appending 10000 records: 1088-2827(2498) ns (
1274312 bytes)
Churning 10000 records: 1636-4267(3785) ns (
1274312 bytes)
smbtorture results:
ntdb speed 85588-189430(157110) ops/sec
}
- ecode = ntdb->io->oob(ntdb, off,
- frec_len(frec)
- + sizeof(struct ntdb_used_record),
- false);
+ ecode = ntdb_oob(ntdb, off,
+ frec_len(frec) + sizeof(struct ntdb_used_record),
+ false);
if (ecode != NTDB_SUCCESS) {
return ecode;
}
/* Someone else may have expanded the file, so retry. */
old_size = ntdb->file->map_size;
- ntdb->io->oob(ntdb, ntdb->file->map_size, 1, true);
+ ntdb_oob(ntdb, ntdb->file->map_size, 1, true);
if (ntdb->file->map_size != old_size) {
ntdb_unlock_expand(ntdb, F_WRLCK);
return NTDB_SUCCESS;
If probe is true, len being too large isn't a failure.
*/
-static enum NTDB_ERROR ntdb_oob(struct ntdb_context *ntdb,
- ntdb_off_t off, ntdb_len_t len, bool probe)
+static enum NTDB_ERROR ntdb_normal_oob(struct ntdb_context *ntdb,
+ ntdb_off_t off, ntdb_len_t len,
+ bool probe)
{
struct stat st;
enum NTDB_ERROR ecode;
(long long)off, (long long)len);
}
- if (len + off <= ntdb->file->map_size)
- return NTDB_SUCCESS;
if (ntdb->flags & NTDB_INTERNAL) {
if (probe)
return NTDB_SUCCESS;
"Write to read-only database");
}
- ecode = ntdb->io->oob(ntdb, off, len, false);
+ ecode = ntdb_oob(ntdb, off, len, false);
if (ecode != NTDB_SUCCESS) {
return ecode;
}
{
enum NTDB_ERROR ecode;
- ecode = ntdb->io->oob(ntdb, off, len, false);
+ ecode = ntdb_oob(ntdb, off, len, false);
if (ecode != NTDB_SUCCESS) {
return ecode;
}
static const struct ntdb_methods io_methods = {
ntdb_read,
ntdb_write,
- ntdb_oob,
+ ntdb_normal_oob,
ntdb_expand_file,
ntdb_direct,
};
ntdb_unlock_open(ntdb, openlock);
/* This makes sure we have current map_size and mmap. */
- ecode = ntdb->io->oob(ntdb, ntdb->file->map_size, 1, true);
+ ecode = ntdb_oob(ntdb, ntdb->file->map_size, 1, true);
if (unlikely(ecode != NTDB_SUCCESS))
goto fail;
enum ntdb_log_level level,
const char *fmt, ...);
+static inline enum NTDB_ERROR ntdb_oob(struct ntdb_context *ntdb,
+ ntdb_off_t off, ntdb_len_t len,
+ bool probe)
+{
+ if (likely(off + len >= off)
+ && likely(off + len <= ntdb->file->map_size)
+ && likely(!probe)) {
+ return NTDB_SUCCESS;
+ }
+ return ntdb->io->oob(ntdb, off, len, probe);
+}
+
#ifdef NTDB_TRACE
void ntdb_trace(struct ntdb_context *ntdb, const char *op);
void ntdb_trace_seqnum(struct ntdb_context *ntdb, uint32_t seqnum, const char *op);
/* make sure we know about any file expansions already done by
anyone else */
- ntdb->io->oob(ntdb, ntdb->file->map_size, 1, true);
+ ntdb_oob(ntdb, ntdb->file->map_size, 1, true);
ntdb->transaction->old_map_size = ntdb->file->map_size;
/* finally hook the io methods, replacing them with