aboutsummaryrefslogtreecommitdiff
path: root/db_test.go
diff options
context:
space:
mode:
authorGyu-Ho Lee <gyuhox@gmail.com>2015-12-21 15:28:44 -0800
committerGyu-Ho Lee <gyuhox@gmail.com>2015-12-21 15:36:00 -0800
commit082efcc23e41f42d15f9e90f4e079fdb793e997f (patch)
treea88f0fb9f747a01a256e9dc33b8f7a99bd78a789 /db_test.go
parentMerge pull request #470 from ReadmeCritic/master (diff)
downloaddedo-082efcc23e41f42d15f9e90f4e079fdb793e997f.tar.gz
dedo-082efcc23e41f42d15f9e90f4e079fdb793e997f.tar.xz
Introduce InitialMmapSize to prevent deadlock
InitialMmapSize is the initial mmap size of the database in bytes. Read transaction won't block write transaction if InitialMmapSize is large enough to handle mmap size. Copied from https://github.com/boltdb/bolt/pull/432.
Diffstat (limited to 'db_test.go')
-rw-r--r--db_test.go45
1 files changed, 45 insertions, 0 deletions
diff --git a/db_test.go b/db_test.go
index aa8a2f2..197071b 100644
--- a/db_test.go
+++ b/db_test.go
@@ -368,6 +368,51 @@ func TestOpen_ReadOnly(t *testing.T) {
}
}
+// TestDB_Open_InitialMmapSize tests if having InitialMmapSize large enough
+// to hold data from concurrent write transaction resolves the issue that
+// read transaction blocks the write transaction and causes deadlock.
+// This is a very hacky test since the mmap size is not exposed.
+func TestDB_Open_InitialMmapSize(t *testing.T) {
+ path := tempfile()
+ defer os.Remove(path)
+
+ initMmapSize := 1 << 31 // 2GB
+ testWriteSize := 1 << 27 // 134MB
+
+ db, err := bolt.Open(path, 0666, &bolt.Options{InitialMmapSize: initMmapSize})
+ assert(t, err == nil, "")
+
+ // create a long-running read transaction
+ // that never gets closed while writing
+ rtx, err := db.Begin(false)
+ assert(t, err == nil, "")
+ defer rtx.Rollback()
+
+ // create a write transaction
+ wtx, err := db.Begin(true)
+ assert(t, err == nil, "")
+
+ b, err := wtx.CreateBucket([]byte("test"))
+ assert(t, err == nil, "")
+
+ // and commit a large write
+ err = b.Put([]byte("foo"), make([]byte, testWriteSize))
+ assert(t, err == nil, "")
+
+ done := make(chan struct{})
+
+ go func() {
+ wtx.Commit()
+ done <- struct{}{}
+ }()
+
+ select {
+ case <-time.After(5 * time.Second):
+ t.Errorf("unexpected that the reader blocks writer")
+ case <-done:
+ }
+}
+
// TODO(benbjohnson): Test corruption at every byte of the first two pages.
// Ensure that a database cannot open a transaction when it's not open.