// 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 %s: %s", nm, err) } // store fileBytes data, e := json.Marshal(nm.mapMetric) if e != nil { return fmt.Errorf("error marshaling metric %s: %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 := nakeFilename(cdbName) if err = os.Rename(fnames[0], bn+".1"+ext); err != nil { return err } return os.Rename(fnames[1], bn+".2"+ext) }
func (nm *NeedleMap) Put(key uint64, offset uint32, size uint32) (int, error) { oldSize := nm.m.Set(Key(key), offset, size) util.Uint64toBytes(nm.bytes[0:8], key) util.Uint32toBytes(nm.bytes[8:12], offset) util.Uint32toBytes(nm.bytes[12:16], size) nm.fileCounter++ nm.fileByteCounter = nm.fileByteCounter + uint64(size) if oldSize > 0 { nm.deletionCounter++ nm.deletionByteCounter = nm.deletionByteCounter + uint64(oldSize) } return nm.indexFile.Write(nm.bytes) }
func (nm *NeedleMap) Delete(key uint64) error { nm.DeletionByteCounter = nm.DeletionByteCounter + uint64(nm.m.Delete(Key(key))) bytes := make([]byte, 16) util.Uint64toBytes(bytes[0:8], key) util.Uint32toBytes(bytes[8:12], 0) util.Uint32toBytes(bytes[12:16], 0) if _, err := nm.indexFile.Seek(0, 2); err != nil { return fmt.Errorf("cannot go to the end of indexfile %s: %s", nm.indexFile.Name(), err.Error()) } if _, err := nm.indexFile.Write(bytes); err != nil { return fmt.Errorf("error writing to indexfile %s: %s", nm.indexFile.Name(), err.Error()) } nm.DeletionCounter++ return nil }
func (nm *NeedleMap) Delete(key uint64) error { nm.deletionByteCounter = nm.deletionByteCounter + uint64(nm.m.Delete(Key(key))) offset, err := nm.indexFile.Seek(0, 1) if err != nil { return fmt.Errorf("cannot get position of indexfile: %s", err) } util.Uint64toBytes(nm.bytes[0:8], key) util.Uint32toBytes(nm.bytes[8:12], 0) util.Uint32toBytes(nm.bytes[12:16], 0) if _, err = nm.indexFile.Write(nm.bytes); err != nil { nm.indexFile.Truncate(offset) return fmt.Errorf("error writing to indexfile %s: %s", nm.indexFile, err) } nm.deletionCounter++ return nil }
func (nm *NeedleMap) Put(key uint64, offset uint32, size uint32) (int, error) { if key > nm.MaximumFileKey { nm.MaximumFileKey = key } oldSize := nm.m.Set(Key(key), offset, size) bytes := make([]byte, 16) util.Uint64toBytes(bytes[0:8], key) util.Uint32toBytes(bytes[8:12], offset) util.Uint32toBytes(bytes[12:16], size) nm.FileCounter++ nm.FileByteCounter = nm.FileByteCounter + uint64(size) if oldSize > 0 { nm.DeletionCounter++ nm.DeletionByteCounter = nm.DeletionByteCounter + uint64(oldSize) } return nm.indexFile.Write(bytes) }
func (n *FileId) String() string { bytes := make([]byte, 12) util.Uint64toBytes(bytes[0:8], n.Key) util.Uint32toBytes(bytes[8:12], n.Hashcode) nonzero_index := 0 for ; bytes[nonzero_index] == 0; nonzero_index++ { } return n.VolumeId.String() + "," + hex.EncodeToString(bytes[nonzero_index:]) }
func (nm *NeedleMap) Put(key uint64, offset uint32, size uint32) (int, error) { if key > nm.MaximumFileKey { nm.MaximumFileKey = key } oldSize := nm.m.Set(Key(key), offset, size) bytes := make([]byte, 16) util.Uint64toBytes(bytes[0:8], key) util.Uint32toBytes(bytes[8:12], offset) util.Uint32toBytes(bytes[12:16], size) nm.FileCounter++ nm.FileByteCounter = nm.FileByteCounter + uint64(size) if oldSize > 0 { nm.DeletionCounter++ nm.DeletionByteCounter = nm.DeletionByteCounter + uint64(oldSize) } if _, err := nm.indexFile.Seek(0, 2); err != nil { return 0, fmt.Errorf("cannot go to the end of indexfile %s: %s", nm.indexFile.Name(), err.Error()) } return nm.indexFile.Write(bytes) }
func (nm *NeedleMap) Delete(key uint64) error { nm.DeletionByteCounter = nm.DeletionByteCounter + uint64(nm.m.Delete(Key(key))) offset, err := nm.indexFile.Seek(0, 1) if err != nil { return fmt.Errorf("cannot get position of indexfile: %s", err) } bytes := make([]byte, 16) util.Uint64toBytes(bytes[0:8], key) util.Uint32toBytes(bytes[8:12], 0) util.Uint32toBytes(bytes[12:16], 0) if _, err = nm.indexFile.Write(bytes); err != nil { plus := "" if e := nm.indexFile.Truncate(offset); e != nil { plus = "\ncouldn't truncate index file: " + e.Error() } return fmt.Errorf("error writing to indexfile %s: %s%s", nm.indexFile.Name(), err, plus) } nm.DeletionCounter++ return nil }
func (n *Needle) Append(w io.Writer, version Version) (size uint32, err error) { if s, ok := w.(io.Seeker); ok { if end, e := s.Seek(0, 1); e == nil { defer func(s io.Seeker, off int64) { if err != nil { if _, e = s.Seek(off, 0); e != nil { log.Printf("Failed to seek %s back to %d with error: %s\n", w, off, e) } } }(s, end) } else { err = fmt.Errorf("Cnnot Read Current Volume Position: %s", e) return } } switch version { case Version1: header := make([]byte, NeedleHeaderSize) util.Uint32toBytes(header[0:4], n.Cookie) util.Uint64toBytes(header[4:12], n.Id) n.Size = uint32(len(n.Data)) size = n.Size util.Uint32toBytes(header[12:16], n.Size) if _, err = w.Write(header); err != nil { return } if _, err = w.Write(n.Data); err != nil { return } padding := NeedlePaddingSize - ((NeedleHeaderSize + n.Size + NeedleChecksumSize) % NeedlePaddingSize) util.Uint32toBytes(header[0:NeedleChecksumSize], n.Checksum.Value()) _, err = w.Write(header[0 : NeedleChecksumSize+padding]) return case Version2: header := make([]byte, NeedleHeaderSize) util.Uint32toBytes(header[0:4], n.Cookie) util.Uint64toBytes(header[4:12], n.Id) n.DataSize, n.NameSize, n.MimeSize = uint32(len(n.Data)), uint8(len(n.Name)), uint8(len(n.Mime)) if n.DataSize > 0 { n.Size = 4 + n.DataSize + 1 if n.HasName() { n.Size = n.Size + 1 + uint32(n.NameSize) } if n.HasMime() { n.Size = n.Size + 1 + uint32(n.MimeSize) } if n.HasLastModifiedDate() { n.Size = n.Size + LastModifiedBytesLength } } size = n.DataSize util.Uint32toBytes(header[12:16], n.Size) if _, err = w.Write(header); err != nil { return } if n.DataSize > 0 { util.Uint32toBytes(header[0:4], n.DataSize) if _, err = w.Write(header[0:4]); err != nil { return } if _, err = w.Write(n.Data); err != nil { return } util.Uint8toBytes(header[0:1], n.Flags) if _, err = w.Write(header[0:1]); err != nil { return } if n.HasName() { util.Uint8toBytes(header[0:1], n.NameSize) if _, err = w.Write(header[0:1]); err != nil { return } if _, err = w.Write(n.Name); err != nil { return } } if n.HasMime() { util.Uint8toBytes(header[0:1], n.MimeSize) if _, err = w.Write(header[0:1]); err != nil { return } if _, err = w.Write(n.Mime); err != nil { return } } if n.HasLastModifiedDate() { util.Uint64toBytes(header[0:8], n.LastModified) if _, err = w.Write(header[8-LastModifiedBytesLength : 8]); err != nil { return } } } padding := NeedlePaddingSize - ((NeedleHeaderSize + n.Size + NeedleChecksumSize) % NeedlePaddingSize) util.Uint32toBytes(header[0:NeedleChecksumSize], n.Checksum.Value()) _, err = w.Write(header[0 : NeedleChecksumSize+padding]) return n.DataSize, err } return 0, fmt.Errorf("Unsupported Version! (%d)", version) }
func (n *Needle) Etag() string { bits := make([]byte, 4) util.Uint32toBytes(bits, uint32(n.Checksum)) return fmt.Sprintf("%x", bits) }