From 082efcc23e41f42d15f9e90f4e079fdb793e997f Mon Sep 17 00:00:00 2001 From: Gyu-Ho Lee Date: Mon, 21 Dec 2015 15:28:44 -0800 Subject: 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. --- db_test.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'db_test.go') 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. -- cgit v1.2.3