db.go
func (db *DB) Flatten(workers int) error {
	db.stopCompactions()
	defer db.startCompactions()

	compactAway := func(cp compactionPriority) error {
		db.opt.Infof("Attempting to compact with %+v\n", cp)
		errCh := make(chan error, 1)
		for i := 0; i < workers; i++ {
			go func() {
				errCh <- db.lc.doCompact(cp)
			}()
		}
		var success int
		var rerr error
		for i := 0; i < workers; i++ {
			err := <-errCh
			if err != nil {
				rerr = err
				db.opt.Warningf("While running doCompact with %+v. Error: %v\n", cp, err)
			} else {
				success++
			}
		}
		if success == 0 {
			return rerr
		}
		// We could do at least one successful compaction. So, we'll consider this a success.
		db.opt.Infof("%d compactor(s) succeeded. One or more tables from level %d compacted.\n",
			success, cp.level)
		return nil
	}

	hbytes := func(sz int64) string {
		return humanize.Bytes(uint64(sz))
	}

	for {
		db.opt.Infof("\n")
		var levels []int
		for i, l := range db.lc.levels {
			sz := l.getTotalSize()
			db.opt.Infof("Level: %d. %8s Size. %8s Max.\n",
				i, hbytes(l.getTotalSize()), hbytes(l.maxTotalSize))
			if sz > 0 {
				levels = append(levels, i)
			}
		}
		if len(levels) <= 1 {
			prios := db.lc.pickCompactLevels()
			if len(prios) == 0 || prios[0].score <= 1.0 {
				db.opt.Infof("All tables consolidated into one level. Flattening done.\n")
				return nil
			}
			if err := compactAway(prios[0]); err != nil {
				return err
			}
			continue
		}
		// Create an artificial compaction priority, to ensure that we compact the level.
		cp := compactionPriority{level: levels[0], score: 1.71}
		if err := compactAway(cp); err != nil {
			return err
		}
	}
}
func (db *DB) Flatten(workers int) error {
	db.stopCompactions()
	defer db.startCompactions()

	compactAway := func(cp compactionPriority) error {
		db.opt.Infof("Attempting to compact with %+v\n", cp)
		errCh := make(chan error, 1)
		for i := 0; i < workers; i++ {
			go func() {
				errCh <- db.lc.doCompact(cp)
			}()
		}
		var success int
		var rerr error
		for i := 0; i < workers; i++ {
			err := <-errCh
			if err != nil {
				rerr = err
				db.opt.Warningf("While running doCompact with %+v. Error: %v\n", cp, err)
			} else {
				success++
			}
		}
		if success == 0 {
			return rerr
		}
		// We could do at least one successful compaction. So, we'll consider this a success.
		db.opt.Infof("%d compactor(s) succeeded. One or more tables from level %d compacted.\n",
			success, cp.level)
		return nil
	}

	hbytes := func(sz int64) string {
		return humanize.Bytes(uint64(sz))
	}

	for {
		db.opt.Infof("\n")
		var levels []int
		for i, l := range db.lc.levels {
			sz := l.getTotalSize()
			db.opt.Infof("Level: %d. %8s Size. %8s Max.\n",
				i, hbytes(l.getTotalSize()), hbytes(l.maxTotalSize))
			if sz > 0 {
				levels = append(levels, i)
			}
		}
		if len(levels) <= 1 {
			prios := db.lc.pickCompactLevels()
			if len(prios) == 0 || prios[0].score <= 1.0 {
				db.opt.Infof("All tables consolidated into one level. Flattening done.\n")
				return nil
			}
			if err := compactAway(prios[0]); err != nil {
				return err
			}
			continue
		}
		// Create an artificial compaction priority, to ensure that we compact the level.
		cp := compactionPriority{level: levels[0], score: 1.71}
		if err := compactAway(cp); err != nil {
			return err
		}
	}
}
func ( db * DB ) Flatten ( workers int ) error { db . stopCompactions ( ) defer db . startCompactions ( ) compactAway := func ( cp compactionPriority ) error { db . opt . Infof ( " \n " , cp ) errCh := make ( chan error , 1 ) for i := 0 ; i < workers ; i ++ { go func ( ) { errCh <- db . lc . doCompact ( cp ) } ( ) } var success int var rerr error for i := 0 ; i < workers ; i ++ { err := <- errCh if err != nil { rerr = err db . opt . Warningf ( " \n " , cp , err ) } else { success ++ } } if success == 0 { return rerr } // We could do at least one successful compaction. So, we'll consider this a success. db . opt . Infof ( " \n " , success , cp . level ) return nil } hbytes := func ( sz int64 ) string { return humanize . Bytes ( uint64 ( sz ) ) } for { db . opt . Infof ( " \n " ) var levels [ ] int for i , l := range db . lc . levels { sz := l . getTotalSize ( ) db . opt . Infof ( " \n " , i , hbytes ( l . getTotalSize ( ) ) , hbytes ( l . maxTotalSize ) ) if sz > 0 { levels = append ( levels , i ) } } if len ( levels ) <= 1 { prios := db . lc . pickCompactLevels ( ) if len ( prios ) == 0 || prios [ 0 ] . score <= 1.0 { db . opt . Infof ( " \n " ) return nil } if err := compactAway ( prios [ 0 ] ) ; err != nil { return err } continue } // Create an artificial compaction priority, to ensure that we compact the level. cp := compactionPriority { level : levels [ 0 ] , score : 1.71 } if err := compactAway ( cp ) ; err != nil { return err } } }
// 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 writes are going on during Flatten. Otherwise, it would create competition
// between flattening the tree and new tables being created at level zero.
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 writes are going on during Flatten . Otherwise it would create competition between flattening the tree and new tables being created at level zero .