// Copyright (c) 2013, Suryandaru Triandana // All rights reserved. // // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. package storage import ( "bytes" "os" "sync" "github.com/syndtr/goleveldb/leveldb/util" ) const typeShift = 3 type memStorageLock struct { ms *memStorage } func (lock *memStorageLock) Release() { ms := lock.ms ms.mu.Lock() defer ms.mu.Unlock() if ms.slock == lock { ms.slock = nil } return } // memStorage is a memory-backed storage. type memStorage struct { mu sync.Mutex slock *memStorageLock files map[uint64]*memFile manifest *memFilePtr } // NewMemStorage returns a new memory-backed storage implementation. func NewMemStorage() Storage { return &memStorage{ files: make(map[uint64]*memFile), } } func (ms *memStorage) Lock() (util.Releaser, error) { ms.mu.Lock() defer ms.mu.Unlock() if ms.slock != nil { return nil, ErrLocked } ms.slock = &memStorageLock{ms: ms} return ms.slock, nil } func (*memStorage) Log(str string) {} func (ms *memStorage) GetFile(num uint64, t FileType) File { return &memFilePtr{ms: ms, num: num, t: t} } func (ms *memStorage) GetFiles(t FileType) ([]File, error) { ms.mu.Lock() var ff []File for x, _ := range ms.files { num, mt := x>>typeShift, FileType(x)&TypeAll if mt&t == 0 { continue } ff = append(ff, &memFilePtr{ms: ms, num: num, t: mt}) } ms.mu.Unlock() return ff, nil } func (ms *memStorage) GetManifest() (File, error) { ms.mu.Lock() defer ms.mu.Unlock() if ms.manifest == nil { return nil, os.ErrNotExist } return ms.manifest, nil } func (ms *memStorage) SetManifest(f File) error { fm, ok := f.(*memFilePtr) if !ok || fm.t != TypeManifest { return ErrInvalidFile } ms.mu.Lock() ms.manifest = fm ms.mu.Unlock() return nil } func (*memStorage) Close() error { return nil } type memReader struct { *bytes.Reader m *memFile } func (mr *memReader) Close() error { return mr.m.Close() } type memFile struct { bytes.Buffer ms *memStorage open bool } func (*memFile) Sync() error { return nil } func (m *memFile) Close() error { m.ms.mu.Lock() m.open = false m.ms.mu.Unlock() return nil } type memFilePtr struct { ms *memStorage num uint64 t FileType } func (p *memFilePtr) x() uint64 { return p.Num()<