2019-05-03 07:24:35 +00:00
|
|
|
package filer2
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
2019-12-13 08:23:05 +00:00
|
|
|
"io"
|
|
|
|
"math"
|
2019-05-03 07:24:35 +00:00
|
|
|
"strings"
|
|
|
|
"sync"
|
|
|
|
|
|
|
|
"github.com/chrislusf/seaweedfs/weed/glog"
|
|
|
|
"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
|
|
|
|
"github.com/chrislusf/seaweedfs/weed/util"
|
|
|
|
)
|
|
|
|
|
|
|
|
func VolumeId(fileId string) string {
|
|
|
|
lastCommaIndex := strings.LastIndex(fileId, ",")
|
|
|
|
if lastCommaIndex > 0 {
|
|
|
|
return fileId[:lastCommaIndex]
|
|
|
|
}
|
|
|
|
return fileId
|
|
|
|
}
|
|
|
|
|
|
|
|
type FilerClient interface {
|
2020-02-26 05:50:12 +00:00
|
|
|
WithFilerClient(fn func(filer_pb.SeaweedFilerClient) error) error
|
2020-02-27 00:46:01 +00:00
|
|
|
AdjustedUrl(hostAndPort string) string
|
2019-05-03 07:24:35 +00:00
|
|
|
}
|
|
|
|
|
2020-02-26 05:50:12 +00:00
|
|
|
func ReadIntoBuffer(filerClient FilerClient, fullFilePath FullPath, buff []byte, chunkViews []*ChunkView, baseOffset int64) (totalRead int64, err error) {
|
2019-05-03 07:24:35 +00:00
|
|
|
var vids []string
|
|
|
|
for _, chunkView := range chunkViews {
|
|
|
|
vids = append(vids, VolumeId(chunkView.FileId))
|
|
|
|
}
|
|
|
|
|
|
|
|
vid2Locations := make(map[string]*filer_pb.Locations)
|
|
|
|
|
2020-02-26 05:50:12 +00:00
|
|
|
err = filerClient.WithFilerClient(func(client filer_pb.SeaweedFilerClient) error {
|
2019-05-03 07:24:35 +00:00
|
|
|
|
|
|
|
glog.V(4).Infof("read fh lookup volume id locations: %v", vids)
|
2020-02-26 05:50:12 +00:00
|
|
|
resp, err := client.LookupVolume(context.Background(), &filer_pb.LookupVolumeRequest{
|
2019-05-03 07:24:35 +00:00
|
|
|
VolumeIds: vids,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
vid2Locations = resp.LocationsMap
|
|
|
|
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return 0, fmt.Errorf("failed to lookup volume ids %v: %v", vids, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var wg sync.WaitGroup
|
|
|
|
for _, chunkView := range chunkViews {
|
|
|
|
wg.Add(1)
|
|
|
|
go func(chunkView *ChunkView) {
|
|
|
|
defer wg.Done()
|
|
|
|
|
|
|
|
glog.V(4).Infof("read fh reading chunk: %+v", chunkView)
|
|
|
|
|
|
|
|
locations := vid2Locations[VolumeId(chunkView.FileId)]
|
|
|
|
if locations == nil || len(locations.Locations) == 0 {
|
|
|
|
glog.V(0).Infof("failed to locate %s", chunkView.FileId)
|
|
|
|
err = fmt.Errorf("failed to locate %s", chunkView.FileId)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-02-27 00:46:01 +00:00
|
|
|
volumeServerAddress := filerClient.AdjustedUrl(locations.Locations[0].Url)
|
2019-05-03 07:24:35 +00:00
|
|
|
var n int64
|
2020-03-09 04:39:33 +00:00
|
|
|
n, err = util.ReadUrl(fmt.Sprintf("http://%s/%s", volumeServerAddress, chunkView.FileId), chunkView.CipherKey, chunkView.isGzipped, chunkView.IsFullChunk, chunkView.Offset, int(chunkView.Size), buff[chunkView.LogicOffset-baseOffset:chunkView.LogicOffset-baseOffset+int64(chunkView.Size)])
|
2019-05-03 07:24:35 +00:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
2020-02-27 00:46:01 +00:00
|
|
|
glog.V(0).Infof("%v read http://%s/%v %v bytes: %v", fullFilePath, volumeServerAddress, chunkView.FileId, n, err)
|
2019-05-03 07:24:35 +00:00
|
|
|
|
|
|
|
err = fmt.Errorf("failed to read http://%s/%s: %v",
|
2020-02-27 00:46:01 +00:00
|
|
|
volumeServerAddress, chunkView.FileId, err)
|
2019-05-03 07:24:35 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
glog.V(4).Infof("read fh read %d bytes: %+v", n, chunkView)
|
|
|
|
totalRead += n
|
|
|
|
|
|
|
|
}(chunkView)
|
|
|
|
}
|
|
|
|
wg.Wait()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-02-26 05:50:12 +00:00
|
|
|
func GetEntry(filerClient FilerClient, fullFilePath FullPath) (entry *filer_pb.Entry, err error) {
|
2019-05-03 07:24:35 +00:00
|
|
|
|
2020-01-20 07:59:46 +00:00
|
|
|
dir, name := fullFilePath.DirAndName()
|
2019-05-03 07:24:35 +00:00
|
|
|
|
2020-02-26 05:50:12 +00:00
|
|
|
err = filerClient.WithFilerClient(func(client filer_pb.SeaweedFilerClient) error {
|
2019-05-03 07:24:35 +00:00
|
|
|
|
|
|
|
request := &filer_pb.LookupDirectoryEntryRequest{
|
|
|
|
Directory: dir,
|
|
|
|
Name: name,
|
|
|
|
}
|
|
|
|
|
2020-01-25 08:31:53 +00:00
|
|
|
// glog.V(3).Infof("read %s request: %v", fullFilePath, request)
|
2020-03-08 00:51:46 +00:00
|
|
|
resp, err := filer_pb.LookupEntry(client, request)
|
2019-05-03 07:24:35 +00:00
|
|
|
if err != nil {
|
2020-03-08 01:01:39 +00:00
|
|
|
if err == filer_pb.ErrNotFound {
|
2019-05-03 21:12:51 +00:00
|
|
|
return nil
|
2019-05-03 07:24:35 +00:00
|
|
|
}
|
2020-01-25 08:31:53 +00:00
|
|
|
glog.V(3).Infof("read %s %v: %v", fullFilePath, resp, err)
|
2019-05-03 07:24:35 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2019-12-11 07:13:14 +00:00
|
|
|
if resp.Entry == nil {
|
2020-01-25 08:31:53 +00:00
|
|
|
// glog.V(3).Infof("read %s entry: %v", fullFilePath, entry)
|
2019-12-11 07:13:14 +00:00
|
|
|
return nil
|
2019-05-03 07:24:35 +00:00
|
|
|
}
|
|
|
|
|
2019-12-11 07:13:14 +00:00
|
|
|
entry = resp.Entry
|
2019-05-03 07:24:35 +00:00
|
|
|
return nil
|
|
|
|
})
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-02-26 05:50:12 +00:00
|
|
|
func ReadDirAllEntries(filerClient FilerClient, fullDirPath FullPath, prefix string, fn func(entry *filer_pb.Entry, isLast bool)) (err error) {
|
2019-05-03 07:24:35 +00:00
|
|
|
|
2020-02-26 05:50:12 +00:00
|
|
|
err = filerClient.WithFilerClient(func(client filer_pb.SeaweedFilerClient) error {
|
2019-05-03 07:24:35 +00:00
|
|
|
|
|
|
|
lastEntryName := ""
|
|
|
|
|
2019-12-13 08:23:05 +00:00
|
|
|
request := &filer_pb.ListEntriesRequest{
|
2020-01-20 07:59:46 +00:00
|
|
|
Directory: string(fullDirPath),
|
2019-12-13 08:23:05 +00:00
|
|
|
Prefix: prefix,
|
|
|
|
StartFromFileName: lastEntryName,
|
|
|
|
Limit: math.MaxUint32,
|
|
|
|
}
|
2019-05-03 07:24:35 +00:00
|
|
|
|
2019-12-13 08:23:05 +00:00
|
|
|
glog.V(3).Infof("read directory: %v", request)
|
2020-02-26 05:50:12 +00:00
|
|
|
stream, err := client.ListEntries(context.Background(), request)
|
2019-12-13 08:23:05 +00:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("list %s: %v", fullDirPath, err)
|
|
|
|
}
|
2019-05-03 07:24:35 +00:00
|
|
|
|
2019-12-13 08:23:05 +00:00
|
|
|
var prevEntry *filer_pb.Entry
|
|
|
|
for {
|
|
|
|
resp, recvErr := stream.Recv()
|
|
|
|
if recvErr != nil {
|
|
|
|
if recvErr == io.EOF {
|
|
|
|
if prevEntry != nil {
|
|
|
|
fn(prevEntry, true)
|
|
|
|
}
|
|
|
|
break
|
|
|
|
} else {
|
|
|
|
return recvErr
|
|
|
|
}
|
2019-05-03 07:24:35 +00:00
|
|
|
}
|
2019-12-13 08:23:05 +00:00
|
|
|
if prevEntry != nil {
|
|
|
|
fn(prevEntry, false)
|
2019-05-03 07:24:35 +00:00
|
|
|
}
|
2019-12-13 08:23:05 +00:00
|
|
|
prevEntry = resp.Entry
|
2019-05-03 07:24:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|