func (s *file) CreateTemp(asc bool) (bt temp, err error) { f, err := s.tempFile("", "ql-tmp-") if err != nil { return nil, err } fn := f.Name() filer := lldb.NewOSFiler(f) a, err := lldb.NewAllocator(filer, &lldb.Options{}) if err != nil { f.Close() os.Remove(fn) return nil, err } k := 1 if !asc { k = -1 } t, _, err := lldb.CreateBTree(a, func(a, b []byte) int { //TODO w/ error return da, err := lldb.DecodeScalars(a) if err != nil { log.Panic(err) } if err = s.expandBytes(da); err != nil { log.Panic(err) } db, err := lldb.DecodeScalars(b) if err != nil { log.Panic(err) } if err = s.expandBytes(db); err != nil { log.Panic(err) } return k * collate(da, db) }) if err != nil { f.Close() if fn != "" { os.Remove(fn) } return nil, err } x := &fileTemp{file: &file{ a: a, codec: newGobCoder(), f0: f, }, t: t} return x, nil }
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 } }