leveldb: DB.tableRangeCompaction: retry 'all level' compaction until nothing to compact; and don't limit single level compaction
diff --git a/leveldb/db_compaction.go b/leveldb/db_compaction.go
index 333ea9b..8b8dc4a 100644
--- a/leveldb/db_compaction.go
+++ b/leveldb/db_compaction.go
@@ -574,23 +574,33 @@
db.logf("table@compaction range L%d %q:%q", level, umin, umax)
if level >= 0 {
- if c := db.s.getCompactionRange(level, umin, umax); c != nil {
+ if c := db.s.getCompactionRange(level, umin, umax, true); c != nil {
db.tableCompaction(c, true)
}
} else {
- // Scan for maximum level with overlapped tables.
- v := db.s.version()
- m := 1
- for i, t := range v.tables[1:] {
- if t.overlaps(db.s.icmp, umin, umax, false) {
- m = i + 1
- }
- }
- v.release()
+ // Retry until nothing to compact.
+ for {
+ compacted := false
- for level := 0; level < m; level++ {
- if c := db.s.getCompactionRange(level, umin, umax); c != nil {
- db.tableCompaction(c, true)
+ // Scan for maximum level with overlapped tables.
+ v := db.s.version()
+ m := 1
+ for i, t := range v.tables[1:] {
+ if t.overlaps(db.s.icmp, umin, umax, false) {
+ m = i + 1
+ }
+ }
+ v.release()
+
+ for level := 0; level < m; level++ {
+ if c := db.s.getCompactionRange(level, umin, umax, false); c != nil {
+ db.tableCompaction(c, true)
+ compacted = true
+ }
+ }
+
+ if !compacted {
+ break
}
}
}
diff --git a/leveldb/session_compaction.go b/leveldb/session_compaction.go
index 7c5a794..36aa1d8 100644
--- a/leveldb/session_compaction.go
+++ b/leveldb/session_compaction.go
@@ -73,7 +73,7 @@
}
// Create compaction from given level and range; need external synchronization.
-func (s *session) getCompactionRange(level int, umin, umax []byte) *compaction {
+func (s *session) getCompactionRange(level int, umin, umax []byte, noLimit bool) *compaction {
v := s.version()
t0 := v.tables[level].getOverlaps(nil, s.icmp, umin, umax, level == 0)
@@ -86,7 +86,7 @@
// But we cannot do this for level-0 since level-0 files can overlap
// and we must not pick one file and drop another older file if the
// two files overlap.
- if level > 0 {
+ if !noLimit && level > 0 {
limit := uint64(v.s.o.GetCompactionSourceLimit(level))
total := uint64(0)
for i, t := range t0 {