levels.go
func (s *levelsController) dropPrefix(prefix []byte) error {
	opt := s.kv.opt
	for _, l := range s.levels {
		l.RLock()
		if l.level == 0 {
			size := len(l.tables)
			l.RUnlock()

			if size > 0 {
				cp := compactionPriority{
					level: 0,
					score: 1.74,
					// A unique number greater than 1.0 does two things. Helps identify this
					// function in logs, and forces a compaction.
					dropPrefix: prefix,
				}
				if err := s.doCompact(cp); err != nil {
					opt.Warningf("While compacting level 0: %v", err)
					return nil
				}
			}
			continue
		}

		var tables []*table.Table
		for _, table := range l.tables {
			var absent bool
			switch {
			case bytes.HasPrefix(table.Smallest(), prefix):
			case bytes.HasPrefix(table.Biggest(), prefix):
			case bytes.Compare(prefix, table.Smallest()) > 0 &&
				bytes.Compare(prefix, table.Biggest()) < 0:
			default:
				absent = true
			}
			if !absent {
				tables = append(tables, table)
			}
		}
		l.RUnlock()
		if len(tables) == 0 {
			continue
		}

		cd := compactDef{
			elog:       trace.New(fmt.Sprintf("Badger.L%d", l.level), "Compact"),
			thisLevel:  l,
			nextLevel:  l,
			top:        []*table.Table{},
			bot:        tables,
			dropPrefix: prefix,
		}
		if err := s.runCompactDef(l.level, cd); err != nil {
			opt.Warningf("While running compact def: %+v. Error: %v", cd, err)
			return err
		}
	}
	return nil
}
func (s *levelsController) dropPrefix(prefix []byte) error {
	opt := s.kv.opt
	for _, l := range s.levels {
		l.RLock()
		if l.level == 0 {
			size := len(l.tables)
			l.RUnlock()

			if size > 0 {
				cp := compactionPriority{
					level: 0,
					score: 1.74,
					// A unique number greater than 1.0 does two things. Helps identify this
					// function in logs, and forces a compaction.
					dropPrefix: prefix,
				}
				if err := s.doCompact(cp); err != nil {
					opt.Warningf("While compacting level 0: %v", err)
					return nil
				}
			}
			continue
		}

		var tables []*table.Table
		for _, table := range l.tables {
			var absent bool
			switch {
			case bytes.HasPrefix(table.Smallest(), prefix):
			case bytes.HasPrefix(table.Biggest(), prefix):
			case bytes.Compare(prefix, table.Smallest()) > 0 &&
				bytes.Compare(prefix, table.Biggest()) < 0:
			default:
				absent = true
			}
			if !absent {
				tables = append(tables, table)
			}
		}
		l.RUnlock()
		if len(tables) == 0 {
			continue
		}

		cd := compactDef{
			elog:       trace.New(fmt.Sprintf("Badger.L%d", l.level), "Compact"),
			thisLevel:  l,
			nextLevel:  l,
			top:        []*table.Table{},
			bot:        tables,
			dropPrefix: prefix,
		}
		if err := s.runCompactDef(l.level, cd); err != nil {
			opt.Warningf("While running compact def: %+v. Error: %v", cd, err)
			return err
		}
	}
	return nil
}
// dropPrefix runs a L0->L1 compaction, and then runs same level compaction on the rest of the
// levels. For L0->L1 compaction, it runs compactions normally, but skips over all the keys with the
// provided prefix. For Li->Li compactions, it picks up the tables which would have the prefix. The
// tables who only have keys with this prefix are quickly dropped. The ones which have other keys
// are run through MergeIterator and compacted to create new tables. All the mechanisms of
// compactions apply, i.e. level sizes and MANIFEST are updated as in the normal flow.