Exemple #1
0
// Opens table. It returns a cache handle, which should
// be released after use.
func (t *tOps) open(f *tFile) (ch *cache.Handle, err error) {
	ch = t.cache.Get(0, uint64(f.fd.Num), func() (size int, value cache.Value) {
		var r storage.Reader
		r, err = t.s.stor.Open(f.fd)
		if err != nil {
			return 0, nil
		}

		var bcache *cache.NamespaceGetter
		if t.bcache != nil {
			bcache = &cache.NamespaceGetter{Cache: t.bcache, NS: uint64(f.fd.Num)}
		}

		var tr *table.Reader
		tr, err = table.NewReader(r, f.size, f.fd, bcache, t.bpool, t.s.o.Options)
		if err != nil {
			r.Close()
			return 0, nil
		}
		return 1, tr

	})
	if ch == nil && err == nil {
		err = ErrClosed
	}
	return
}
Exemple #2
0
func (t *tOps) lookup(f *tFile) (c cache.Object, err error) {
	num := f.file.Num()
	c, ok := t.cacheNS.Get(num, func() (ok bool, value interface{}, charge int, fin cache.SetFin) {
		var r storage.Reader
		r, err = f.file.Open()
		if err != nil {
			return
		}

		o := t.s.o

		var cacheNS cache.Namespace
		if bc := o.GetBlockCache(); bc != nil {
			cacheNS = bc.GetNamespace(num)
		}

		ok = true
		value = table.NewReader(r, int64(f.size), cacheNS, o)
		charge = 1
		fin = func() {
			r.Close()
		}
		return
	})
	if !ok && err == nil {
		err = ErrClosed
	}
	return
}
Exemple #3
0
// Opens table. It returns a cache handle, which should
// be released after use.
func (t *tOps) open(f *tFile) (ch *cache.Handle, err error) {
	num := f.file.Num()
	ch = t.cache.Get(0, num, func() (size int, value cache.Value) {
		var r storage.Reader
		r, err = f.file.Open()
		if err != nil {
			return 0, nil
		}

		var bcache *cache.CacheGetter
		if t.bcache != nil {
			bcache = &cache.CacheGetter{Cache: t.bcache, NS: num}
		}

		var tr *table.Reader
		tr, err = table.NewReader(r, int64(f.size), storage.NewFileInfo(f.file), bcache, t.bpool, t.s.o.Options)
		if err != nil {
			r.Close()
			return 0, nil
		}
		return 1, tr

	})
	if ch == nil && err == nil {
		err = ErrClosed
	}
	return
}
Exemple #4
0
// Opens table. It returns a cache handle, which should
// be released after use.
func (t *tOps) open(f *tFile) (ch cache.Handle, err error) {
	num := f.file.Num()
	ch = t.cacheNS.Get(num, func() (charge int, value interface{}) {
		var r storage.Reader
		r, err = f.file.Open()
		if err != nil {
			return 0, nil
		}

		var bcacheNS cache.Namespace
		if bc := t.s.o.GetBlockCache(); bc != nil {
			bcacheNS = bc.GetNamespace(num)
		}
		var tr *table.Reader
		tr, err = table.NewReader(r, int64(f.size), storage.NewFileInfo(f.file), bcacheNS, t.bpool, t.s.o.Options)
		if err != nil {
			r.Close()
			return 0, nil
		}
		return 1, tr
	})
	if ch == nil && err == nil {
		err = ErrClosed
	}
	return
}
Exemple #5
0
func (t *tOps) lookup(f *tFile) (c cache.Object, err error) {
	num := f.file.Num()

	c, _ = t.cachens.Get(num, func() (ok bool, value interface{}, charge int, fin func()) {
		var r storage.Reader
		r, err = f.file.Open()
		if err != nil {
			return
		}

		o := t.s.o

		var ns cache.Namespace
		bc := o.GetBlockCache()
		if bc != nil {
			ns = bc.GetNamespace(num)
		}

		var p *table.Reader
		p, err = table.NewReader(r, f.size, t.s.o, ns)
		if err != nil {
			return
		}

		ok = true
		value = p
		charge = 1
		fin = func() {
			r.Close()
		}

		return
	})

	return
}
Exemple #6
0
// Recover recovers and opens a DB with missing or corrupted manifest files
// for the given storage. It will ignore any manifest files, valid or not.
// The DB must already exist or it will returns an error.
// Also, Recover will ignore ErrorIfMissing and ErrorIfExist options.
//
// The DB must be closed after use, by calling Close method.
func Recover(p storage.Storage, o *opt.Options) (db *DB, err error) {
	s, err := newSession(p, o)
	if err != nil {
		return
	}
	defer func() {
		if err != nil {
			s.close()
			s.release()
		}
	}()

	// get all files
	ff0, err := s.getFiles(storage.TypeAll)
	if err != nil {
		return
	}

	ff := files(ff0)
	ff.sort()

	s.logf("db@recovery F·%d", len(ff))

	rec := new(sessionRecord)

	// recover tables
	var nt *tFile
	for _, f := range ff {
		if f.Type() != storage.TypeTable {
			continue
		}

		var r storage.Reader
		r, err = f.Open()
		if err != nil {
			return
		}
		var size int64
		size, err = r.Seek(0, 2)
		r.Close()
		if err != nil {
			return
		}

		t := newTFile(f, uint64(size), nil, nil)
		iter := s.tops.newIterator(t, nil, nil)
		// min ikey
		if iter.First() {
			t.min = iter.Key()
		} else {
			err = iter.Error()
			iter.Release()
			if err != nil {
				return
			} else {
				continue
			}
		}
		// max ikey
		if iter.Last() {
			t.max = iter.Key()
		} else {
			err = iter.Error()
			iter.Release()
			if err != nil {
				return
			} else {
				continue
			}
		}
		iter.Release()
		s.logf("db@recovery found table @%d S·%s %q:%q", t.file.Num(), shortenb(int(t.size)), t.min, t.max)
		// add table to level 0
		rec.addTableFile(0, t)
		nt = t
	}

	// extract largest seq number from newest table
	if nt != nil {
		var lseq uint64
		iter := s.tops.newIterator(nt, nil, nil)
		for iter.Next() {
			seq, _, ok := iKey(iter.Key()).parseNum()
			if !ok {
				continue
			}
			if seq > lseq {
				lseq = seq
			}
		}
		iter.Release()
		rec.setSeq(lseq)
	}

	// set file num based on largest one
	if len(ff) > 0 {
		s.stFileNum = ff[len(ff)-1].Num() + 1
	} else {
		s.stFileNum = 0
	}

	// create brand new manifest
	err = s.create()
	if err != nil {
		return
	}
	// commit record
	err = s.commit(rec)
	if err != nil {
		return
	}
	return openDB(s)
}