Beispiel #1
0
// 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)
}
Beispiel #2
0
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)
}
Beispiel #3
0
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
}
Beispiel #4
0
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
}
Beispiel #5
0
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)
}
Beispiel #6
0
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:])
}
Beispiel #7
0
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)
}
Beispiel #8
0
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
}
Beispiel #9
0
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)
}
Beispiel #10
0
func (n *Needle) Etag() string {
	bits := make([]byte, 4)
	util.Uint32toBytes(bits, uint32(n.Checksum))
	return fmt.Sprintf("%x", bits)
}