| 242 | } |
| 243 | |
| 244 | func (s *Store) compact(footer *Footer, partialCompactStart int, |
| 245 | higher Snapshot, persistOptions StorePersistOptions) error { |
| 246 | startTime := time.Now() |
| 247 | |
| 248 | var newSS *segmentStack // Segments to compact (all segs when full compaction). |
| 249 | var newBase *segmentStack // Segments not compacted (nil when full compaction). |
| 250 | |
| 251 | if higher != nil { |
| 252 | ssHigher, ok := higher.(*segmentStack) |
| 253 | if !ok { |
| 254 | return fmt.Errorf("store_compact: higher not a segmentStack") |
| 255 | } |
| 256 | |
| 257 | if ssHigher.isEmpty() && len(footer.SegmentLocs) <= 1 { |
| 258 | // No incoming data to persist and 1 or fewer footer segments. |
| 259 | return ErrNothingToCompact |
| 260 | } |
| 261 | |
| 262 | ssHigher.ensureFullySorted() |
| 263 | |
| 264 | newSS, newBase = s.mergeSegStacks(footer, partialCompactStart, ssHigher) |
| 265 | } else { |
| 266 | newSS = footer.ss // Safe as footer ref count is held positive. |
| 267 | if len(newSS.a) <= 1 { // No incoming data & 1 or fewer footer segments. |
| 268 | return ErrNothingToCompact // no need to perform compaction. |
| 269 | } |
| 270 | } |
| 271 | |
| 272 | var frefCompact *FileRef |
| 273 | var fileCompact File |
| 274 | var err error |
| 275 | if partialCompactStart == 0 { |
| 276 | s.m.Lock() |
| 277 | frefCompact, fileCompact, err = s.startFileLOCKED() |
| 278 | s.m.Unlock() |
| 279 | } else { |
| 280 | frefCompact, fileCompact, err = s.startOrReuseFile() |
| 281 | } |
| 282 | if err != nil { |
| 283 | return err |
| 284 | } |
| 285 | defer frefCompact.DecRef() |
| 286 | |
| 287 | syncAfterBytes := 0 |
| 288 | if s.options != nil { |
| 289 | syncAfterBytes = s.options.CompactionSyncAfterBytes |
| 290 | if syncAfterBytes == 0 { |
| 291 | syncAfterBytes = DefaultStoreOptions.CompactionSyncAfterBytes |
| 292 | } |
| 293 | } |
| 294 | |
| 295 | compactFooter, err := s.writeSegments(newSS, newBase, |
| 296 | frefCompact, |
| 297 | fileCompact, |
| 298 | partialCompactStart != 0, // Include deletions for partialCompactions. |
| 299 | syncAfterBytes) |
| 300 | if err != nil { |
| 301 | if partialCompactStart == 0 { |