242 lines
5.2 KiB
Go
242 lines
5.2 KiB
Go
|
package client
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"io"
|
||
|
|
||
|
"github.com/keegancsmith/rpc"
|
||
|
|
||
|
"forge.cadoles.com/arcad/edge/pkg/storage"
|
||
|
"forge.cadoles.com/arcad/edge/pkg/storage/rpc/server/blob"
|
||
|
"github.com/pkg/errors"
|
||
|
)
|
||
|
|
||
|
type BlobBucket struct {
|
||
|
name string
|
||
|
id blob.BucketID
|
||
|
client *rpc.Client
|
||
|
}
|
||
|
|
||
|
// Size implements storage.BlobBucket
|
||
|
func (b *BlobBucket) Size(ctx context.Context) (int64, error) {
|
||
|
args := blob.GetBucketSizeArgs{
|
||
|
BucketID: b.id,
|
||
|
}
|
||
|
|
||
|
reply := blob.GetBucketSizeReply{}
|
||
|
|
||
|
if err := b.client.Call(ctx, "Service.GetBucketSize", args, &reply); err != nil {
|
||
|
return 0, errors.WithStack(err)
|
||
|
}
|
||
|
|
||
|
return reply.Size, nil
|
||
|
}
|
||
|
|
||
|
// Name implements storage.BlobBucket
|
||
|
func (b *BlobBucket) Name() string {
|
||
|
return b.name
|
||
|
}
|
||
|
|
||
|
// Close implements storage.BlobBucket
|
||
|
func (b *BlobBucket) Close() error {
|
||
|
args := blob.CloseBucketArgs{
|
||
|
BucketID: b.id,
|
||
|
}
|
||
|
|
||
|
reply := blob.CloseBucketReply{}
|
||
|
|
||
|
if err := b.client.Call(context.Background(), "Service.CloseBucket", args, &reply); err != nil {
|
||
|
return errors.WithStack(err)
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// Delete implements storage.BlobBucket
|
||
|
func (b *BlobBucket) Delete(ctx context.Context, id storage.BlobID) error {
|
||
|
args := blob.DeleteBucketArgs{
|
||
|
BucketName: b.name,
|
||
|
}
|
||
|
|
||
|
reply := blob.DeleteBucketReply{}
|
||
|
|
||
|
if err := b.client.Call(context.Background(), "Service.DeleteBucket", args, &reply); err != nil {
|
||
|
return errors.WithStack(err)
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// Get implements storage.BlobBucket
|
||
|
func (b *BlobBucket) Get(ctx context.Context, id storage.BlobID) (storage.BlobInfo, error) {
|
||
|
args := blob.GetBlobInfoArgs{
|
||
|
Name: b.name,
|
||
|
BlobID: id,
|
||
|
}
|
||
|
|
||
|
reply := blob.GetBlobInfoReply{}
|
||
|
|
||
|
if err := b.client.Call(context.Background(), "Service.GetBlobInfo", args, &reply); err != nil {
|
||
|
return nil, errors.WithStack(err)
|
||
|
}
|
||
|
|
||
|
return reply.BlobInfo, nil
|
||
|
}
|
||
|
|
||
|
// List implements storage.BlobBucket
|
||
|
func (b *BlobBucket) List(ctx context.Context) ([]storage.BlobInfo, error) {
|
||
|
args := blob.ListBlobInfoArgs{
|
||
|
BucketID: b.id,
|
||
|
}
|
||
|
|
||
|
reply := blob.ListBlobInfoReply{}
|
||
|
|
||
|
if err := b.client.Call(context.Background(), "Service.ListBlobInfo", args, &reply); err != nil {
|
||
|
return nil, errors.WithStack(err)
|
||
|
}
|
||
|
|
||
|
return reply.BlobInfos, nil
|
||
|
}
|
||
|
|
||
|
// NewReader implements storage.BlobBucket
|
||
|
func (b *BlobBucket) NewReader(ctx context.Context, id storage.BlobID) (io.ReadSeekCloser, error) {
|
||
|
args := blob.NewBlobReaderArgs{
|
||
|
BucketID: b.id,
|
||
|
BlobID: id,
|
||
|
}
|
||
|
|
||
|
reply := blob.NewBlobReaderReply{}
|
||
|
|
||
|
if err := b.client.Call(context.Background(), "Service.NewBlobReader", args, &reply); err != nil {
|
||
|
return nil, errors.WithStack(err)
|
||
|
}
|
||
|
|
||
|
return &blobReaderCloser{
|
||
|
readerID: reply.ReaderID,
|
||
|
client: b.client,
|
||
|
}, nil
|
||
|
}
|
||
|
|
||
|
// NewWriter implements storage.BlobBucket
|
||
|
func (b *BlobBucket) NewWriter(ctx context.Context, id storage.BlobID) (io.WriteCloser, error) {
|
||
|
args := blob.NewBlobWriterArgs{
|
||
|
BucketID: b.id,
|
||
|
BlobID: id,
|
||
|
}
|
||
|
|
||
|
reply := blob.NewBlobWriterReply{}
|
||
|
|
||
|
if err := b.client.Call(context.Background(), "Service.NewBlobWriter", args, &reply); err != nil {
|
||
|
return nil, errors.WithStack(err)
|
||
|
}
|
||
|
|
||
|
return &blobWriterCloser{
|
||
|
blobID: id,
|
||
|
writerID: reply.WriterID,
|
||
|
client: b.client,
|
||
|
}, nil
|
||
|
}
|
||
|
|
||
|
type blobWriterCloser struct {
|
||
|
blobID storage.BlobID
|
||
|
writerID blob.WriterID
|
||
|
client *rpc.Client
|
||
|
}
|
||
|
|
||
|
// Write implements io.WriteCloser
|
||
|
func (bwc *blobWriterCloser) Write(data []byte) (int, error) {
|
||
|
args := blob.WriteBlobArgs{
|
||
|
WriterID: bwc.writerID,
|
||
|
Data: data,
|
||
|
}
|
||
|
|
||
|
reply := blob.WriteBlobReply{}
|
||
|
|
||
|
if err := bwc.client.Call(context.Background(), "Service.WriteBlob", args, &reply); err != nil {
|
||
|
return 0, errors.WithStack(err)
|
||
|
}
|
||
|
|
||
|
return reply.Written, nil
|
||
|
}
|
||
|
|
||
|
// Close implements io.WriteCloser
|
||
|
func (bwc *blobWriterCloser) Close() error {
|
||
|
args := blob.CloseWriterArgs{
|
||
|
WriterID: bwc.writerID,
|
||
|
}
|
||
|
|
||
|
reply := blob.CloseBucketReply{}
|
||
|
|
||
|
if err := bwc.client.Call(context.Background(), "Service.CloseWriter", args, &reply); err != nil {
|
||
|
return errors.WithStack(err)
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
type blobReaderCloser struct {
|
||
|
readerID blob.ReaderID
|
||
|
client *rpc.Client
|
||
|
}
|
||
|
|
||
|
// Read implements io.ReadSeekCloser
|
||
|
func (brc *blobReaderCloser) Read(p []byte) (int, error) {
|
||
|
args := blob.ReadBlobArgs{
|
||
|
ReaderID: brc.readerID,
|
||
|
Length: len(p),
|
||
|
}
|
||
|
|
||
|
reply := blob.ReadBlobReply{}
|
||
|
|
||
|
if err := brc.client.Call(context.Background(), "Service.ReadBlob", args, &reply); err != nil {
|
||
|
return 0, errors.WithStack(err)
|
||
|
}
|
||
|
|
||
|
copy(p, reply.Data)
|
||
|
|
||
|
if reply.EOF {
|
||
|
return reply.Read, io.EOF
|
||
|
}
|
||
|
|
||
|
return reply.Read, nil
|
||
|
}
|
||
|
|
||
|
// Seek implements io.ReadSeekCloser
|
||
|
func (brc *blobReaderCloser) Seek(offset int64, whence int) (int64, error) {
|
||
|
args := blob.SeekBlobArgs{
|
||
|
ReaderID: brc.readerID,
|
||
|
Offset: offset,
|
||
|
Whence: whence,
|
||
|
}
|
||
|
|
||
|
reply := blob.SeekBlobReply{}
|
||
|
|
||
|
if err := brc.client.Call(context.Background(), "Service.SeekBlob", args, &reply); err != nil {
|
||
|
return 0, errors.WithStack(err)
|
||
|
}
|
||
|
|
||
|
return reply.Read, nil
|
||
|
}
|
||
|
|
||
|
// Close implements io.ReadSeekCloser
|
||
|
func (brc *blobReaderCloser) Close() error {
|
||
|
args := blob.CloseReaderArgs{
|
||
|
ReaderID: brc.readerID,
|
||
|
}
|
||
|
|
||
|
reply := blob.CloseReaderReply{}
|
||
|
|
||
|
if err := brc.client.Call(context.Background(), "Service.CloseReader", args, &reply); err != nil {
|
||
|
return errors.WithStack(err)
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
var (
|
||
|
_ storage.BlobBucket = &BlobBucket{}
|
||
|
_ storage.BlobInfo = &BlobInfo{}
|
||
|
_ io.WriteCloser = &blobWriterCloser{}
|
||
|
_ io.ReadSeekCloser = &blobReaderCloser{}
|
||
|
)
|