aboutsummaryrefslogtreecommitdiff
path: root/weed
diff options
context:
space:
mode:
Diffstat (limited to 'weed')
-rw-r--r--weed/command/mount.go14
-rw-r--r--weed/command/mount_std.go5
-rw-r--r--weed/filer/filechunk_manifest.go2
-rw-r--r--weed/filer/reader_at.go18
-rw-r--r--weed/filer/stream.go2
-rw-r--r--weed/filesys/filehandle.go2
-rw-r--r--weed/server/filer_server_handlers_read_dir.go44
-rw-r--r--weed/server/filer_ui/templates.go19
8 files changed, 79 insertions, 27 deletions
diff --git a/weed/command/mount.go b/weed/command/mount.go
index 7bf59cdc7..42a79bd1f 100644
--- a/weed/command/mount.go
+++ b/weed/command/mount.go
@@ -2,6 +2,7 @@ package command
import (
"os"
+ "time"
)
type MountOptions struct {
@@ -25,9 +26,10 @@ type MountOptions struct {
}
var (
- mountOptions MountOptions
- mountCpuProfile *string
- mountMemProfile *string
+ mountOptions MountOptions
+ mountCpuProfile *string
+ mountMemProfile *string
+ mountReadRetryTime *time.Duration
)
func init() {
@@ -46,11 +48,13 @@ func init() {
mountOptions.allowOthers = cmdMount.Flag.Bool("allowOthers", true, "allows other users to access the file system")
mountOptions.umaskString = cmdMount.Flag.String("umask", "022", "octal umask, e.g., 022, 0111")
mountOptions.nonempty = cmdMount.Flag.Bool("nonempty", false, "allows the mounting over a non-empty directory")
- mountCpuProfile = cmdMount.Flag.String("cpuprofile", "", "cpu profile output file")
- mountMemProfile = cmdMount.Flag.String("memprofile", "", "memory profile output file")
mountOptions.outsideContainerClusterMode = cmdMount.Flag.Bool("outsideContainerClusterMode", false, "allows other users to access the file system")
mountOptions.uidMap = cmdMount.Flag.String("map.uid", "", "map local uid to uid on filer, comma-separated <local_uid>:<filer_uid>")
mountOptions.gidMap = cmdMount.Flag.String("map.gid", "", "map local gid to gid on filer, comma-separated <local_gid>:<filer_gid>")
+
+ mountCpuProfile = cmdMount.Flag.String("cpuprofile", "", "cpu profile output file")
+ mountMemProfile = cmdMount.Flag.String("memprofile", "", "memory profile output file")
+ mountReadRetryTime = cmdMount.Flag.Duration("readRetryTime", 6*time.Second, "maximum read retry wait time")
}
var cmdMount = &Command{
diff --git a/weed/command/mount_std.go b/weed/command/mount_std.go
index 14374eb5c..20d08314c 100644
--- a/weed/command/mount_std.go
+++ b/weed/command/mount_std.go
@@ -5,6 +5,7 @@ package command
import (
"context"
"fmt"
+ "github.com/chrislusf/seaweedfs/weed/filer"
"github.com/chrislusf/seaweedfs/weed/filesys/meta_cache"
"os"
"os/user"
@@ -29,6 +30,10 @@ import (
func runMount(cmd *Command, args []string) bool {
grace.SetupProfiling(*mountCpuProfile, *mountMemProfile)
+ if *mountReadRetryTime < time.Second {
+ *mountReadRetryTime = time.Second
+ }
+ filer.ReadWaitTime = *mountReadRetryTime
umask, umaskErr := strconv.ParseUint(*mountOptions.umaskString, 8, 64)
if umaskErr != nil {
diff --git a/weed/filer/filechunk_manifest.go b/weed/filer/filechunk_manifest.go
index 9e53e008f..2df8a4bbf 100644
--- a/weed/filer/filechunk_manifest.go
+++ b/weed/filer/filechunk_manifest.go
@@ -98,7 +98,7 @@ func retriedFetchChunkData(urlStrings []string, cipherKey []byte, isGzipped bool
var err error
var buffer bytes.Buffer
- for waitTime := time.Second; waitTime < 10*time.Second; waitTime += waitTime / 2 {
+ for waitTime := time.Second; waitTime < ReadWaitTime; waitTime += waitTime / 2 {
for _, urlString := range urlStrings {
err = util.ReadUrlAsStream(urlString, cipherKey, isGzipped, isFullChunk, offset, size, func(data []byte) {
buffer.Write(data)
diff --git a/weed/filer/reader_at.go b/weed/filer/reader_at.go
index fa51df687..835d6cfc2 100644
--- a/weed/filer/reader_at.go
+++ b/weed/filer/reader_at.go
@@ -11,6 +11,11 @@ import (
"io"
"math/rand"
"sync"
+ "time"
+)
+
+var (
+ ReadWaitTime = 6 * time.Second
)
type ChunkReadAt struct {
@@ -37,7 +42,8 @@ func LookupFn(filerClient filer_pb.FilerClient) LookupFileIdFunctionType {
vid := VolumeId(fileId)
locations, found := vidCache[vid]
- if !found {
+ waitTime := time.Second
+ for !found && waitTime < ReadWaitTime {
// println("looking up volume", vid)
err = filerClient.WithFilerClient(func(client filer_pb.SeaweedFilerClient) error {
resp, err := client.LookupVolume(context.Background(), &filer_pb.LookupVolumeRequest{
@@ -56,6 +62,16 @@ func LookupFn(filerClient filer_pb.FilerClient) LookupFileIdFunctionType {
return nil
})
+ if err == nil {
+ break
+ }
+ glog.V(1).Infof("wait for volume %s", vid)
+ time.Sleep(waitTime)
+ waitTime += waitTime / 2
+ }
+
+ if err != nil {
+ return nil, err
}
for _, loc := range locations.Locations {
diff --git a/weed/filer/stream.go b/weed/filer/stream.go
index f6e2a7643..a41aebe22 100644
--- a/weed/filer/stream.go
+++ b/weed/filer/stream.go
@@ -34,7 +34,7 @@ func StreamContent(masterClient *wdclient.MasterClient, w io.Writer, chunks []*f
urlStrings := fileId2Url[chunkView.FileId]
data, err := retriedFetchChunkData(urlStrings, chunkView.CipherKey, chunkView.IsGzipped, chunkView.IsFullChunk(), chunkView.Offset, int(chunkView.Size))
- if err == nil {
+ if err != nil {
return err
}
w.Write(data)
diff --git a/weed/filesys/filehandle.go b/weed/filesys/filehandle.go
index 660bbf076..e1524f939 100644
--- a/weed/filesys/filehandle.go
+++ b/weed/filesys/filehandle.go
@@ -79,7 +79,7 @@ func (fh *FileHandle) Read(ctx context.Context, req *fuse.ReadRequest, resp *fus
if err != nil {
glog.Warningf("file handle read %s %d: %v", fh.f.fullpath(), totalRead, err)
- return nil
+ return fuse.EIO
}
if totalRead > int64(len(buff)) {
diff --git a/weed/server/filer_server_handlers_read_dir.go b/weed/server/filer_server_handlers_read_dir.go
index 9ca0209f4..99345550c 100644
--- a/weed/server/filer_server_handlers_read_dir.go
+++ b/weed/server/filer_server_handlers_read_dir.go
@@ -2,6 +2,9 @@ package weed_server
import (
"context"
+ "encoding/base64"
+ "fmt"
+ "github.com/skip2/go-qrcode"
"net/http"
"strconv"
"strings"
@@ -65,21 +68,30 @@ func (fs *FilerServer) listDirectoryHandler(w http.ResponseWriter, r *http.Reque
lastFileName,
shouldDisplayLoadMore,
})
- } else {
- ui.StatusTpl.Execute(w, struct {
- Path string
- Breadcrumbs []ui.Breadcrumb
- Entries interface{}
- Limit int
- LastFileName string
- ShouldDisplayLoadMore bool
- }{
- path,
- ui.ToBreadcrumb(path),
- entries,
- limit,
- lastFileName,
- shouldDisplayLoadMore,
- })
+ return
+ }
+
+ var qrImageString string
+ img, err := qrcode.Encode(fmt.Sprintf("http://%s:%d%s", fs.option.Host, fs.option.Port, r.URL.Path), qrcode.Medium, 128)
+ if err == nil {
+ qrImageString = base64.StdEncoding.EncodeToString(img)
}
+
+ ui.StatusTpl.Execute(w, struct {
+ Path string
+ Breadcrumbs []ui.Breadcrumb
+ Entries interface{}
+ Limit int
+ LastFileName string
+ ShouldDisplayLoadMore bool
+ QrImage string
+ }{
+ path,
+ ui.ToBreadcrumb(path),
+ entries,
+ limit,
+ lastFileName,
+ shouldDisplayLoadMore,
+ qrImageString,
+ })
}
diff --git a/weed/server/filer_ui/templates.go b/weed/server/filer_ui/templates.go
index 04a81433b..f86dde5b1 100644
--- a/weed/server/filer_ui/templates.go
+++ b/weed/server/filer_ui/templates.go
@@ -21,9 +21,11 @@ var funcMap = template.FuncMap{
var StatusTpl = template.Must(template.New("status").Funcs(funcMap).Parse(`<!DOCTYPE html>
<html>
<head>
- <title>SeaweedFS Filer</title>
- <link rel="stylesheet" href="/seaweedfsstatic/bootstrap/3.3.1/css/bootstrap.min.css">
+ <title>SeaweedFS Filer</title>
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <link rel="stylesheet" href="/seaweedfsstatic/bootstrap/3.3.1/css/bootstrap.min.css">
<style>
+body { padding-bottom: 70px; }
#drop-area {
border: 1px transparent;
}
@@ -46,6 +48,11 @@ var StatusTpl = template.Must(template.New("status").Funcs(funcMap).Parse(`<!DOC
#fileElem {
display: none;
}
+.qrImage {
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+}
</style>
</head>
<body>
@@ -116,6 +123,14 @@ var StatusTpl = template.Must(template.New("status").Funcs(funcMap).Parse(`<!DOC
</a>
</div>
{{end}}
+
+ <br/>
+ <br/>
+
+ <div class="navbar navbar-fixed-bottom">
+ <img src="data:image/png;base64,{{.QrImage}}" class="qrImage" />
+ </div>
+
</div>
</body>
<script type="text/javascript">