Exemple #1
0
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
	}
}
Exemple #2
0
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
}
Exemple #3
0
func newFileFromFile(f *os.File, simple bool) (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
	if !simple {
		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.NewSimpleFileFiler(f))
		filer = lldb.NewInnerFiler(filer, 16)
		switch simple {
		case true:
			f0 := filer
			if filer, err = lldb.NewRollbackFiler(
				filer,
				func(sz int64) error {
					return f0.Truncate(sz)
				},
				f0,
			); err != nil {
				return nil, err
			}
		default:
			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,
			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.NewSimpleFileFiler(f))
		filer = lldb.NewInnerFiler(filer, 16)
		switch simple {
		case true:
			f0 := filer
			if filer, err = lldb.NewRollbackFiler(
				filer,
				func(sz int64) error {
					return f0.Truncate(sz)
				},
				f0,
			); err != nil {
				return nil, err
			}
		default:
			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,
			f0:   f,
			f:    filer,
			id:   id,
			lck:  lck,
			name: f.Name(),
			wal:  w,
		}

		close, closew = false, false
		return s, nil
	}
}