s3 API add ListObjectsV1

This commit is contained in:
Chris Lu 2018-07-22 01:14:36 -07:00
parent 922c614bde
commit 6319d84f42
11 changed files with 333 additions and 131 deletions

View file

@ -11,6 +11,7 @@ type MountOptions struct {
filerGrpcPort *int filerGrpcPort *int
filerMountRootPath *string filerMountRootPath *string
dir *string dir *string
dirListingLimit *int
collection *string collection *string
replication *string replication *string
ttlSec *int ttlSec *int
@ -28,6 +29,7 @@ func init() {
mountOptions.filerGrpcPort = cmdMount.Flag.Int("filer.grpc.port", 0, "filer grpc server listen port, default to http port + 10000") mountOptions.filerGrpcPort = cmdMount.Flag.Int("filer.grpc.port", 0, "filer grpc server listen port, default to http port + 10000")
mountOptions.filerMountRootPath = cmdMount.Flag.String("filer.path", "/", "mount this remote path from filer server") mountOptions.filerMountRootPath = cmdMount.Flag.String("filer.path", "/", "mount this remote path from filer server")
mountOptions.dir = cmdMount.Flag.String("dir", ".", "mount weed filer to this directory") mountOptions.dir = cmdMount.Flag.String("dir", ".", "mount weed filer to this directory")
mountOptions.dirListingLimit = cmdMount.Flag.Int("dirListLimit", 1000, "limit sub dir listing size")
mountOptions.collection = cmdMount.Flag.String("collection", "", "collection to create the files") mountOptions.collection = cmdMount.Flag.String("collection", "", "collection to create the files")
mountOptions.replication = cmdMount.Flag.String("replication", "000", "replication to create to files") mountOptions.replication = cmdMount.Flag.String("replication", "000", "replication to create to files")
mountOptions.ttlSec = cmdMount.Flag.Int("ttl", 0, "file ttl in seconds") mountOptions.ttlSec = cmdMount.Flag.Int("ttl", 0, "file ttl in seconds")

View file

@ -11,6 +11,7 @@ import (
"github.com/chrislusf/seaweedfs/weed/filesys" "github.com/chrislusf/seaweedfs/weed/filesys"
"github.com/chrislusf/seaweedfs/weed/glog" "github.com/chrislusf/seaweedfs/weed/glog"
"github.com/chrislusf/seaweedfs/weed/util" "github.com/chrislusf/seaweedfs/weed/util"
"strings"
) )
func runMount(cmd *Command, args []string) bool { func runMount(cmd *Command, args []string) bool {
@ -57,9 +58,21 @@ func runMount(cmd *Command, args []string) bool {
return false return false
} }
err = fs.Serve(c, filesys.NewSeaweedFileSystem( mountRoot := *mountOptions.filerMountRootPath
filerGrpcAddress, *mountOptions.filerMountRootPath, *mountOptions.collection, *mountOptions.replication, int32(*mountOptions.ttlSec), if mountRoot != "/" && strings.HasSuffix(mountRoot, "/") {
*mountOptions.chunkSizeLimitMB, *mountOptions.dataCenter)) mountRoot = mountRoot[0: len(mountRoot)-1]
}
err = fs.Serve(c, filesys.NewSeaweedFileSystem(&filesys.Option{
FilerGrpcAddress: filerGrpcAddress,
FilerMountRootPath: mountRoot,
Collection: *mountOptions.collection,
Replication: *mountOptions.replication,
TtlSec: int32(*mountOptions.ttlSec),
ChunkSizeLimit: int64(*mountOptions.chunkSizeLimitMB) * 1024 * 1024,
DataCenter: *mountOptions.dataCenter,
DirListingLimit: *mountOptions.dirListingLimit,
}))
if err != nil { if err != nil {
fuse.Unmount(*mountOptions.dir) fuse.Unmount(*mountOptions.dir)
} }

View file

@ -117,9 +117,9 @@ func (dir *Dir) Create(ctx context.Context, req *fuse.CreateRequest,
FileMode: uint32(req.Mode), FileMode: uint32(req.Mode),
Uid: req.Uid, Uid: req.Uid,
Gid: req.Gid, Gid: req.Gid,
Collection: dir.wfs.collection, Collection: dir.wfs.option.Collection,
Replication: dir.wfs.replication, Replication: dir.wfs.option.Replication,
TtlSec: dir.wfs.ttlSec, TtlSec: dir.wfs.option.TtlSec,
}, },
}, },
} }
@ -226,6 +226,7 @@ func (dir *Dir) ReadDirAll(ctx context.Context) (ret []fuse.Dirent, err error) {
request := &filer_pb.ListEntriesRequest{ request := &filer_pb.ListEntriesRequest{
Directory: dir.Path, Directory: dir.Path,
Limit: uint32(dir.wfs.option.DirListingLimit),
} }
glog.V(4).Infof("read directory: %v", request) glog.V(4).Infof("read directory: %v", request)

View file

@ -21,7 +21,7 @@ type ContinuousDirtyPages struct {
func newDirtyPages(file *File) *ContinuousDirtyPages { func newDirtyPages(file *File) *ContinuousDirtyPages {
return &ContinuousDirtyPages{ return &ContinuousDirtyPages{
Data: make([]byte, file.wfs.chunkSizeLimit), Data: make([]byte, file.wfs.option.ChunkSizeLimit),
f: file, f: file,
} }
} }
@ -119,10 +119,10 @@ func (pages *ContinuousDirtyPages) saveToStorage(ctx context.Context, buf []byte
request := &filer_pb.AssignVolumeRequest{ request := &filer_pb.AssignVolumeRequest{
Count: 1, Count: 1,
Replication: pages.f.wfs.replication, Replication: pages.f.wfs.option.Replication,
Collection: pages.f.wfs.collection, Collection: pages.f.wfs.option.Collection,
TtlSec: pages.f.wfs.ttlSec, TtlSec: pages.f.wfs.option.TtlSec,
DataCenter: pages.f.wfs.dataCenter, DataCenter: pages.f.wfs.option.DataCenter,
} }
resp, err := client.AssignVolume(ctx, request) resp, err := client.AssignVolume(ctx, request)

View file

@ -8,19 +8,23 @@ import (
"github.com/chrislusf/seaweedfs/weed/pb/filer_pb" "github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
"github.com/chrislusf/seaweedfs/weed/util" "github.com/chrislusf/seaweedfs/weed/util"
"github.com/karlseguin/ccache" "github.com/karlseguin/ccache"
"strings"
"sync" "sync"
) )
type Option struct {
FilerGrpcAddress string
FilerMountRootPath string
Collection string
Replication string
TtlSec int32
ChunkSizeLimit int64
DataCenter string
DirListingLimit int
}
type WFS struct { type WFS struct {
filerGrpcAddress string option *Option
filerMountRootPath string
listDirectoryEntriesCache *ccache.Cache listDirectoryEntriesCache *ccache.Cache
collection string
replication string
ttlSec int32
chunkSizeLimit int64
dataCenter string
// contains all open handles // contains all open handles
handles []*FileHandle handles []*FileHandle
@ -28,32 +32,23 @@ type WFS struct {
pathToHandleLock sync.Mutex pathToHandleLock sync.Mutex
} }
func NewSeaweedFileSystem(filerGrpcAddress string, filerMountRootPath string, collection string, replication string, ttlSec int32, chunkSizeLimitMB int, dataCenter string) *WFS { func NewSeaweedFileSystem(option *Option) *WFS {
if filerMountRootPath != "/" && strings.HasSuffix(filerMountRootPath, "/") {
filerMountRootPath = filerMountRootPath[0 : len(filerMountRootPath)-1]
}
return &WFS{ return &WFS{
filerGrpcAddress: filerGrpcAddress, option: option,
filerMountRootPath: filerMountRootPath,
listDirectoryEntriesCache: ccache.New(ccache.Configure().MaxSize(6000).ItemsToPrune(100)), listDirectoryEntriesCache: ccache.New(ccache.Configure().MaxSize(6000).ItemsToPrune(100)),
collection: collection,
replication: replication,
ttlSec: ttlSec,
chunkSizeLimit: int64(chunkSizeLimitMB) * 1024 * 1024,
dataCenter: dataCenter,
pathToHandleIndex: make(map[string]int), pathToHandleIndex: make(map[string]int),
} }
} }
func (wfs *WFS) Root() (fs.Node, error) { func (wfs *WFS) Root() (fs.Node, error) {
return &Dir{Path: wfs.filerMountRootPath, wfs: wfs}, nil return &Dir{Path: wfs.option.FilerMountRootPath, wfs: wfs}, nil
} }
func (wfs *WFS) withFilerClient(fn func(filer_pb.SeaweedFilerClient) error) error { func (wfs *WFS) withFilerClient(fn func(filer_pb.SeaweedFilerClient) error) error {
grpcConnection, err := util.GrpcDial(wfs.filerGrpcAddress) grpcConnection, err := util.GrpcDial(wfs.option.FilerGrpcAddress)
if err != nil { if err != nil {
return fmt.Errorf("fail to dial %s: %v", wfs.filerGrpcAddress, err) return fmt.Errorf("fail to dial %s: %v", wfs.option.FilerGrpcAddress, err)
} }
defer grpcConnection.Close() defer grpcConnection.Close()
@ -62,7 +57,7 @@ func (wfs *WFS) withFilerClient(fn func(filer_pb.SeaweedFilerClient) error) erro
return fn(client) return fn(client)
} }
func (wfs *WFS) AcquireHandle(file *File, uid, gid uint32) (handle *FileHandle) { func (wfs *WFS) AcquireHandle(file *File, uid, gid uint32) (fileHandle *FileHandle) {
wfs.pathToHandleLock.Lock() wfs.pathToHandleLock.Lock()
defer wfs.pathToHandleLock.Unlock() defer wfs.pathToHandleLock.Unlock()
@ -70,39 +65,33 @@ func (wfs *WFS) AcquireHandle(file *File, uid, gid uint32) (handle *FileHandle)
index, found := wfs.pathToHandleIndex[fullpath] index, found := wfs.pathToHandleIndex[fullpath]
if found && wfs.handles[index] != nil { if found && wfs.handles[index] != nil {
glog.V(4).Infoln(fullpath, "found handle id", index) glog.V(4).Infoln(fullpath, "found fileHandle id", index)
return wfs.handles[index] return wfs.handles[index]
} }
// create a new handler fileHandle = newFileHandle(file, uid, gid)
handle = &FileHandle{
f: file,
dirtyPages: newDirtyPages(file),
Uid: uid,
Gid: gid,
}
if found && wfs.handles[index] != nil { if found && wfs.handles[index] != nil {
glog.V(4).Infoln(fullpath, "reuse previous handle id", index) glog.V(4).Infoln(fullpath, "reuse previous fileHandle id", index)
wfs.handles[index] = handle wfs.handles[index] = fileHandle
handle.handle = uint64(index) fileHandle.handle = uint64(index)
return return
} }
for i, h := range wfs.handles { for i, h := range wfs.handles {
if h == nil { if h == nil {
wfs.handles[i] = handle wfs.handles[i] = fileHandle
handle.handle = uint64(i) fileHandle.handle = uint64(i)
wfs.pathToHandleIndex[fullpath] = i wfs.pathToHandleIndex[fullpath] = i
glog.V(4).Infoln(fullpath, "reuse handle id", handle.handle) glog.V(4).Infoln(fullpath, "reuse fileHandle id", fileHandle.handle)
return return
} }
} }
wfs.handles = append(wfs.handles, handle) wfs.handles = append(wfs.handles, fileHandle)
handle.handle = uint64(len(wfs.handles) - 1) fileHandle.handle = uint64(len(wfs.handles) - 1)
glog.V(4).Infoln(fullpath, "new handle id", handle.handle) glog.V(4).Infoln(fullpath, "new fileHandle id", fileHandle.handle)
wfs.pathToHandleIndex[fullpath] = int(handle.handle) wfs.pathToHandleIndex[fullpath] = int(fileHandle.handle)
return return
} }

View file

@ -48,6 +48,10 @@ message LookupDirectoryEntryResponse {
message ListEntriesRequest { message ListEntriesRequest {
string directory = 1; string directory = 1;
string prefix = 2;
string startFromFileName = 3;
bool inclusiveStartFrom = 4;
uint32 limit = 5;
} }
message ListEntriesResponse { message ListEntriesResponse {

View file

@ -98,7 +98,11 @@ func (m *LookupDirectoryEntryResponse) GetEntry() *Entry {
} }
type ListEntriesRequest struct { type ListEntriesRequest struct {
Directory string `protobuf:"bytes,1,opt,name=directory" json:"directory,omitempty"` Directory string `protobuf:"bytes,1,opt,name=directory" json:"directory,omitempty"`
Prefix string `protobuf:"bytes,2,opt,name=prefix" json:"prefix,omitempty"`
StartFromFileName string `protobuf:"bytes,3,opt,name=startFromFileName" json:"startFromFileName,omitempty"`
InclusiveStartFrom bool `protobuf:"varint,4,opt,name=inclusiveStartFrom" json:"inclusiveStartFrom,omitempty"`
Limit uint32 `protobuf:"varint,5,opt,name=limit" json:"limit,omitempty"`
} }
func (m *ListEntriesRequest) Reset() { *m = ListEntriesRequest{} } func (m *ListEntriesRequest) Reset() { *m = ListEntriesRequest{} }
@ -113,6 +117,34 @@ func (m *ListEntriesRequest) GetDirectory() string {
return "" return ""
} }
func (m *ListEntriesRequest) GetPrefix() string {
if m != nil {
return m.Prefix
}
return ""
}
func (m *ListEntriesRequest) GetStartFromFileName() string {
if m != nil {
return m.StartFromFileName
}
return ""
}
func (m *ListEntriesRequest) GetInclusiveStartFrom() bool {
if m != nil {
return m.InclusiveStartFrom
}
return false
}
func (m *ListEntriesRequest) GetLimit() uint32 {
if m != nil {
return m.Limit
}
return 0
}
type ListEntriesResponse struct { type ListEntriesResponse struct {
Entries []*Entry `protobuf:"bytes,1,rep,name=entries" json:"entries,omitempty"` Entries []*Entry `protobuf:"bytes,1,rep,name=entries" json:"entries,omitempty"`
} }
@ -1056,71 +1088,75 @@ var _SeaweedFiler_serviceDesc = grpc.ServiceDesc{
func init() { proto.RegisterFile("filer.proto", fileDescriptor0) } func init() { proto.RegisterFile("filer.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{ var fileDescriptor0 = []byte{
// 1049 bytes of a gzipped FileDescriptorProto // 1108 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x57, 0xcd, 0x6e, 0xdb, 0x46, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x57, 0x4f, 0x6f, 0xdc, 0x44,
0x10, 0x0e, 0x45, 0x4b, 0x16, 0x47, 0x72, 0x9a, 0xae, 0x9c, 0x84, 0x55, 0xec, 0x54, 0xd9, 0x26, 0x14, 0x8f, 0xd7, 0xbb, 0x9b, 0xf8, 0xed, 0xa6, 0xb4, 0xb3, 0x69, 0x6b, 0xb6, 0x49, 0xd9, 0x0e,
0x85, 0x83, 0x02, 0x86, 0xe1, 0xf6, 0x90, 0xb6, 0x28, 0xd0, 0xc0, 0x4e, 0x83, 0x00, 0x0e, 0x02, 0x2d, 0x4a, 0x05, 0x8a, 0xa2, 0xc0, 0xa1, 0x80, 0x90, 0xa8, 0x92, 0xb6, 0xaa, 0x94, 0x52, 0xc9,
0xd0, 0x75, 0x81, 0xa2, 0x07, 0x81, 0x26, 0xc7, 0xea, 0xc2, 0x14, 0xa9, 0x72, 0x97, 0x2e, 0xdc, 0x21, 0x48, 0x88, 0xc3, 0xca, 0xb1, 0x67, 0xc3, 0x28, 0x5e, 0xdb, 0xcc, 0x8c, 0x03, 0xe1, 0xca,
0x6b, 0x8f, 0x3d, 0xf5, 0x21, 0x8a, 0xde, 0xfb, 0x0a, 0x7d, 0xb1, 0x62, 0x7f, 0x48, 0x2d, 0x45, 0x91, 0x13, 0x1f, 0x02, 0x71, 0xe7, 0x03, 0x70, 0xe1, 0x8b, 0xa1, 0xf9, 0x63, 0xef, 0x78, 0xed,
0xca, 0x49, 0x0e, 0xbd, 0xed, 0xce, 0xce, 0x7c, 0x33, 0xdf, 0x72, 0xe6, 0x5b, 0x09, 0x06, 0x17, 0x4d, 0xdb, 0x03, 0xb7, 0x99, 0xf7, 0xde, 0xfc, 0xe6, 0xf7, 0xde, 0xbc, 0xf7, 0xf3, 0x2e, 0x0c,
0x2c, 0xc1, 0x7c, 0x7f, 0x91, 0x67, 0x22, 0x23, 0x7d, 0xb5, 0x99, 0x2e, 0xce, 0xe9, 0x1b, 0x78, 0x66, 0x34, 0x21, 0x6c, 0x2f, 0x67, 0x99, 0xc8, 0xd0, 0x86, 0xda, 0x4c, 0xf3, 0x33, 0xfc, 0x1a,
0x70, 0x92, 0x65, 0x97, 0xc5, 0xe2, 0x98, 0xe5, 0x18, 0x89, 0x2c, 0xbf, 0x7e, 0x91, 0x8a, 0xfc, 0xee, 0x1d, 0x67, 0xd9, 0x45, 0x91, 0x1f, 0x51, 0x46, 0x22, 0x91, 0xb1, 0xab, 0x67, 0xa9, 0x60,
0x3a, 0xc0, 0x5f, 0x0a, 0xe4, 0x82, 0xec, 0x80, 0x17, 0x97, 0x07, 0xbe, 0x33, 0x71, 0xf6, 0xbc, 0x57, 0x01, 0xf9, 0xa9, 0x20, 0x5c, 0xa0, 0x6d, 0xf0, 0xe2, 0xd2, 0xe1, 0x3b, 0x13, 0x67, 0xd7,
0x60, 0x69, 0x20, 0x04, 0x36, 0xd2, 0x70, 0x8e, 0x7e, 0x47, 0x1d, 0xa8, 0x35, 0x7d, 0x01, 0x3b, 0x0b, 0x16, 0x06, 0x84, 0xa0, 0x9b, 0x86, 0x73, 0xe2, 0x77, 0x94, 0x43, 0xad, 0xf1, 0x33, 0xd8,
0xed, 0x80, 0x7c, 0x91, 0xa5, 0x1c, 0xc9, 0x13, 0xe8, 0xa2, 0x34, 0x28, 0xb4, 0xc1, 0xe1, 0x07, 0x6e, 0x07, 0xe4, 0x79, 0x96, 0x72, 0x82, 0x1e, 0x41, 0x8f, 0x48, 0x83, 0x42, 0x1b, 0x1c, 0xbc,
0xfb, 0x65, 0x29, 0xfb, 0xda, 0x4f, 0x9f, 0xd2, 0x43, 0x20, 0x27, 0x8c, 0x0b, 0x69, 0x63, 0xc8, 0xb7, 0x57, 0x52, 0xd9, 0xd3, 0x71, 0xda, 0x8b, 0xff, 0x71, 0x00, 0x1d, 0x53, 0x2e, 0xa4, 0x91,
0xdf, 0xa9, 0x1c, 0xfa, 0x2d, 0x8c, 0x6a, 0x31, 0x26, 0xe3, 0x53, 0xd8, 0x44, 0x6d, 0xf2, 0x9d, 0x12, 0xfe, 0x76, 0x7c, 0xee, 0x40, 0x3f, 0x67, 0x64, 0x46, 0x7f, 0x31, 0x8c, 0xcc, 0x0e, 0x7d,
0x89, 0xdb, 0x96, 0xb3, 0x3c, 0xa7, 0x7f, 0x39, 0xd0, 0x55, 0xa6, 0x8a, 0x9a, 0xb3, 0xa4, 0x46, 0x02, 0xb7, 0xb8, 0x08, 0x99, 0x78, 0xce, 0xb2, 0xf9, 0x73, 0x9a, 0x90, 0x6f, 0x24, 0x69, 0x57,
0x1e, 0xc1, 0x90, 0xf1, 0xe9, 0xb2, 0x00, 0x49, 0xbb, 0x1f, 0x0c, 0x18, 0xaf, 0xa8, 0x92, 0xcf, 0x85, 0x34, 0x1d, 0x68, 0x0f, 0x10, 0x4d, 0xa3, 0xa4, 0xe0, 0xf4, 0x92, 0x9c, 0x94, 0x5e, 0xbf,
0xa0, 0x17, 0xfd, 0x5c, 0xa4, 0x97, 0xdc, 0x77, 0x55, 0xaa, 0xd1, 0x32, 0xd5, 0x77, 0x2c, 0xc1, 0x3b, 0x71, 0x76, 0x37, 0x82, 0x16, 0x0f, 0xda, 0x82, 0x5e, 0x42, 0xe7, 0x54, 0xf8, 0xbd, 0x89,
0x23, 0x79, 0x16, 0x18, 0x17, 0xf2, 0x0c, 0x20, 0x14, 0x22, 0x67, 0xe7, 0x85, 0x40, 0xee, 0x6f, 0xb3, 0xbb, 0x19, 0xe8, 0x0d, 0xfe, 0x1a, 0x46, 0x35, 0xfe, 0x26, 0xfd, 0xc7, 0xb0, 0x4e, 0xb4,
0xa8, 0xfb, 0xf0, 0xad, 0x80, 0x82, 0xe3, 0xf3, 0xea, 0x3c, 0xb0, 0x7c, 0xe9, 0x05, 0x78, 0x15, 0xc9, 0x77, 0x26, 0x6e, 0x5b, 0x01, 0x4a, 0x3f, 0xfe, 0xd3, 0x81, 0x9e, 0x32, 0x55, 0x75, 0x76,
0x1c, 0xb9, 0x0f, 0x9b, 0x32, 0x66, 0xca, 0x62, 0x53, 0x6d, 0x4f, 0x6e, 0x5f, 0xc5, 0xe4, 0x1e, 0x16, 0x75, 0x46, 0x0f, 0x60, 0x48, 0xf9, 0x74, 0x51, 0x8c, 0x8e, 0xe2, 0x37, 0xa0, 0xbc, 0xaa,
0xf4, 0xb2, 0x8b, 0x0b, 0x8e, 0x42, 0x55, 0xea, 0x06, 0x66, 0x27, 0xb9, 0x71, 0xf6, 0x1b, 0xfa, 0x3b, 0xfa, 0x18, 0xfa, 0xd1, 0x8f, 0x45, 0x7a, 0xc1, 0x7d, 0x57, 0x5d, 0x35, 0x5a, 0x5c, 0x25,
0xee, 0xc4, 0xd9, 0xdb, 0x08, 0xd4, 0x9a, 0x6c, 0x43, 0x77, 0x2e, 0xd8, 0x1c, 0x55, 0x19, 0x6e, 0x93, 0x3d, 0x94, 0xbe, 0xc0, 0x84, 0xa0, 0x27, 0x00, 0xa1, 0x10, 0x8c, 0x9e, 0x15, 0x82, 0x70,
0xa0, 0x37, 0xf4, 0x8f, 0x0e, 0xdc, 0xae, 0x97, 0x41, 0x1e, 0x80, 0xa7, 0xb2, 0x29, 0x04, 0x47, 0x95, 0xed, 0xe0, 0xc0, 0xb7, 0x0e, 0x14, 0x9c, 0x3c, 0xad, 0xfc, 0x81, 0x15, 0x8b, 0x67, 0xe0,
0x21, 0xa8, 0x6e, 0x3a, 0xad, 0xa1, 0x74, 0x2c, 0x94, 0x2a, 0x64, 0x9e, 0xc5, 0x3a, 0xe9, 0x96, 0x55, 0x70, 0xe8, 0x2e, 0xac, 0xcb, 0x33, 0x53, 0x1a, 0x1b, 0xb6, 0x7d, 0xb9, 0x7d, 0x19, 0xcb,
0x0e, 0x79, 0x9d, 0xc5, 0x48, 0xee, 0x80, 0x5b, 0xb0, 0x58, 0xa5, 0xdd, 0x0a, 0xe4, 0x52, 0x5a, 0xb7, 0xc9, 0x66, 0x33, 0x4e, 0x84, 0x62, 0xea, 0x06, 0x66, 0x27, 0x73, 0xe3, 0xf4, 0x57, 0xfd,
0x66, 0x2c, 0xf6, 0xbb, 0xda, 0x32, 0x63, 0x8a, 0x48, 0x94, 0x2b, 0xdc, 0x9e, 0x26, 0xa2, 0x77, 0x1c, 0xdd, 0x40, 0xad, 0x65, 0x45, 0xe7, 0x82, 0xce, 0x89, 0xa2, 0xe1, 0x06, 0x7a, 0x83, 0x7f,
0x92, 0xc8, 0x5c, 0x5a, 0x37, 0xf5, 0x47, 0x92, 0x6b, 0x32, 0x81, 0x41, 0x8e, 0x8b, 0x84, 0x45, 0xef, 0xc0, 0x8d, 0x3a, 0x0d, 0x74, 0x0f, 0x3c, 0x75, 0x9b, 0x42, 0x70, 0x14, 0x82, 0x6a, 0xed,
0xa1, 0x60, 0x59, 0xea, 0xf7, 0xd5, 0x91, 0x6d, 0x22, 0x0f, 0x01, 0xa2, 0x2c, 0x49, 0x30, 0x52, 0x93, 0x1a, 0x4a, 0xc7, 0x42, 0xa9, 0x8e, 0xcc, 0xb3, 0x58, 0x5f, 0xba, 0xa9, 0x8f, 0xbc, 0xca,
0x0e, 0x9e, 0x72, 0xb0, 0x2c, 0xf2, 0x3e, 0x85, 0x48, 0xa6, 0x1c, 0x23, 0x1f, 0x26, 0xce, 0x5e, 0x62, 0x82, 0x6e, 0x82, 0x5b, 0xd0, 0x58, 0x5d, 0xbb, 0x19, 0xc8, 0xa5, 0xb4, 0x9c, 0xd3, 0xd8,
0x37, 0xe8, 0x09, 0x91, 0x9c, 0x62, 0x44, 0x67, 0xf0, 0xd1, 0x4b, 0x54, 0xed, 0x75, 0x6d, 0x7d, 0x3c, 0xad, 0x5c, 0xca, 0x44, 0x22, 0xa6, 0x70, 0xfb, 0x3a, 0x11, 0xbd, 0x93, 0x89, 0xcc, 0xa5,
0x17, 0xd3, 0x9a, 0x6d, 0x0d, 0xb3, 0x0b, 0xb0, 0x08, 0x73, 0x4c, 0x85, 0x6c, 0x1a, 0x33, 0x25, 0x75, 0x5d, 0x3f, 0x92, 0x5c, 0xa3, 0x09, 0x0c, 0x18, 0xc9, 0x13, 0x1a, 0x85, 0x82, 0x66, 0xa9,
0x9e, 0xb6, 0x1c, 0xb3, 0xdc, 0xfe, 0x70, 0xae, 0xfd, 0xe1, 0xe8, 0xef, 0x0e, 0x8c, 0xdb, 0x32, 0xbf, 0xa1, 0x5c, 0xb6, 0x09, 0xdd, 0x07, 0x88, 0xb2, 0x24, 0x21, 0x91, 0x0a, 0xf0, 0x54, 0x80,
0x99, 0x86, 0xae, 0xf7, 0x8d, 0xf3, 0xee, 0x7d, 0x63, 0xb5, 0x67, 0xe7, 0xad, 0xed, 0x49, 0x0f, 0x65, 0x91, 0xf5, 0x14, 0x22, 0x99, 0x72, 0x12, 0xf9, 0x30, 0x71, 0x76, 0x7b, 0x41, 0x5f, 0x88,
0xe0, 0xee, 0x4b, 0x14, 0xca, 0x9e, 0xa5, 0x02, 0x53, 0x51, 0x52, 0x5d, 0xd7, 0x70, 0xf4, 0x10, 0xe4, 0x84, 0x44, 0xf8, 0x1c, 0xde, 0x7f, 0x41, 0x54, 0x7b, 0x5d, 0x59, 0xef, 0x62, 0xc6, 0xa4,
0xee, 0xad, 0x46, 0x98, 0x92, 0x7d, 0xd8, 0x8c, 0xb4, 0x49, 0x85, 0x0c, 0x83, 0x72, 0x4b, 0x7f, 0xad, 0x61, 0x76, 0x00, 0xf2, 0x90, 0x91, 0x54, 0xc8, 0xa6, 0x31, 0x03, 0xe2, 0x69, 0xcb, 0x11,
0x04, 0x72, 0x94, 0x63, 0x28, 0xf0, 0x3d, 0x74, 0xa7, 0xd2, 0x90, 0xce, 0x8d, 0x1a, 0x72, 0x17, 0x65, 0xf6, 0xc3, 0xb9, 0xf6, 0xc3, 0xe1, 0xdf, 0x1c, 0x18, 0xb7, 0xdd, 0x64, 0x1a, 0xba, 0xde,
0x46, 0x35, 0x68, 0x5d, 0x8b, 0xcc, 0x78, 0xb6, 0x88, 0xff, 0xaf, 0x8c, 0x35, 0x68, 0x93, 0xf1, 0x37, 0xce, 0xdb, 0xf7, 0x8d, 0xd5, 0x9e, 0x9d, 0x37, 0xb6, 0x27, 0xde, 0x87, 0xdb, 0x2f, 0x88,
0x1f, 0x07, 0xc8, 0x31, 0x26, 0xf8, 0x5e, 0x29, 0x5b, 0xc4, 0xb5, 0xa1, 0x40, 0x6e, 0x53, 0x81, 0x50, 0xf6, 0x2c, 0x15, 0x24, 0x15, 0x65, 0xaa, 0xab, 0x1a, 0x0e, 0x1f, 0xc0, 0x9d, 0xe5, 0x13,
0x1e, 0xc3, 0x6d, 0xe9, 0xa2, 0xb2, 0x4d, 0xe3, 0x50, 0x84, 0x6a, 0xb4, 0xfa, 0xc1, 0x90, 0x71, 0x86, 0xb2, 0x0f, 0xeb, 0x91, 0x36, 0xa9, 0x23, 0xc3, 0xa0, 0xdc, 0xe2, 0xef, 0x01, 0x1d, 0x32,
0x5d, 0xc2, 0x71, 0x28, 0x42, 0x03, 0x94, 0x63, 0x54, 0xe4, 0x9c, 0x5d, 0xa1, 0x1a, 0x36, 0x05, 0x12, 0x0a, 0xf2, 0x0e, 0x22, 0x58, 0x09, 0x5a, 0xe7, 0x5a, 0x41, 0xbb, 0x0d, 0xa3, 0x1a, 0xb4,
0x14, 0x94, 0x26, 0xc9, 0xa5, 0x56, 0xb3, 0xe1, 0xf2, 0xb7, 0x03, 0xa3, 0xe7, 0x9c, 0xb3, 0x59, 0xe6, 0x22, 0x6f, 0x3c, 0xcd, 0xe3, 0xff, 0xeb, 0xc6, 0x1a, 0xb4, 0xb9, 0xf1, 0x6f, 0x07, 0xd0,
0xfa, 0x43, 0x96, 0x14, 0x73, 0x2c, 0xc9, 0x6c, 0x43, 0x37, 0xca, 0x0a, 0xf3, 0x7d, 0xbb, 0x81, 0x11, 0x49, 0xc8, 0x3b, 0x5d, 0xd9, 0xa2, 0xf4, 0x0d, 0x05, 0x72, 0x9b, 0x0a, 0xf4, 0x10, 0x6e,
0xde, 0xac, 0xcc, 0x5a, 0xa7, 0x31, 0x6b, 0x2b, 0xd3, 0xea, 0x36, 0xa7, 0xd5, 0x9a, 0xc6, 0x0d, 0xc8, 0x10, 0x75, 0xdb, 0x34, 0x0e, 0x45, 0x68, 0x64, 0x74, 0x48, 0xb9, 0xa6, 0x70, 0x14, 0x8a,
0x7b, 0x1a, 0xc9, 0xc7, 0x30, 0x90, 0xf4, 0xa6, 0x11, 0xa6, 0x02, 0x73, 0xc5, 0xc0, 0x0b, 0x40, 0xd0, 0x00, 0x31, 0x12, 0x15, 0x4c, 0x2a, 0xab, 0x1a, 0x36, 0x05, 0x14, 0x94, 0x26, 0x99, 0x4b,
0x9a, 0x8e, 0x94, 0x85, 0x5e, 0xc1, 0x76, 0xbd, 0x50, 0xd3, 0x8b, 0x6b, 0xf5, 0x52, 0x4a, 0x51, 0x8d, 0xb3, 0xc9, 0xe5, 0x2f, 0x07, 0x46, 0x4f, 0x39, 0xa7, 0xe7, 0xe9, 0x77, 0x59, 0x52, 0xcc,
0x9e, 0x98, 0x2a, 0xe5, 0x52, 0x0d, 0x70, 0x71, 0x9e, 0xb0, 0x68, 0x2a, 0x0f, 0x5c, 0x33, 0xc0, 0x49, 0x99, 0xcc, 0x16, 0xf4, 0xa2, 0xac, 0x30, 0xef, 0xdb, 0x0b, 0xf4, 0x66, 0x69, 0xd6, 0x3a,
0xca, 0x72, 0x96, 0x27, 0x4b, 0xce, 0x1b, 0x16, 0x67, 0xfa, 0x05, 0x8c, 0xf4, 0x0b, 0x58, 0xbf, 0x8d, 0x59, 0x5b, 0x9a, 0x56, 0xb7, 0x39, 0xad, 0xd6, 0x34, 0x76, 0xed, 0x69, 0x44, 0x1f, 0xc0,
0xa0, 0x5d, 0x80, 0x2b, 0x65, 0x98, 0xb2, 0x58, 0xbf, 0x44, 0x5e, 0xe0, 0x69, 0xcb, 0xab, 0x98, 0x40, 0xa6, 0x37, 0x8d, 0x48, 0x2a, 0x08, 0x53, 0x19, 0x78, 0x01, 0x48, 0xd3, 0xa1, 0xb2, 0xe0,
0xd3, 0x6f, 0xc0, 0x3b, 0xc9, 0x34, 0x67, 0x4e, 0x0e, 0xc0, 0x4b, 0xca, 0x8d, 0x79, 0xb4, 0xc8, 0x4b, 0xd8, 0xaa, 0x13, 0x35, 0xbd, 0xb8, 0x52, 0x2f, 0xa5, 0x14, 0xb1, 0xc4, 0xb0, 0x94, 0x4b,
0xb2, 0xe5, 0x4a, 0xbf, 0x60, 0xe9, 0x44, 0xbf, 0x86, 0x7e, 0x69, 0x2e, 0x79, 0x38, 0xeb, 0x78, 0x35, 0xc0, 0xc5, 0x59, 0x42, 0xa3, 0xa9, 0x74, 0xb8, 0x66, 0x80, 0x95, 0xe5, 0x94, 0x25, 0x8b,
0x74, 0x56, 0x78, 0xd0, 0x7f, 0x1d, 0xd8, 0xae, 0x97, 0x6c, 0xae, 0xea, 0x0c, 0xb6, 0xaa, 0x14, 0x9c, 0xbb, 0x56, 0xce, 0xf8, 0x33, 0x18, 0xe9, 0xcf, 0x71, 0xbd, 0x40, 0x3b, 0x00, 0x97, 0xca,
0xd3, 0x79, 0xb8, 0x30, 0xb5, 0x1c, 0xd8, 0xb5, 0x34, 0xc3, 0xaa, 0x02, 0xf9, 0xeb, 0x70, 0xa1, 0x30, 0xa5, 0xb1, 0xfe, 0x12, 0x79, 0x81, 0xa7, 0x2d, 0x2f, 0x63, 0x8e, 0xbf, 0x02, 0xef, 0x38,
0xbb, 0x67, 0x98, 0x58, 0xa6, 0xf1, 0xf7, 0xf0, 0x61, 0xc3, 0x45, 0x56, 0x7d, 0x89, 0xe5, 0x1c, 0xd3, 0x39, 0x73, 0xb4, 0x0f, 0x5e, 0x52, 0x6e, 0xcc, 0x47, 0x0b, 0x2d, 0x5a, 0xae, 0x8c, 0x0b,
0xc8, 0x25, 0x79, 0x0a, 0xdd, 0xab, 0x30, 0x29, 0xd0, 0x0c, 0xdd, 0xa8, 0x79, 0x03, 0x3c, 0xd0, 0x16, 0x41, 0xf8, 0x4b, 0xd8, 0x28, 0xcd, 0x65, 0x1e, 0xce, 0xaa, 0x3c, 0x3a, 0x4b, 0x79, 0xe0,
0x1e, 0x5f, 0x75, 0x9e, 0x39, 0xf4, 0x4b, 0xb8, 0xaf, 0x1b, 0xf6, 0xa8, 0xea, 0xaf, 0xf2, 0xee, 0x7f, 0x1d, 0xd8, 0xaa, 0x53, 0x36, 0xa5, 0x3a, 0x85, 0xcd, 0xea, 0x8a, 0xe9, 0x3c, 0xcc, 0x0d,
0xeb, 0x6d, 0xe8, 0xac, 0xb6, 0x21, 0x1d, 0x83, 0xdf, 0x0c, 0xd5, 0x64, 0x0e, 0xff, 0xec, 0xc1, 0x97, 0x7d, 0x9b, 0x4b, 0xf3, 0x58, 0x45, 0x90, 0xbf, 0x0a, 0x73, 0xdd, 0x3d, 0xc3, 0xc4, 0x32,
0xf0, 0x14, 0xc3, 0x5f, 0x11, 0x63, 0xa9, 0x6c, 0x39, 0x99, 0x95, 0x97, 0x55, 0xff, 0x85, 0x43, 0x8d, 0xbf, 0x85, 0x5b, 0x8d, 0x10, 0xc9, 0xfa, 0x82, 0x94, 0x73, 0x20, 0x97, 0xe8, 0x31, 0xf4,
0x9e, 0xac, 0xde, 0x4a, 0xeb, 0x4f, 0xaa, 0xf1, 0xa7, 0x6f, 0x73, 0x33, 0x83, 0x76, 0x8b, 0x9c, 0x2e, 0xc3, 0xa4, 0x20, 0x66, 0xe8, 0x46, 0xcd, 0x0a, 0xf0, 0x40, 0x47, 0x7c, 0xd1, 0x79, 0xe2,
0xc0, 0xc0, 0xfa, 0x3d, 0x43, 0x76, 0xac, 0xc0, 0xc6, 0x4f, 0xa3, 0xf1, 0xee, 0x9a, 0xd3, 0x0a, 0xe0, 0xcf, 0xe1, 0xae, 0x6e, 0xd8, 0xc3, 0xaa, 0xbf, 0xca, 0xda, 0xd7, 0xdb, 0xd0, 0x59, 0x6e,
0x2d, 0x04, 0xd2, 0x7c, 0x53, 0xc8, 0x27, 0xcb, 0xb0, 0xb5, 0x6f, 0xdb, 0xf8, 0xf1, 0xcd, 0x4e, 0x43, 0x3c, 0x06, 0xbf, 0x79, 0x54, 0x27, 0x73, 0xf0, 0x47, 0x1f, 0x86, 0x27, 0x24, 0xfc, 0x99,
0x76, 0xc1, 0x96, 0xe0, 0xda, 0x05, 0x37, 0x25, 0xde, 0x2e, 0xb8, 0x4d, 0xa5, 0x15, 0x9a, 0x25, 0x90, 0x58, 0x2a, 0x1b, 0x43, 0xe7, 0x65, 0xb1, 0xea, 0x3f, 0xb7, 0xd0, 0xa3, 0xe5, 0xaa, 0xb4,
0xa6, 0x36, 0x5a, 0x53, 0xbe, 0x6d, 0xb4, 0x36, 0x05, 0x56, 0x68, 0x96, 0x9c, 0xd9, 0x68, 0x4d, 0xfe, 0xbe, 0x1b, 0x7f, 0xf4, 0xa6, 0x30, 0x33, 0x68, 0x6b, 0xe8, 0x18, 0x06, 0xd6, 0xef, 0x19,
0x65, 0xb6, 0xd1, 0xda, 0x34, 0xf0, 0x16, 0x79, 0x03, 0x43, 0x5b, 0x5b, 0x88, 0x15, 0xd0, 0x22, 0xb4, 0x6d, 0x1d, 0x6c, 0xfc, 0x4c, 0x1b, 0xef, 0xac, 0xf0, 0x56, 0x68, 0x21, 0xa0, 0xe6, 0x37,
0x8e, 0xe3, 0x87, 0xeb, 0x8e, 0x6d, 0x40, 0x7b, 0x94, 0x6c, 0xc0, 0x16, 0x31, 0xb1, 0x01, 0xdb, 0x05, 0x7d, 0xb8, 0x38, 0xb6, 0xf2, 0xdb, 0x36, 0x7e, 0x78, 0x7d, 0x90, 0x4d, 0xd8, 0x12, 0x5c,
0x26, 0x90, 0xde, 0x22, 0x3f, 0xc1, 0x9d, 0xd5, 0x96, 0x26, 0x8f, 0x56, 0x69, 0x35, 0x26, 0x65, 0x9b, 0x70, 0x53, 0xe2, 0x6d, 0xc2, 0x6d, 0x2a, 0xad, 0xd0, 0x2c, 0x31, 0xb5, 0xd1, 0x9a, 0xf2,
0x4c, 0x6f, 0x72, 0x29, 0xc1, 0xcf, 0x7b, 0xea, 0x6f, 0xc4, 0xe7, 0xff, 0x05, 0x00, 0x00, 0xff, 0x6d, 0xa3, 0xb5, 0x29, 0xb0, 0x42, 0xb3, 0xe4, 0xcc, 0x46, 0x6b, 0x2a, 0xb3, 0x8d, 0xd6, 0xa6,
0xff, 0x45, 0xa6, 0x48, 0x98, 0x55, 0x0c, 0x00, 0x00, 0x81, 0x6b, 0xe8, 0x35, 0x0c, 0x6d, 0x6d, 0x41, 0xd6, 0x81, 0x16, 0x71, 0x1c, 0xdf, 0x5f, 0xe5,
0xb6, 0x01, 0xed, 0x51, 0xb2, 0x01, 0x5b, 0xc4, 0xc4, 0x06, 0x6c, 0x9b, 0x40, 0xbc, 0x86, 0x7e,
0x80, 0x9b, 0xcb, 0x2d, 0x8d, 0x1e, 0x2c, 0xa7, 0xd5, 0x98, 0x94, 0x31, 0xbe, 0x2e, 0xa4, 0x04,
0x3f, 0xeb, 0xab, 0xff, 0x34, 0x9f, 0xfe, 0x17, 0x00, 0x00, 0xff, 0xff, 0x41, 0x12, 0xff, 0xda,
0xe2, 0x0c, 0x00, 0x00,
} }

View file

@ -26,7 +26,7 @@ type ErrorCode int
// Error codes, see full list at http://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html // Error codes, see full list at http://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html
const ( const (
ErrNone ErrorCode = iota ErrNone ErrorCode = iota
ErrMethodNotAllowed ErrMethodNotAllowed
ErrBucketNotEmpty ErrBucketNotEmpty
ErrBucketAlreadyExists ErrBucketAlreadyExists
@ -34,7 +34,9 @@ const (
ErrNoSuchBucket ErrNoSuchBucket
ErrInvalidBucketName ErrInvalidBucketName
ErrInvalidDigest ErrInvalidDigest
ErrInvalidMaxKeys
ErrInternalError ErrInternalError
ErrNotImplemented
) )
// error code to APIError structure, these fields carry respective // error code to APIError structure, these fields carry respective
@ -70,6 +72,11 @@ var errorCodeResponse = map[ErrorCode]APIError{
Description: "The Content-Md5 you specified is not valid.", Description: "The Content-Md5 you specified is not valid.",
HTTPStatusCode: http.StatusBadRequest, HTTPStatusCode: http.StatusBadRequest,
}, },
ErrInvalidMaxKeys: {
Code: "InvalidArgument",
Description: "Argument maxKeys must be an integer between 0 and 2147483647",
HTTPStatusCode: http.StatusBadRequest,
},
ErrNoSuchBucket: { ErrNoSuchBucket: {
Code: "NoSuchBucket", Code: "NoSuchBucket",
Description: "The specified bucket does not exist", Description: "The specified bucket does not exist",
@ -80,6 +87,11 @@ var errorCodeResponse = map[ErrorCode]APIError{
Description: "We encountered an internal error, please try again.", Description: "We encountered an internal error, please try again.",
HTTPStatusCode: http.StatusInternalServerError, HTTPStatusCode: http.StatusInternalServerError,
}, },
ErrNotImplemented: {
Code: "NotImplemented",
Description: "A header you provided implies functionality that is not implemented",
HTTPStatusCode: http.StatusNotImplemented,
},
} }
// getAPIError provides API Error for input API error code. // getAPIError provides API Error for input API error code.

View file

@ -0,0 +1,116 @@
package s3api
import (
"github.com/gorilla/mux"
"net/http"
"net/url"
"strconv"
"github.com/chrislusf/seaweedfs/weed/glog"
"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
"context"
"fmt"
"path/filepath"
"time"
"github.com/chrislusf/seaweedfs/weed/filer2"
)
const (
maxObjectListSizeLimit = 1000 // Limit number of objects in a listObjectsResponse.
)
func (s3a *S3ApiServer) ListObjectsV1Handler(w http.ResponseWriter, r *http.Request) {
// https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGET.html
// collect parameters
vars := mux.Vars(r)
bucket := vars["bucket"]
originalPrefix, marker, delimiter, maxKeys := getListObjectsV1Args(r.URL.Query())
if maxKeys < 0 {
writeErrorResponse(w, ErrInvalidMaxKeys, r.URL)
return
}
if delimiter != "" && delimiter != "/" {
writeErrorResponse(w, ErrNotImplemented, r.URL)
}
// convert full path prefix into directory name and prefix for entry name
dir, prefix := filepath.Split(originalPrefix)
// check filer
var response ListBucketResponse
err := s3a.withFilerClient(func(client filer_pb.SeaweedFilerClient) error {
request := &filer_pb.ListEntriesRequest{
Directory: fmt.Sprintf("%s/%s/%s", s3a.option.BucketsPath, bucket, dir),
Prefix: prefix,
Limit: uint32(maxKeys),
StartFromFileName: marker,
InclusiveStartFrom: false,
}
glog.V(4).Infof("read directory: %v", request)
resp, err := client.ListEntries(context.Background(), request)
if err != nil {
return fmt.Errorf("list buckets: %v", err)
}
var contents []ListEntry
var commonPrefixes []PrefixEntry
for _, entry := range resp.Entries {
if entry.IsDirectory {
commonPrefixes = append(commonPrefixes, PrefixEntry{
Prefix: fmt.Sprintf("%s%s/", dir, entry.Name),
})
} else {
contents = append(contents, ListEntry{
Key: fmt.Sprintf("%s%s", dir, entry.Name),
LastModified: time.Unix(entry.Attributes.Mtime, 0),
ETag: "", // TODO add etag
Size: int64(filer2.TotalSize(entry.Chunks)),
Owner: CanonicalUser{
ID: fmt.Sprintf("%d", entry.Attributes.Uid),
},
StorageClass: StorageClass("STANDARD"),
})
}
}
response = ListBucketResponse{
ListBucketResponse: ListBucketResult{
Name: bucket,
Prefix: originalPrefix,
Marker: marker, // TODO
NextMarker: "", // TODO
MaxKeys: maxKeys,
Delimiter: delimiter,
IsTruncated: false, // TODO
Contents: contents,
CommonPrefixes: commonPrefixes,
},
}
return nil
})
if err != nil {
writeErrorResponse(w, ErrInternalError, r.URL)
return
}
writeSuccessResponseXML(w, encodeResponse(response))
}
func getListObjectsV1Args(values url.Values) (prefix, marker, delimiter string, maxkeys int) {
prefix = values.Get("prefix")
marker = values.Get("marker")
delimiter = values.Get("delimiter")
if values.Get("max-keys") != "" {
maxkeys, _ = strconv.Atoi(values.Get("max-keys"))
} else {
maxkeys = maxObjectListSizeLimit
}
return
}

View file

@ -59,6 +59,9 @@ func (s3a *S3ApiServer) registerRouter(router *mux.Router) {
// HeadBucket // HeadBucket
bucket.Methods("HEAD").HandlerFunc(s3a.HeadBucketHandler) bucket.Methods("HEAD").HandlerFunc(s3a.HeadBucketHandler)
// ListObjectsV1 (Legacy)
bucket.Methods("GET").HandlerFunc(s3a.ListObjectsV1Handler)
/* /*
// CopyObject // CopyObject
bucket.Methods("PUT").Path("/{object:.+}").HeadersRegexp("X-Amz-Copy-Source", ".*?(\\/|%2F).*?").HandlerFunc(s3a.CopyObjectHandler) bucket.Methods("PUT").Path("/{object:.+}").HeadersRegexp("X-Amz-Copy-Source", ".*?(\\/|%2F).*?").HandlerFunc(s3a.CopyObjectHandler)

View file

@ -13,6 +13,7 @@ import (
"github.com/chrislusf/seaweedfs/weed/pb/filer_pb" "github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
"github.com/chrislusf/seaweedfs/weed/util" "github.com/chrislusf/seaweedfs/weed/util"
"strconv" "strconv"
"strings"
) )
func (fs *FilerServer) LookupDirectoryEntry(ctx context.Context, req *filer_pb.LookupDirectoryEntryRequest) (*filer_pb.LookupDirectoryEntryResponse, error) { func (fs *FilerServer) LookupDirectoryEntry(ctx context.Context, req *filer_pb.LookupDirectoryEntryRequest) (*filer_pb.LookupDirectoryEntryResponse, error) {
@ -34,20 +35,45 @@ func (fs *FilerServer) LookupDirectoryEntry(ctx context.Context, req *filer_pb.L
func (fs *FilerServer) ListEntries(ctx context.Context, req *filer_pb.ListEntriesRequest) (*filer_pb.ListEntriesResponse, error) { func (fs *FilerServer) ListEntries(ctx context.Context, req *filer_pb.ListEntriesRequest) (*filer_pb.ListEntriesResponse, error) {
entries, err := fs.filer.ListDirectoryEntries(filer2.FullPath(req.Directory), "", false, fs.option.DirListingLimit) println("directory:", req.Directory, "prefix", req.Prefix)
if err != nil { limit := int(req.Limit)
return nil, err if limit == 0 {
limit = fs.option.DirListingLimit
} }
resp := &filer_pb.ListEntriesResponse{} resp := &filer_pb.ListEntriesResponse{}
for _, entry := range entries { lastFileName := req.StartFromFileName
includeLastFile := req.InclusiveStartFrom
for limit > 0 {
entries, err := fs.filer.ListDirectoryEntries(filer2.FullPath(req.Directory), lastFileName, includeLastFile, limit)
if err != nil {
return nil, err
}
if len(entries) == 0 {
return resp, nil
}
includeLastFile = false
for _, entry := range entries {
lastFileName = entry.Name()
if req.Prefix != "" {
if !strings.HasPrefix(entry.Name(), req.Prefix) {
continue
}
}
resp.Entries = append(resp.Entries, &filer_pb.Entry{
Name: entry.Name(),
IsDirectory: entry.IsDirectory(),
Chunks: entry.Chunks,
Attributes: filer2.EntryAttributeToPb(entry),
})
limit--
}
resp.Entries = append(resp.Entries, &filer_pb.Entry{
Name: entry.Name(),
IsDirectory: entry.IsDirectory(),
Chunks: entry.Chunks,
Attributes: filer2.EntryAttributeToPb(entry),
})
} }
return resp, nil return resp, nil