Skip to content
This repository has been archived by the owner on Sep 13, 2023. It is now read-only.

Fix support for larger than 2 GB databases on Windows #24

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ members = [
[dependencies]
bitflags = "1"
libc = "0.2"
lmdb-sys = "0.8.0"
lmdb-sys = { path = "lmdb-sys" }

[dev-dependencies]
rand = "0.4"
Expand Down
14 changes: 14 additions & 0 deletions lmdb-sys/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,20 @@ fn main() {
if target.contains("android") {
build.define("ANDROID", "1");
}
if target.contains("windows") {
// LMDB on Windows has an issue with ´off_t´ being defined as ´long´ 32-bit signed
// which caused a max size of the database of 2 GB which we work
// around by redefining ´off_t´ to 64-bit
//
// was discussed here and allgedly fixed in January 2016 but fix doesn't work as
// Windows doesn't support _FILE_OFFSET_BITS
// https://www.openldap.org/lists/openldap-bugs/201605/msg00015.htm
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This URL returns a 404 NOT FOUND error. It looks like the correct URL is https://www.openldap.org/lists/openldap-bugs/201605/msg00015.html (with the trailing "l"; perhaps due to a recent reconfiguration of the server?).

// https://github.com/LMDB/lmdb/commit/20dec1f69bf4860202c764ce92b1fbbe3d11a065
build.define("_OFF_T_DEFINED", "1");
build.define("off_t", "__int64");
build.define("_off_t", "__int64");
}

build
.file(lmdb.join("mdb.c"))
.file(lmdb.join("midl.c"))
Expand Down
54 changes: 54 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,58 @@ mod test_utils {
tx.commit().expect("tx.commit")
}
}

// verify that the map file is sparsly allocated
// this used to fail on earlier versions of LMDB on Windows, before ITS#8324
#[test]
fn verify_sparse() {
const HEIGHT_KEY: [u8; 1] = [0];

let dir = TempDir::new("test").unwrap();

{
let env = {
let mut builder = Environment::new();
builder.set_map_size(1_000_000_000);
builder.open(dir.path()).expect("open lmdb env")
};
let db = env.open_db(None).unwrap();

for height in 0..1000 {
let mut value = [0u8; 8];
LittleEndian::write_u64(&mut value, height);
let mut tx = env.begin_rw_txn().expect("begin_rw_txn");
tx.put(db, &HEIGHT_KEY, &value, WriteFlags::empty())
.expect("tx.put");
tx.commit().expect("tx.commit")
}
}

let size = std::fs::metadata(dir.path().join("data.mdb"))
.expect("get file size")
.len();
assert!(size < 1_000_000);
}


// Verify that one can create a database larger than 2 GB
#[test]
fn verify_2gb_plus() {
let dir = TempDir::new("test").unwrap();
let env = Environment::new()
.set_map_size(4_000_000_000)
.open(dir.path()).expect("open lmdb env");
let db = env.open_db(None).unwrap();

let data: Vec<u8> = (0..1_000_000).into_iter().map(|i| i as u8).collect();

// try to write 3 GB of data
let mut tx = env.begin_rw_txn().expect("begin_rw_txn");
for i in 0..3000 {
let key = &data[i..(i+32)];
tx.put(db, &key, &data, WriteFlags::empty()).expect("tx.put");
}
tx.commit().expect("tx.commit")
}

}