2014-11-29 17:42:22 -05:00
|
|
|
package storage
|
2015-01-18 16:31:22 -05:00
|
|
|
|
2015-01-18 19:10:48 -05:00
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"io"
|
2015-01-20 21:39:30 -05:00
|
|
|
"log"
|
|
|
|
"strings"
|
|
|
|
"time"
|
2015-01-18 19:10:48 -05:00
|
|
|
)
|
2015-01-18 16:31:22 -05:00
|
|
|
|
2015-01-18 19:54:45 -05:00
|
|
|
type Storage struct {
|
2015-01-20 21:39:30 -05:00
|
|
|
data map[string]storedObject
|
2015-01-18 19:54:45 -05:00
|
|
|
}
|
2015-01-18 19:10:48 -05:00
|
|
|
|
2015-01-20 21:39:30 -05:00
|
|
|
type storedObject struct {
|
|
|
|
metadata ObjectMetadata
|
|
|
|
data []byte
|
|
|
|
}
|
|
|
|
|
|
|
|
type ObjectMetadata struct {
|
|
|
|
Key string
|
|
|
|
SecCreated int64
|
|
|
|
Size int
|
|
|
|
}
|
2015-01-20 19:08:14 -05:00
|
|
|
|
2015-01-19 20:39:20 -05:00
|
|
|
type GenericError struct {
|
|
|
|
bucket string
|
|
|
|
path string
|
|
|
|
}
|
|
|
|
|
|
|
|
type ObjectNotFound GenericError
|
|
|
|
|
|
|
|
func (self ObjectNotFound) Error() string {
|
|
|
|
return "Not Found: " + self.bucket + "#" + self.path
|
|
|
|
}
|
|
|
|
|
2015-01-20 22:13:57 -05:00
|
|
|
type ObjectExists struct {
|
|
|
|
bucket string
|
|
|
|
key string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (self ObjectExists) Error() string {
|
|
|
|
return "Object exists: " + self.bucket + "#" + self.key
|
|
|
|
}
|
|
|
|
|
2015-01-19 20:39:20 -05:00
|
|
|
func (storage *Storage) CopyObjectToWriter(w io.Writer, bucket string, object string) (int64, error) {
|
2015-01-18 19:10:48 -05:00
|
|
|
// TODO synchronize access
|
|
|
|
// get object
|
2015-01-18 19:54:45 -05:00
|
|
|
key := bucket + ":" + object
|
|
|
|
if val, ok := storage.data[key]; ok {
|
2015-01-20 21:39:30 -05:00
|
|
|
objectBuffer := bytes.NewBuffer(val.data)
|
2015-01-19 20:39:20 -05:00
|
|
|
written, err := io.Copy(w, objectBuffer)
|
|
|
|
return written, err
|
2015-01-18 19:54:45 -05:00
|
|
|
} else {
|
2015-01-19 20:39:20 -05:00
|
|
|
return 0, ObjectNotFound{bucket: bucket, path: object}
|
2015-01-18 19:54:45 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-20 22:13:57 -05:00
|
|
|
func (storage *Storage) StoreObject(bucket string, key string, data io.Reader) error {
|
2015-01-20 21:39:30 -05:00
|
|
|
objectKey := bucket + ":" + key
|
2015-01-20 22:13:57 -05:00
|
|
|
if _, ok := storage.data[objectKey]; ok == true {
|
|
|
|
return ObjectExists{bucket: bucket, key: key}
|
|
|
|
}
|
2015-01-18 19:54:45 -05:00
|
|
|
var bytesBuffer bytes.Buffer
|
2015-01-20 21:39:30 -05:00
|
|
|
newObject := storedObject{}
|
2015-01-18 19:54:45 -05:00
|
|
|
if _, ok := io.Copy(&bytesBuffer, data); ok == nil {
|
2015-01-20 21:39:30 -05:00
|
|
|
newObject.metadata = ObjectMetadata{
|
|
|
|
Key: key,
|
|
|
|
SecCreated: time.Now().Unix(),
|
|
|
|
Size: len(bytesBuffer.Bytes()),
|
|
|
|
}
|
|
|
|
newObject.data = bytesBuffer.Bytes()
|
2015-01-18 19:54:45 -05:00
|
|
|
}
|
2015-01-20 21:39:30 -05:00
|
|
|
storage.data[objectKey] = newObject
|
2015-01-20 22:13:57 -05:00
|
|
|
return nil
|
2015-01-18 19:10:48 -05:00
|
|
|
}
|
|
|
|
|
2015-01-20 19:08:14 -05:00
|
|
|
func (storage *Storage) ListObjects(bucket, prefix string, count int) []ObjectMetadata {
|
2015-01-20 21:39:30 -05:00
|
|
|
var results []ObjectMetadata
|
|
|
|
for key, object := range storage.data {
|
|
|
|
log.Println(key)
|
|
|
|
if strings.HasPrefix(key, bucket+":") {
|
|
|
|
results = append(results, object.metadata)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return results
|
2015-01-20 19:08:14 -05:00
|
|
|
}
|
|
|
|
|
2015-01-18 19:10:48 -05:00
|
|
|
func Start() (chan<- string, <-chan error, *Storage) {
|
2015-01-18 16:31:22 -05:00
|
|
|
ctrlChannel := make(chan string)
|
|
|
|
errorChannel := make(chan error)
|
|
|
|
go start(ctrlChannel, errorChannel)
|
2015-01-19 13:30:40 -05:00
|
|
|
return ctrlChannel, errorChannel, &Storage{
|
2015-01-20 21:39:30 -05:00
|
|
|
data: make(map[string]storedObject),
|
2015-01-19 13:30:40 -05:00
|
|
|
}
|
2015-01-18 16:31:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func start(ctrlChannel <-chan string, errorChannel chan<- error) {
|
|
|
|
close(errorChannel)
|
|
|
|
}
|