From b7e0881df5079a7ef06851397e24741686091081 Mon Sep 17 00:00:00 2001 From: Armon Dadgar Date: Tue, 29 Apr 2014 16:01:20 -0700 Subject: [PATCH] consul: Hack around LMDB delete issue. Fixes #85. --- consul/mdb_table.go | 25 +++++++++++++++++++++++-- consul/mdb_table_test.go | 2 +- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/consul/mdb_table.go b/consul/mdb_table.go index c710e96ce2..96c1fad883 100644 --- a/consul/mdb_table.go +++ b/consul/mdb_table.go @@ -450,8 +450,29 @@ func (t *MDBTable) DeleteTxn(tx *MDBTxn, index string, parts ...string) (int, er } // deleteWithIndex deletes all associated rows while scanning -// a given index for a key prefix. -func (t *MDBTable) deleteWithIndex(tx *MDBTxn, idx *MDBIndex, key []byte) (num int, err error) { +// a given index for a key prefix. May perform multiple index traversals. +// This is a hack around a bug in LMDB which can cause a partial delete to +// take place. To fix this, we invoke the innerDelete until all rows are +// removed. This hack can be removed once the LMDB bug is resolved. +func (t *MDBTable) deleteWithIndex(tx *MDBTxn, idx *MDBIndex, key []byte) (int, error) { + var total int + var num int + var err error +DELETE: + num, err = t.innerDeleteWithIndex(tx, idx, key) + total += num + if err != nil { + return total, err + } + if num > 0 { + goto DELETE + } + return total, nil +} + +// innerDeleteWithIndex deletes all associated rows while scanning +// a given index for a key prefix. It only traverses the index a single time. +func (t *MDBTable) innerDeleteWithIndex(tx *MDBTxn, idx *MDBIndex, key []byte) (num int, err error) { // Handle an error while deleting defer func() { if r := recover(); r != nil { diff --git a/consul/mdb_table_test.go b/consul/mdb_table_test.go index d57a9bd6b2..2800c2a483 100644 --- a/consul/mdb_table_test.go +++ b/consul/mdb_table_test.go @@ -57,7 +57,7 @@ func testMDBEnv(t *testing.T) (string, *mdb.Env) { } // Increase the maximum map size - if err := env.SetMapSize(dbMaxMapSize); err != nil { + if err := env.SetMapSize(dbMaxMapSize32bit); err != nil { t.Fatalf("err: %v", err) }