作者:jgluc
项目:bazi
// Clone is like Get but clones the chunk if it's not already private.
// Chunks that are already private are returned as-is.
//
// A cloned chunk will have a buffer of size bytes. This is intended
// to use for re-inflating zero-trimmed chunks.
//
// Modifying the returned chunk *will* cause the locally stored data
// to change. This is the intended usage of a stash.
func (s *Stash) Clone(key cas.Key, typ string, level uint8, size uint32) (cas.Key, *chunks.Chunk, error) {
priv, ok := key.Private()
if ok {
chunk, ok := s.local[priv]
if !ok {
return key, nil, cas.NotFound{
Type: typ,
Level: level,
Key: key,
}
}
return key, chunk, nil
}
chunk, err := s.chunks.Get(key, typ, level)
if err != nil {
return key, nil, err
}
// clone the byte slice
tmp := make([]byte, size)
copy(tmp, chunk.Buf)
chunk.Buf = tmp
priv = s.ids.Get()
privkey := cas.NewKeyPrivateNum(priv)
s.local[priv] = chunk
return privkey, chunk, nil
}
作者:som-snyt
项目:bazi
func (blob *Blob) saveChunk(key cas.Key, level uint8) (cas.Key, error) {
if !key.IsPrivate() {
// already saved
return key, nil
}
chunk, err := blob.stash.Get(key, blob.m.Type, level)
if err != nil {
return key, err
}
if level > 0 {
for off := uint32(0); off+cas.KeySize <= uint32(len(chunk.Buf)); off += cas.KeySize {
cur := cas.NewKeyPrivate(chunk.Buf[off : off+cas.KeySize])
if cur.IsReserved() {
return key, fmt.Errorf("invalid stored key: key @%d in %v is %v", off, key, chunk.Buf[off:off+cas.KeySize])
}
// recurses at most `level` deep
saved, err := blob.saveChunk(cur, level-1)
if err != nil {
return key, err
}
copy(chunk.Buf[off:off+cas.KeySize], saved.Bytes())
}
}
chunk.Buf = trim(chunk.Buf)
return blob.stash.Save(key)
}
作者:jgluc
项目:bazi
// Drop forgets a Private chunk. The key may be reused, so caller must
// not remember the old key.
func (s *Stash) Drop(key cas.Key) {
priv, ok := key.Private()
if !ok {
return
}
s.drop(priv)
}
作者:voidExceptio
项目:bazi
func HandleGet(fn Handler, key cas.Key, typ string, level uint8) (*chunks.Chunk, error) {
if key.IsSpecial() {
if key == cas.Empty {
chunk := MakeChunk(typ, level, nil)
return chunk, nil
}
return nil, cas.NotFound{
Type: typ,
Level: level,
Key: key,
}
}
data, err := fn(key, typ, level)
if err != nil {
return nil, err
}
if data == nil {
return nil, cas.NotFound{
Type: typ,
Level: level,
Key: key,
}
}
chunk := MakeChunk(typ, level, data)
return chunk, nil
}
作者:jgluc
项目:bazi
func makeKey(key cas.Key, typ string, level uint8) []byte {
k := make([]byte, 0, cas.KeySize+len(typ)+1)
k = append(k, key.Bytes()...)
k = append(k, typ...)
k = append(k, level)
return k
}
作者:som-snyt
项目:bazi
func (m *Manifest) ToBlob(type_ string) (*blobs.Manifest, error) {
var k cas.Key
if err := k.UnmarshalBinary(m.Root); err != nil {
return nil, err
}
manifest := &blobs.Manifest{
Type: type_,
Root: k,
Size: m.Size,
ChunkSize: m.ChunkSize,
Fanout: m.Fanout,
}
return manifest, nil
}
作者:read-late
项目:bazi
func TestKeyUnmarshalBinaryBadLong(t *testing.T) {
KEY := strings.Repeat("borketyBorkBORK!", 4) + "x"
buf := []byte(KEY)
var k cas.Key
err := k.UnmarshalBinary(buf)
if err == nil {
t.Fatalf("unmarshal should have failed: %v", k)
}
e, ok := err.(*cas.BadKeySizeError)
if !ok {
t.Fatalf("unmarshal error is of wrong type: %T: %v", err, err)
}
if g, w := string(e.Key), KEY; g != w {
t.Errorf("BadKeySizeError Key is wrong: %x != %x", g, w)
}
}
作者:jgluc
项目:bazi
// Get returns a chunk either from the local stash, or from the
// Store (for Private keys).
//
// For Private keys, modifying the returned chunk *will* cause the
// locally stored data to change. This is the intended usage of a
// stash.
func (s *Stash) Get(key cas.Key, typ string, level uint8) (*chunks.Chunk, error) {
priv, ok := key.Private()
if ok {
chunk, ok := s.local[priv]
if !ok {
return nil, cas.NotFound{
Type: typ,
Level: level,
Key: key,
}
}
return chunk, nil
}
chunk, err := s.chunks.Get(key, typ, level)
return chunk, err
}
作者:read-late
项目:bazi
func (d *listSnaps) Lookup(ctx context.Context, name string) (fs.Node, error) {
var ref wire.SnapshotRef
lookup := func(tx *db.Tx) error {
bucket := d.fs.bucket(tx).SnapBucket()
if bucket == nil {
return errors.New("snapshot bucket missing")
}
buf := bucket.Get([]byte(name))
if buf == nil {
return fuse.ENOENT
}
if err := proto.Unmarshal(buf, &ref); err != nil {
return fmt.Errorf("corrupt snapshot reference: %q: %v", name, err)
}
return nil
}
if err := d.fs.db.View(lookup); err != nil {
return nil, err
}
var k cas.Key
if err := k.UnmarshalBinary(ref.Key); err != nil {
return nil, fmt.Errorf("corrupt snapshot reference: %q: %v", name, err)
}
chunk, err := d.fs.chunkStore.Get(k, "snap", 0)
if err != nil {
return nil, fmt.Errorf("cannot fetch snapshot: %v", err)
}
var snapshot wiresnap.Snapshot
err = proto.Unmarshal(chunk.Buf, &snapshot)
if err != nil {
return nil, fmt.Errorf("corrupt snapshot: %v: %v", ref.Key, err)
}
n, err := snap.Open(d.fs.chunkStore, snapshot.Contents)
if err != nil {
return nil, fmt.Errorf("cannot serve snapshot: %v", err)
}
return n, nil
}
作者:jgluc
项目:bazi
// Save the local Chunk to the Store.
//
// On success, the old key becomes invalid.
func (s *Stash) Save(key cas.Key) (cas.Key, error) {
priv, ok := key.Private()
if !ok {
return key, nil
}
chunk, ok := s.local[priv]
if !ok {
return key, cas.NotFound{
Key: key,
}
}
newkey, err := s.chunks.Add(chunk)
if err != nil {
return key, err
}
s.drop(priv)
return newkey, nil
}
作者:read-late
项目:bazi
// Mkdir takes a snapshot of this volume and records it under the
// given name.
func (d *listSnaps) Mkdir(ctx context.Context, req *fuse.MkdirRequest) (fs.Node, error) {
var snapshot *wiresnap.Snapshot
record := func(tx *db.Tx) error {
s, err := d.fs.Snapshot(ctx, tx)
if err != nil {
return err
}
snapshot = s
return nil
}
if err := d.fs.db.View(record); err != nil {
return nil, fmt.Errorf("cannot record snapshot: %v", err)
}
snapshot.Name = req.Name
var key cas.Key
{
buf, err := proto.Marshal(snapshot)
if err != nil {
return nil, fmt.Errorf("cannot marshal snapshot: %v", err)
}
if len(buf) == 0 {
return nil, errors.New("marshaled snapshot become empty; this is a bug")
}
// store the snapshot as a chunk, for disaster recovery
key, err = d.fs.chunkStore.Add(&chunks.Chunk{
Type: "snap",
Level: 0,
Buf: buf,
})
if err != nil {
return nil, fmt.Errorf("cannot store snapshot: %v", err)
}
}
var ref = wire.SnapshotRef{
Key: key.Bytes(),
}
buf, err := proto.Marshal(&ref)
if err != nil {
return nil, fmt.Errorf("cannot marshal snapshot pointer: %v", err)
}
add := func(tx *db.Tx) error {
b := d.fs.bucket(tx).SnapBucket()
if b == nil {
return errors.New("snapshot bucket missing")
}
return b.Put([]byte(req.Name), buf)
}
if err := d.fs.db.Update(add); err != nil {
return nil, fmt.Errorf("cannot save snapshot pointer: %v", err)
}
n, err := snap.Open(d.fs.chunkStore, snapshot.Contents)
if err != nil {
return nil, fmt.Errorf("cannot serve snapshot: %v", err)
}
return n, nil
}