func (m *MemDB) NewSnapshot() (*Snapshot, error) { buf := m.snapshots.MakeBuf() defer m.snapshots.FreeBuf(buf) // Stitch all local gclists from all writers to create snapshot gclist var head, tail *skiplist.Node for w := m.wlist; w != nil; w = w.next { if tail == nil { head = w.gchead tail = w.gctail } else if w.gchead != nil { tail.GClink = w.gchead tail = w.gctail } w.gchead = nil w.gctail = nil // Update global stats m.store.Stats.Merge(&w.slSts1) atomic.AddInt64(&m.itemsCount, w.count) w.count = 0 } snap := &Snapshot{db: m, sn: m.getCurrSn(), refCount: 1, count: m.ItemsCount()} m.snapshots.Insert(unsafe.Pointer(snap), CompareSnapshot, buf, &m.snapshots.Stats) snap.gclist = head newSn := atomic.AddUint32(&m.currSn, 1) if newSn == math.MaxUint32 { return nil, ErrMaxSnapshotsLimitReached } return snap, nil }
func (w *Writer) DeleteNode(x *skiplist.Node) (success bool) { defer func() { if success { w.count -= 1 } }() x.GClink = nil sn := w.getCurrSn() gotItem := (*Item)(x.Item()) if gotItem.bornSn == sn { success = w.store.DeleteNode(x, w.insCmp, w.buf, &w.slSts1) barrier := w.store.GetAccesBarrier() barrier.FlushSession(unsafe.Pointer(x)) return } success = atomic.CompareAndSwapUint32(&gotItem.deadSn, 0, sn) if success { if w.gctail == nil { w.gctail = x w.gchead = w.gctail } else { w.gctail.GClink = x w.gctail = x } } return }