DropPrefix would drop all the keys with the provided prefix. It does this in the following way: - Stop accepting new writes. - Stop memtable flushes before acquiring lock. Because we're acquring lock here and memtable flush stalls for lock, which leads to deadlock - Flush out all memtables, skipping
(prefixes ...[]byte)
| 1620 | // - Compact rest of the levels, Li->Li, picking tables which have Kp. |
| 1621 | // - Resume memtable flushes, compactions and writes. |
| 1622 | func (db *DB) DropPrefix(prefixes ...[]byte) error { |
| 1623 | db.opt.Infof("DropPrefix Called") |
| 1624 | f, err := db.prepareToDrop() |
| 1625 | if err != nil { |
| 1626 | return err |
| 1627 | } |
| 1628 | defer f() |
| 1629 | // Block all foreign interactions with memory tables. |
| 1630 | db.Lock() |
| 1631 | defer db.Unlock() |
| 1632 | |
| 1633 | db.imm = append(db.imm, db.mt) |
| 1634 | for _, memtable := range db.imm { |
| 1635 | if memtable.Empty() { |
| 1636 | memtable.DecrRef() |
| 1637 | continue |
| 1638 | } |
| 1639 | task := flushTask{ |
| 1640 | mt: memtable, |
| 1641 | // Ensure that the head of value log gets persisted to disk. |
| 1642 | vptr: db.vhead, |
| 1643 | dropPrefixes: prefixes, |
| 1644 | } |
| 1645 | db.opt.Debugf("Flushing memtable") |
| 1646 | if err := db.handleFlushTask(task); err != nil { |
| 1647 | db.opt.Errorf("While trying to flush memtable: %v", err) |
| 1648 | return err |
| 1649 | } |
| 1650 | memtable.DecrRef() |
| 1651 | } |
| 1652 | db.stopCompactions() |
| 1653 | defer db.startCompactions() |
| 1654 | db.imm = db.imm[:0] |
| 1655 | db.mt = skl.NewSkiplist(arenaSize(db.opt)) |
| 1656 | |
| 1657 | // Drop prefixes from the levels. |
| 1658 | if err := db.lc.dropPrefixes(prefixes); err != nil { |
| 1659 | return err |
| 1660 | } |
| 1661 | db.opt.Infof("DropPrefix done") |
| 1662 | return nil |
| 1663 | } |
| 1664 | |
| 1665 | // KVList contains a list of key-value pairs. |
| 1666 | type KVList = pb.KVList |