diff options
Diffstat (limited to 'go/storage/cdb_map.go')
| -rw-r--r-- | go/storage/cdb_map.go | 238 |
1 files changed, 0 insertions, 238 deletions
diff --git a/go/storage/cdb_map.go b/go/storage/cdb_map.go deleted file mode 100644 index 8b70a1fd3..000000000 --- a/go/storage/cdb_map.go +++ /dev/null @@ -1,238 +0,0 @@ -package storage - -import ( - "encoding/json" - "errors" - "fmt" - "os" - "path/filepath" - - "github.com/chrislusf/weed-fs/go/util" - "github.com/tgulacsi/go-cdb" -) - -// CDB-backed read-only needle map -type cdbMap struct { - c1, c2 *cdb.Cdb - fn1, fn2 string - mapMetric -} - -const maxCdbRecCount = 100000000 - -var errReadOnly = errors.New("cannot modify a read-only map") - -// opens the cdb file(s) (base.cdb OR base.1.cdb AND base.2.cdb) -// in case of two files, the metric (at key 'M') must be in base.2.cdb -func OpenCdbMap(fileName string) (m *cdbMap, err error) { - m = new(cdbMap) - if m.c1, err = cdb.Open(fileName); err == nil { - m.fn1 = fileName - err = getMetric(m.c1, &m.mapMetric) - return - } - if os.IsNotExist(err) { - bn, ext := baseFilename(fileName) - m.fn1 = bn + ".1" + ext - if m.c1, err = cdb.Open(m.fn1); err != nil { - return nil, err - } - m.fn2 = bn + ".2" + ext - if m.c2, err = cdb.Open(m.fn2); err != nil { - return nil, err - } - err = getMetric(m.c2, &m.mapMetric) - return - } - return nil, err -} - -func (m *cdbMap) Put(key uint64, offset uint32, size uint32) (int, error) { - return -1, errReadOnly -} -func (m *cdbMap) Delete(key uint64) error { - return errReadOnly -} - -func (m *cdbMap) Close() { - if m.c2 != nil { - m.c2.Close() - m.c2 = nil - } - if m.c1 != nil { - m.c1.Close() - m.c1 = nil - } -} - -func (m *cdbMap) Destroy() error { - return errors.New("Can not delete readonly volumes") -} - -func (m cdbMap) ContentSize() uint64 { - return m.FileByteCounter -} -func (m cdbMap) DeletedSize() uint64 { - return m.DeletionByteCounter -} -func (m cdbMap) FileCount() int { - return m.FileCounter -} -func (m *cdbMap) DeletedCount() int { - return m.DeletionCounter -} -func (m *cdbMap) MaxFileKey() uint64 { - return m.MaximumFileKey -} - -func getMetric(c *cdb.Cdb, m *mapMetric) error { - data, err := c.Data([]byte{'M'}) - if err != nil { - return err - } - return json.Unmarshal(data, m) -} - -func (m cdbMap) Get(key uint64) (element *NeedleValue, ok bool) { - var ( - data []byte - k = make([]byte, 8) - err error - ) - util.Uint64toBytes(k, key) - if data, err = m.c1.Data(k); err != nil || data == nil { - if m.c2 == nil { - return nil, false - } - if data, err = m.c2.Data(k); err != nil || data == nil { - return nil, false - } - } - return &NeedleValue{Key: Key(key), Offset: util.BytesToUint32(data[:4]), - Size: util.BytesToUint32(data[4:])}, true -} - -func (m cdbMap) Visit(visit func(NeedleValue) error) (err error) { - fh, err := os.Open(m.fn1) - if err != nil { - return fmt.Errorf("cannot open %s: %s", m.fn1, err) - } - defer fh.Close() - walk := func(elt cdb.Element) error { - if len(elt.Key) != 8 { - return nil - } - return visit(NeedleValue{Key: Key(util.BytesToUint64(elt.Key)), - Offset: util.BytesToUint32(elt.Data[:4]), - Size: util.BytesToUint32(elt.Data[4:8])}) - } - if err = cdb.DumpMap(fh, walk); err != nil { - return err - } - if m.c2 == nil { - return nil - } - fh.Close() - if fh, err = os.Open(m.fn2); err != nil { - return fmt.Errorf("cannot open %s: %s", m.fn2, err) - } - return cdb.DumpMap(fh, walk) -} - -// converts an .idx index to a cdb -func ConvertIndexToCdb(cdbName string, index *os.File) error { - idx, err := LoadNeedleMap(index) - if err != nil { - return fmt.Errorf("error loading needle map %s: %s", index.Name(), err) - } - defer idx.Close() - return DumpNeedleMapToCdb(cdbName, idx) -} - -// dumps a NeedleMap into a cdb -func DumpNeedleMapToCdb(cdbName string, nm *NeedleMap) error { - tempnam := cdbName + "t" - fnames := make([]string, 1, 2) - adder, closer, err := openTempCdb(tempnam) - if err != nil { - return fmt.Errorf("error creating factory: %s", err) - } - fnames[0] = tempnam - - elt := cdb.Element{Key: make([]byte, 8), Data: make([]byte, 8)} - - fcount := uint64(0) - walk := func(key uint64, offset, size uint32) error { - if fcount >= maxCdbRecCount { - if err = closer(); err != nil { - return err - } - tempnam = cdbName + "t2" - if adder, closer, err = openTempCdb(tempnam); err != nil { - return fmt.Errorf("error creating second factory: %s", err) - } - fnames = append(fnames, tempnam) - fcount = 0 - } - util.Uint64toBytes(elt.Key, key) - util.Uint32toBytes(elt.Data[:4], offset) - util.Uint32toBytes(elt.Data[4:], size) - fcount++ - return adder(elt) - } - // and write out the cdb from there - err = nm.Visit(func(nv NeedleValue) error { - return walk(uint64(nv.Key), nv.Offset, nv.Size) - }) - if err != nil { - closer() - return fmt.Errorf("error walking index %v: %s", nm, err) - } - // store fileBytes - data, e := json.Marshal(nm.mapMetric) - if e != nil { - return fmt.Errorf("error marshaling metric %v: %s", nm.mapMetric, e) - } - if err = adder(cdb.Element{Key: []byte{'M'}, Data: data}); err != nil { - return err - } - if err = closer(); err != nil { - return err - } - - os.Remove(cdbName) - if len(fnames) == 1 { - return os.Rename(fnames[0], cdbName) - } - bn, ext := baseFilename(cdbName) - if err = os.Rename(fnames[0], bn+".1"+ext); err != nil { - return err - } - return os.Rename(fnames[1], bn+".2"+ext) -} - -func openTempCdb(fileName string) (cdb.AdderFunc, cdb.CloserFunc, error) { - fh, err := os.Create(fileName) - if err != nil { - return nil, nil, fmt.Errorf("cannot create cdb file %s: %v", fileName, err) - } - adder, closer, err := cdb.MakeFactory(fh) - if err != nil { - fh.Close() - return nil, nil, fmt.Errorf("error creating factory: %v", err) - } - return adder, func() error { - if e := closer(); e != nil { - fh.Close() - return e - } - fh.Close() - return nil - }, nil -} - -// returns filename without extension, and the extension -func baseFilename(fileName string) (string, string) { - ext := filepath.Ext(fileName) - return fileName[:len(fileName)-len(ext)], ext -} |
