mirror of
https://github.com/minio/minio.git
synced 2025-01-12 15:33:22 -05:00
Working in memory donut driver
This commit is contained in:
parent
15d5e74837
commit
3e453a394a
@ -9,15 +9,15 @@ type DonutBox interface {
|
|||||||
|
|
||||||
// bucket operations
|
// bucket operations
|
||||||
CreateBucket(bucket string) error
|
CreateBucket(bucket string) error
|
||||||
ListObjects(bucket, prefix string) ([]string, error)
|
ListObjectsInBucket(bucket, prefix string) ([]string, error)
|
||||||
GetBucketMetadata(bucket, name string) (io.Reader, error)
|
GetBucketMetadata(bucket string) (map[string]string, error)
|
||||||
SetBucketMetadata(bucket, name string, metadata io.Reader) error
|
SetBucketMetadata(bucket string, metadata map[string]string) error
|
||||||
|
|
||||||
// object operations
|
// object operations
|
||||||
GetObjectWriter(bucket, object string, column, blockSize uint) *io.PipeWriter
|
GetObjectWriter(bucket, object string, column, blockSize uint) *io.PipeWriter
|
||||||
GetObjectReader(bucket, object string, column int) (io.Reader, error)
|
GetObjectReader(bucket, object string, column int) (io.Reader, error)
|
||||||
StoreObjectMetadata(bucket, object, name string, reader io.Reader) error
|
SetObjectMetadata(bucket, object string, metadata map[string]string) error
|
||||||
GetObjectMetadata(bucket, object, name string) (io.Reader, error)
|
GetObjectMetadata(bucket, object string) (map[string]string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Result is a result for async tasks
|
// Result is a result for async tasks
|
||||||
|
@ -39,11 +39,19 @@ func NewDonutMem() donutbox.DonutBox {
|
|||||||
|
|
||||||
// system operations
|
// system operations
|
||||||
func (donutMem donutMem) ListBuckets() ([]string, error) {
|
func (donutMem donutMem) ListBuckets() ([]string, error) {
|
||||||
return nil, errors.New("Not Implemented")
|
donutMem.lock.RLock()
|
||||||
|
defer donutMem.lock.RUnlock()
|
||||||
|
buckets := make([]string, 0)
|
||||||
|
for k, _ := range donutMem.buckets {
|
||||||
|
buckets = append(buckets, k)
|
||||||
|
}
|
||||||
|
return buckets, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// bucket operations
|
// bucket operations
|
||||||
func (donutMem donutMem) CreateBucket(b string) error {
|
func (donutMem donutMem) CreateBucket(b string) error {
|
||||||
|
donutMem.lock.Lock()
|
||||||
|
defer donutMem.lock.Unlock()
|
||||||
b = strings.ToLower(b)
|
b = strings.ToLower(b)
|
||||||
if _, ok := donutMem.buckets[b]; ok {
|
if _, ok := donutMem.buckets[b]; ok {
|
||||||
return errors.New("Bucket Exists")
|
return errors.New("Bucket Exists")
|
||||||
@ -60,16 +68,53 @@ func (donutMem donutMem) CreateBucket(b string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (donutMem donutMem) ListObjects(bucket, prefix string) ([]string, error) {
|
func (donutMem donutMem) ListObjectsInBucket(bucketKey, prefixKey string) ([]string, error) {
|
||||||
return nil, errors.New("Not Implemented")
|
donutMem.lock.RLock()
|
||||||
|
defer donutMem.lock.RUnlock()
|
||||||
|
if curBucket, ok := donutMem.buckets[bucketKey]; ok {
|
||||||
|
curBucket.lock.RLock()
|
||||||
|
defer curBucket.lock.RUnlock()
|
||||||
|
objects := make([]string, 0)
|
||||||
|
for objectKey, _ := range curBucket.objects {
|
||||||
|
if strings.HasPrefix(objectKey, prefixKey) {
|
||||||
|
objects = append(objects, objectKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return objects, nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("Bucket does not exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (donutMem donutMem) GetBucketMetadata(bucket, name string) (io.Reader, error) {
|
func (donutMem donutMem) GetBucketMetadata(bucketKey string) (map[string]string, error) {
|
||||||
return nil, errors.New("Not Implemented")
|
donutMem.lock.RLock()
|
||||||
|
defer donutMem.lock.RUnlock()
|
||||||
|
|
||||||
|
if curBucket, ok := donutMem.buckets[bucketKey]; ok {
|
||||||
|
curBucket.lock.RLock()
|
||||||
|
defer curBucket.lock.RUnlock()
|
||||||
|
result := make(map[string]string)
|
||||||
|
for k, v := range curBucket.metadata {
|
||||||
|
result[k] = v
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("Bucket not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (donutMem donutMem) SetBucketMetadata(bucket, name string, metadata io.Reader) error {
|
func (donutMem donutMem) SetBucketMetadata(bucketKey string, metadata map[string]string) error {
|
||||||
return errors.New("Not Implemented")
|
donutMem.lock.RLock()
|
||||||
|
defer donutMem.lock.RUnlock()
|
||||||
|
if curBucket, ok := donutMem.buckets[bucketKey]; ok {
|
||||||
|
curBucket.lock.Lock()
|
||||||
|
defer curBucket.lock.Unlock()
|
||||||
|
newMetadata := make(map[string]string)
|
||||||
|
for k, v := range metadata {
|
||||||
|
newMetadata[k] = v
|
||||||
|
}
|
||||||
|
curBucket.metadata = newMetadata
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return errors.New("Bucket not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
// object operations
|
// object operations
|
||||||
@ -137,10 +182,44 @@ func (donutMem donutMem) GetObjectReader(bucket, key string, column int) (io.Rea
|
|||||||
return nil, errors.New("Bucket not found")
|
return nil, errors.New("Bucket not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (donutMem donutMem) StoreObjectMetadata(bucket, object, name string, reader io.Reader) error {
|
func (donutMem donutMem) SetObjectMetadata(bucketKey, objectKey string, metadata map[string]string) error {
|
||||||
return errors.New("Not Implemented")
|
donutMem.lock.RLock()
|
||||||
|
defer donutMem.lock.RUnlock()
|
||||||
|
if curBucket, ok := donutMem.buckets[bucketKey]; ok {
|
||||||
|
curBucket.lock.RLock()
|
||||||
|
defer curBucket.lock.RUnlock()
|
||||||
|
if curObject, ok := curBucket.objects[objectKey]; ok {
|
||||||
|
curObject.lock.Lock()
|
||||||
|
defer curObject.lock.Unlock()
|
||||||
|
newMetadata := make(map[string]string)
|
||||||
|
for k, v := range metadata {
|
||||||
|
newMetadata[k] = v
|
||||||
|
}
|
||||||
|
curObject.metadata = newMetadata
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return errors.New("Object not found")
|
||||||
|
}
|
||||||
|
return errors.New("Bucket not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (donutMem donutMem) GetObjectMetadata(bucket, object, name string) (io.Reader, error) {
|
func (donutMem donutMem) GetObjectMetadata(bucketKey, objectKey string) (map[string]string, error) {
|
||||||
return nil, errors.New("Not Implemented")
|
donutMem.lock.RLock()
|
||||||
|
defer donutMem.lock.RUnlock()
|
||||||
|
|
||||||
|
if curBucket, ok := donutMem.buckets[bucketKey]; ok {
|
||||||
|
curBucket.lock.RLock()
|
||||||
|
defer curBucket.lock.RUnlock()
|
||||||
|
if curObject, ok := curBucket.objects[objectKey]; ok {
|
||||||
|
curObject.lock.RLock()
|
||||||
|
defer curObject.lock.RUnlock()
|
||||||
|
result := make(map[string]string)
|
||||||
|
for k, v := range curObject.metadata {
|
||||||
|
result[k] = v
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("Object not found")
|
||||||
|
}
|
||||||
|
return nil, errors.New("Bucket not found")
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,8 @@ import (
|
|||||||
|
|
||||||
. "gopkg.in/check.v1"
|
. "gopkg.in/check.v1"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test(t *testing.T) { TestingT(t) }
|
func Test(t *testing.T) { TestingT(t) }
|
||||||
@ -13,7 +15,7 @@ type MySuite struct{}
|
|||||||
|
|
||||||
var _ = Suite(&MySuite{})
|
var _ = Suite(&MySuite{})
|
||||||
|
|
||||||
func (s *MySuite) TestAPISuite(c *C) {
|
func (s *MySuite) TestCreateAndReadObject(c *C) {
|
||||||
data := "Hello World"
|
data := "Hello World"
|
||||||
donut := NewDonutMem()
|
donut := NewDonutMem()
|
||||||
|
|
||||||
@ -52,5 +54,95 @@ func (s *MySuite) TestAPISuite(c *C) {
|
|||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
result, err = ioutil.ReadAll(reader)
|
result, err = ioutil.ReadAll(reader)
|
||||||
c.Assert(result, DeepEquals, []byte(data))
|
c.Assert(result, DeepEquals, []byte(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MySuite) TestBucketList(c *C) {
|
||||||
|
donut := NewDonutMem()
|
||||||
|
|
||||||
|
results, err := donut.ListBuckets()
|
||||||
|
c.Assert(len(results), Equals, 0)
|
||||||
|
|
||||||
|
buckets := make([]string, 0)
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
bucket := "foo" + strconv.Itoa(i)
|
||||||
|
buckets = append(buckets, bucket)
|
||||||
|
err := donut.CreateBucket(bucket)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
}
|
||||||
|
sort.Strings(buckets)
|
||||||
|
results, err = donut.ListBuckets()
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
sort.Strings(results)
|
||||||
|
c.Assert(results, DeepEquals, buckets)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MySuite) TestObjectList(c *C) {
|
||||||
|
donut := NewDonutMem()
|
||||||
|
donut.CreateBucket("foo")
|
||||||
|
|
||||||
|
results, err := donut.ListObjectsInBucket("foo", "")
|
||||||
|
c.Assert(len(results), Equals, 0)
|
||||||
|
|
||||||
|
objects := make([]string, 0)
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
object := "foo" + strconv.Itoa(i)
|
||||||
|
objects = append(objects, object)
|
||||||
|
writer := donut.GetObjectWriter("foo", object, 0, 2)
|
||||||
|
writer.Write([]byte(object))
|
||||||
|
writer.Close()
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
}
|
||||||
|
sort.Strings(objects)
|
||||||
|
results, err = donut.ListObjectsInBucket("foo", "")
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
c.Assert(len(results), Equals, 10)
|
||||||
|
sort.Strings(results)
|
||||||
|
c.Assert(results, DeepEquals, objects)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MySuite) TestBucketMetadata(c *C) {
|
||||||
|
donut := NewDonutMem()
|
||||||
|
donut.CreateBucket("foo")
|
||||||
|
|
||||||
|
metadata := make(map[string]string)
|
||||||
|
|
||||||
|
metadata["hello"] = "world"
|
||||||
|
metadata["foo"] = "bar"
|
||||||
|
|
||||||
|
err := donut.SetBucketMetadata("foo", metadata)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
result, err := donut.GetBucketMetadata("foo")
|
||||||
|
c.Assert(result, DeepEquals, metadata)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MySuite) TestObjectMetadata(c *C) {
|
||||||
|
donut := NewDonutMem()
|
||||||
|
donut.CreateBucket("foo")
|
||||||
|
|
||||||
|
metadata := make(map[string]string)
|
||||||
|
|
||||||
|
metadata["hello"] = "world"
|
||||||
|
metadata["foo"] = "bar"
|
||||||
|
|
||||||
|
err := donut.SetObjectMetadata("foo", "bar", metadata)
|
||||||
|
c.Assert(err, Not(IsNil))
|
||||||
|
|
||||||
|
result, err := donut.GetObjectMetadata("foo", "bar")
|
||||||
|
c.Assert(result, IsNil)
|
||||||
|
c.Assert(err, Not(IsNil))
|
||||||
|
|
||||||
|
writer := donut.GetObjectWriter("foo", "bar", 0, 2)
|
||||||
|
_, err = writer.Write([]byte("Hello World"))
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
err = writer.Close()
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
err = donut.SetObjectMetadata("foo", "bar", metadata)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
result, err = donut.GetObjectMetadata("foo", "bar")
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
c.Assert(result, DeepEquals, metadata)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -29,10 +29,11 @@ type StorageDriver struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Start a single disk subsystem
|
// Start a single disk subsystem
|
||||||
func Start() (chan<- string, <-chan error, storage.Storage) {
|
func Start(donutBox donutbox.DonutBox) (chan<- string, <-chan error, storage.Storage) {
|
||||||
ctrlChannel := make(chan string)
|
ctrlChannel := make(chan string)
|
||||||
errorChannel := make(chan error)
|
errorChannel := make(chan error)
|
||||||
s := new(StorageDriver)
|
s := new(StorageDriver)
|
||||||
|
s.donutBox = donutBox
|
||||||
go start(ctrlChannel, errorChannel, s)
|
go start(ctrlChannel, errorChannel, s)
|
||||||
return ctrlChannel, errorChannel, s
|
return ctrlChannel, errorChannel, s
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ import (
|
|||||||
|
|
||||||
mstorage "github.com/minio-io/minio/pkg/storage"
|
mstorage "github.com/minio-io/minio/pkg/storage"
|
||||||
|
|
||||||
|
"github.com/minio-io/minio/pkg/donutbox/donutmem"
|
||||||
. "gopkg.in/check.v1"
|
. "gopkg.in/check.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -33,13 +34,13 @@ type MySuite struct{}
|
|||||||
var _ = Suite(&MySuite{})
|
var _ = Suite(&MySuite{})
|
||||||
|
|
||||||
func (s *MySuite) TestAPISuite(c *C) {
|
func (s *MySuite) TestAPISuite(c *C) {
|
||||||
c.Skip("Not implemented yet.")
|
//c.Skip("Not implemented yet.")
|
||||||
var storageList []string
|
var storageList []string
|
||||||
create := func() mstorage.Storage {
|
create := func() mstorage.Storage {
|
||||||
path, err := ioutil.TempDir(os.TempDir(), "minio-fs-")
|
path, err := ioutil.TempDir(os.TempDir(), "minio-fs-")
|
||||||
c.Check(err, IsNil)
|
c.Check(err, IsNil)
|
||||||
storageList = append(storageList, path)
|
storageList = append(storageList, path)
|
||||||
_, _, store := Start() // TODO Make InMemory driver
|
_, _, store := Start(donutmem.NewDonutMem()) // TODO Make InMemory driver
|
||||||
return store
|
return store
|
||||||
}
|
}
|
||||||
mstorage.APITestSuite(c, create)
|
mstorage.APITestSuite(c, create)
|
||||||
|
Loading…
Reference in New Issue
Block a user