ClearPageElements supports clearing elements in both branch and leaf pages. Note if the ${abandonFreelist} is true, the freelist may be cleaned in the meta pages in the following two cases, and bbolt needs to scan the db to reconstruct free list. It may cause some delay on next startup, depending on
(path string, pgId common.Pgid, start, end int, abandonFreelist bool)
| 34 | // afterwards; the first return parameter will be true in such case. But if |
| 35 | // the freelist isn't synced at all, no warning message will be displayed. |
| 36 | func ClearPageElements(path string, pgId common.Pgid, start, end int, abandonFreelist bool) (bool, error) { |
| 37 | // Read the page |
| 38 | p, buf, err := guts_cli.ReadPage(path, uint64(pgId)) |
| 39 | if err != nil { |
| 40 | return false, fmt.Errorf("ReadPage failed: %w", err) |
| 41 | } |
| 42 | |
| 43 | if !p.IsLeafPage() && !p.IsBranchPage() { |
| 44 | return false, fmt.Errorf("can't clear elements in %q page", p.Typ()) |
| 45 | } |
| 46 | |
| 47 | elementCnt := int(p.Count()) |
| 48 | |
| 49 | if elementCnt == 0 { |
| 50 | return false, nil |
| 51 | } |
| 52 | |
| 53 | if start < 0 || start >= elementCnt { |
| 54 | return false, fmt.Errorf("the start index (%d) is out of range [0, %d)", start, elementCnt) |
| 55 | } |
| 56 | |
| 57 | if (end < 0 || end > elementCnt) && end != -1 { |
| 58 | return false, fmt.Errorf("the end index (%d) is out of range [0, %d]", end, elementCnt) |
| 59 | } |
| 60 | |
| 61 | if start > end && end != -1 { |
| 62 | return false, fmt.Errorf("the start index (%d) is bigger than the end index (%d)", start, end) |
| 63 | } |
| 64 | |
| 65 | if start == end { |
| 66 | return false, fmt.Errorf("invalid: the start index (%d) is equal to the end index (%d)", start, end) |
| 67 | } |
| 68 | |
| 69 | preOverflow := p.Overflow() |
| 70 | |
| 71 | var ( |
| 72 | dataWritten uint32 |
| 73 | ) |
| 74 | if end == int(p.Count()) || end == -1 { |
| 75 | inodes := common.ReadInodeFromPage(p) |
| 76 | inodes = inodes[:start] |
| 77 | |
| 78 | p.SetCount(uint16(start)) |
| 79 | // no need to write inode & data again, we just need to get |
| 80 | // the data size which will be kept. |
| 81 | dataWritten = common.UsedSpaceInPage(inodes, p) |
| 82 | } else { |
| 83 | inodes := common.ReadInodeFromPage(p) |
| 84 | inodes = append(inodes[:start], inodes[end:]...) |
| 85 | |
| 86 | p.SetCount(uint16(len(inodes))) |
| 87 | dataWritten = common.WriteInodeToPage(inodes, p) |
| 88 | } |
| 89 | |
| 90 | pageSize, _, err := guts_cli.ReadPageAndHWMSize(path) |
| 91 | if err != nil { |
| 92 | return false, fmt.Errorf("ReadPageAndHWMSize failed: %w", err) |
| 93 | } |
no test coverage detected