func (o *Options) acidFiler(db *DB, f lldb.Filer) (r lldb.Filer, err error) { switch o._ACID { default: panic("internal error") case _ACIDTransactions: if r, err = lldb.NewRollbackFiler( f, func(sz int64) error { return f.Truncate(sz) }, f, ); err != nil { return nil, err } return r, nil case _ACIDFull: if r, err = lldb.NewACIDFiler(f, o.wal); err != nil { return nil, err } db.acidState = stIdle db.gracePeriod = o._GracePeriod if o._GracePeriod == 0 { panic("internal error") } return r, nil } }
func (o *Options) acidFiler(db *DB, f lldb.Filer) (r lldb.Filer, err error) { switch o.ACID { default: panic("internal error") case ACIDNone: r = f case ACIDTransactions: var rf *lldb.RollbackFiler if rf, err = lldb.NewRollbackFiler( f, func(sz int64) error { return f.Truncate(sz) }, f, ); err != nil { return } db.xact = true r = rf case ACIDFull: if r, err = lldb.NewACIDFiler(f, o.wal); err != nil { return } db.acidState = stIdle db.gracePeriod = o.GracePeriod db.xact = true if o.GracePeriod == 0 { db.acidState = stDisabled break } // Ensure GOMAXPROCS > 1, required for ACID FSM if n := runtime.GOMAXPROCS(0); n > 1 { return } runtime.GOMAXPROCS(2) } return }
func newFileFromOSFile(f lldb.OSFile) (fi *file, err error) { nm := lockName(f.Name()) lck, err := lock.Lock(nm) if err != nil { if lck != nil { lck.Close() } return nil, err } close := true defer func() { if close && lck != nil { lck.Close() } }() var w *os.File closew := false wn := walName(f.Name()) w, err = os.OpenFile(wn, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666) closew = true defer func() { if closew { nm := w.Name() w.Close() os.Remove(nm) w = nil } }() if err != nil { if !os.IsExist(err) { return nil, err } closew = false w, err = os.OpenFile(wn, os.O_RDWR, 0666) if err != nil { return nil, err } closew = true st, err := w.Stat() if err != nil { return nil, err } if st.Size() != 0 { return nil, fmt.Errorf("non empty WAL file %s exists", wn) } } info, err := f.Stat() if err != nil { return nil, err } switch sz := info.Size(); { case sz == 0: b := make([]byte, 16) copy(b, []byte(magic)) if _, err := f.Write(b); err != nil { return nil, err } filer := lldb.Filer(lldb.NewOSFiler(f)) filer = lldb.NewInnerFiler(filer, 16) if filer, err = lldb.NewACIDFiler(filer, w); err != nil { return nil, err } a, err := lldb.NewAllocator(filer, &lldb.Options{}) if err != nil { return nil, err } a.Compress = true s := &file{ a: a, codec: newGobCoder(), f0: f, f: filer, lck: lck, name: f.Name(), wal: w, } if err = s.BeginTransaction(); err != nil { return nil, err } h, err := s.Create() if err != nil { return nil, err } if h != 1 { // root log.Panic("internal error") } if h, err = s.a.Alloc(make([]byte, 8)); err != nil { return nil, err } if h != 2 { // id log.Panic("internal error") } close, closew = false, false return s, s.Commit() default: b := make([]byte, 16) if _, err := f.Read(b); err != nil { return nil, err } if string(b[:len(magic)]) != magic { return nil, fmt.Errorf("unknown file format") } filer := lldb.Filer(lldb.NewOSFiler(f)) filer = lldb.NewInnerFiler(filer, 16) if filer, err = lldb.NewACIDFiler(filer, w); err != nil { return nil, err } a, err := lldb.NewAllocator(filer, &lldb.Options{}) if err != nil { return nil, err } bid, err := a.Get(nil, 2) // id if err != nil { return nil, err } if len(bid) != 8 { return nil, fmt.Errorf("corrupted id |% x|", bid) } id := int64(0) for _, v := range bid { id = (id << 8) | int64(v) } a.Compress = true s := &file{ a: a, codec: newGobCoder(), f0: f, f: filer, id: id, lck: lck, name: f.Name(), wal: w, } close, closew = false, false return s, nil } }