Flatten can be used to force compactions on the LSM tree so all the tables fall on the same level. This ensures that all the versions of keys are colocated and not split across multiple levels, which is necessary after a restore from backup. During Flatten, live compactions are stopped. Ideally, no
(workers int)
| 1430 | // stopped. Ideally, no writes are going on during Flatten. Otherwise, it would create competition |
| 1431 | // between flattening the tree and new tables being created at level zero. |
| 1432 | func (db *DB) Flatten(workers int) error { |
| 1433 | db.stopCompactions() |
| 1434 | defer db.startCompactions() |
| 1435 | |
| 1436 | compactAway := func(cp compactionPriority) error { |
| 1437 | db.opt.Infof("Attempting to compact with %+v\n", cp) |
| 1438 | errCh := make(chan error, 1) |
| 1439 | for i := 0; i < workers; i++ { |
| 1440 | go func() { |
| 1441 | errCh <- db.lc.doCompact(cp) |
| 1442 | }() |
| 1443 | } |
| 1444 | var success int |
| 1445 | var rerr error |
| 1446 | for i := 0; i < workers; i++ { |
| 1447 | err := <-errCh |
| 1448 | if err != nil { |
| 1449 | rerr = err |
| 1450 | db.opt.Warningf("While running doCompact with %+v. Error: %v\n", cp, err) |
| 1451 | } else { |
| 1452 | success++ |
| 1453 | } |
| 1454 | } |
| 1455 | if success == 0 { |
| 1456 | return rerr |
| 1457 | } |
| 1458 | // We could do at least one successful compaction. So, we'll consider this a success. |
| 1459 | db.opt.Infof("%d compactor(s) succeeded. One or more tables from level %d compacted.\n", |
| 1460 | success, cp.level) |
| 1461 | return nil |
| 1462 | } |
| 1463 | |
| 1464 | hbytes := func(sz int64) string { |
| 1465 | return humanize.Bytes(uint64(sz)) |
| 1466 | } |
| 1467 | |
| 1468 | for { |
| 1469 | db.opt.Infof("\n") |
| 1470 | var levels []int |
| 1471 | for i, l := range db.lc.levels { |
| 1472 | sz := l.getTotalSize() |
| 1473 | db.opt.Infof("Level: %d. %8s Size. %8s Max.\n", |
| 1474 | i, hbytes(l.getTotalSize()), hbytes(l.maxTotalSize)) |
| 1475 | if sz > 0 { |
| 1476 | levels = append(levels, i) |
| 1477 | } |
| 1478 | } |
| 1479 | if len(levels) <= 1 { |
| 1480 | prios := db.lc.pickCompactLevels() |
| 1481 | if len(prios) == 0 || prios[0].score <= 1.0 { |
| 1482 | db.opt.Infof("All tables consolidated into one level. Flattening done.\n") |
| 1483 | return nil |
| 1484 | } |
| 1485 | if err := compactAway(prios[0]); err != nil { |
| 1486 | return err |
| 1487 | } |
| 1488 | continue |
| 1489 | } |