diff options
Diffstat (limited to 'weed/server')
| -rw-r--r-- | weed/server/filer_server_handlers_read_dir.go | 6 | ||||
| -rw-r--r-- | weed/server/filer_server_handlers_write_autochunk.go | 12 | ||||
| -rw-r--r-- | weed/server/filer_server_handlers_write_merge.go | 11 | ||||
| -rw-r--r-- | weed/server/filer_ui/filer.html | 229 | ||||
| -rw-r--r-- | weed/server/master_grpc_server.go | 12 |
5 files changed, 232 insertions, 38 deletions
diff --git a/weed/server/filer_server_handlers_read_dir.go b/weed/server/filer_server_handlers_read_dir.go index f67e90d38..8382cfc76 100644 --- a/weed/server/filer_server_handlers_read_dir.go +++ b/weed/server/filer_server_handlers_read_dir.go @@ -46,8 +46,10 @@ func (fs *FilerServer) listDirectoryHandler(w http.ResponseWriter, r *http.Reque path = "" } + emptyFolder := true if len(entries) > 0 { lastFileName = entries[len(entries)-1].Name() + emptyFolder = false } glog.V(4).Infof("listDirectory %s, last file %s, limit %d: %d items", path, lastFileName, limit, len(entries)) @@ -59,12 +61,14 @@ func (fs *FilerServer) listDirectoryHandler(w http.ResponseWriter, r *http.Reque Limit int LastFileName string ShouldDisplayLoadMore bool + EmptyFolder bool }{ path, entries, limit, lastFileName, shouldDisplayLoadMore, + emptyFolder, }) return } @@ -76,6 +80,7 @@ func (fs *FilerServer) listDirectoryHandler(w http.ResponseWriter, r *http.Reque Limit int LastFileName string ShouldDisplayLoadMore bool + EmptyFolder bool }{ path, ui.ToBreadcrumb(path), @@ -83,5 +88,6 @@ func (fs *FilerServer) listDirectoryHandler(w http.ResponseWriter, r *http.Reque limit, lastFileName, shouldDisplayLoadMore, + emptyFolder, }) } diff --git a/weed/server/filer_server_handlers_write_autochunk.go b/weed/server/filer_server_handlers_write_autochunk.go index 854b35f82..9bf2df6ef 100644 --- a/weed/server/filer_server_handlers_write_autochunk.go +++ b/weed/server/filer_server_handlers_write_autochunk.go @@ -164,6 +164,7 @@ func (fs *FilerServer) saveMetaData(ctx context.Context, r *http.Request, fileNa } var entry *filer.Entry + var newChunks []*filer_pb.FileChunk var mergedChunks []*filer_pb.FileChunk isAppend := isAppend(r) @@ -186,7 +187,7 @@ func (fs *FilerServer) saveMetaData(ctx context.Context, r *http.Request, fileNa } entry.FileSize += uint64(chunkOffset) } - mergedChunks = append(entry.Chunks, fileChunks...) + newChunks = append(entry.Chunks, fileChunks...) // TODO if len(entry.Content) > 0 { @@ -196,7 +197,7 @@ func (fs *FilerServer) saveMetaData(ctx context.Context, r *http.Request, fileNa } else { glog.V(4).Infoln("saving", path) - mergedChunks = fileChunks + newChunks = fileChunks entry = &filer.Entry{ FullPath: util.FullPath(path), Attr: filer.Attr{ @@ -217,6 +218,13 @@ func (fs *FilerServer) saveMetaData(ctx context.Context, r *http.Request, fileNa } } + // maybe concatenate small chunks into one whole chunk + mergedChunks, replyerr = fs.maybeMergeChunks(so, newChunks) + if replyerr != nil { + glog.V(0).Infof("merge chunks %s: %v", r.RequestURI, replyerr) + mergedChunks = newChunks + } + // maybe compact entry chunks mergedChunks, replyerr = filer.MaybeManifestize(fs.saveAsChunk(so), mergedChunks) if replyerr != nil { diff --git a/weed/server/filer_server_handlers_write_merge.go b/weed/server/filer_server_handlers_write_merge.go new file mode 100644 index 000000000..dadc6f726 --- /dev/null +++ b/weed/server/filer_server_handlers_write_merge.go @@ -0,0 +1,11 @@ +package weed_server + +import ( + "github.com/chrislusf/seaweedfs/weed/operation" + "github.com/chrislusf/seaweedfs/weed/pb/filer_pb" +) + +func (fs *FilerServer) maybeMergeChunks(so *operation.StorageOption, inputChunks []*filer_pb.FileChunk) (mergedChunks []*filer_pb.FileChunk, err error) { + //TODO merge consecutive smaller chunks into a large chunk to reduce number of chunks + return inputChunks, nil +} diff --git a/weed/server/filer_ui/filer.html b/weed/server/filer_ui/filer.html index 6f57c25d8..593d115f0 100644 --- a/weed/server/filer_ui/filer.html +++ b/weed/server/filer_ui/filer.html @@ -26,6 +26,12 @@ border-radius: 2px; border: 1px solid #ccc; float: right; + margin-left: 2px; + margin-bottom: 0; + } + + label { + font-weight: normal; } .button:hover { @@ -36,6 +42,50 @@ display: none; } + td, th { + vertical-align: bottom; + } + + .danger { + color: red; + background: #fff; + border: 1px solid #fff; + border-radius: 2px; + } + + .info { + background: #fff; + border: 1px solid #fff; + border-radius: 2px; + } + + .footer { + position: absolute; + bottom: 10px; + right: 10%; + min-width: 30%; + } + + .progress-table { + width: 100%; + } + + .progress-table-file-name { + text-align: right; + } + + .progress-table-percent { + width: 60px; + text-align: right; + } + + .add-files { + font-size: 46px; + text-align: center; + border: 1px dashed #999; + padding-bottom: 9px; + margin: 0 2px; + } </style> </head> <body> @@ -54,6 +104,7 @@ </a> {{ end }} <label class="button" for="fileElem">Upload</label> + <label class="button" onclick="handleCreateDir()">New Folder</label> </div> </div> @@ -61,13 +112,13 @@ <form class="upload-form"> <input type="file" id="fileElem" multiple onchange="handleFiles(this.files)"> - <table width="90%"> + <table width="100%"> {{$path := .Path }} {{ range $entry_index, $entry := .Entries }} <tr> <td> {{if $entry.IsDirectory}} - <img src="/seaweedfsstatic/images/folder.gif" width="20" height="23"> + <img src="/seaweedfsstatic/images/folder.gif" width="20" height="16"> <a href="{{ printpath $path "/" $entry.Name "/"}}" > {{ $entry.Name }} </a> @@ -89,13 +140,25 @@ {{ $entry.Size | humanizeBytes }} {{end}} </td> - <td nowrap> + <td align="right" nowrap> {{ $entry.Timestamp.Format "2006-01-02 15:04" }} </td> + <td> + {{if $entry.IsDirectory}} + <label class="button danger" onclick="handleDelete('{{ printpath $path "/" $entry.Name "/" }}')">Delete</label> + {{else}} + <label class="button danger" onclick="handleDelete('{{ printpath $path "/" $entry.Name }}')">Delete</label> + {{end}} + <label class="button info" onclick="handleRename('{{ $entry.Name }}', '{{ printpath $path "/" }}')">Rename</label> + </td> </tr> {{ end }} - </table> + {{if .EmptyFolder}} + <div class="row add-files"> + + + </div> + {{end}} </form> </div> @@ -109,65 +172,171 @@ <br/> <br/> - + <div id="progress-area" class="footer" style="display: none;"> + </div> </div> </body> <script type="text/javascript"> // ************************ Drag and drop ***************** // - let dropArea = document.getElementById("drop-area") + let dropArea = document.getElementById("drop-area"); + let progressArea = document.getElementById("progress-area"); // Prevent default drag behaviors ;['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => { - dropArea.addEventListener(eventName, preventDefaults, false) - document.body.addEventListener(eventName, preventDefaults, false) - }) + dropArea.addEventListener(eventName, preventDefaults, false); + document.body.addEventListener(eventName, preventDefaults, false); + }); // Highlight drop area when item is dragged over it ;['dragenter', 'dragover'].forEach(eventName => { - dropArea.addEventListener(eventName, highlight, false) - }) + dropArea.addEventListener(eventName, highlight, false); + }); ;['dragleave', 'drop'].forEach(eventName => { - dropArea.addEventListener(eventName, unhighlight, false) - }) + dropArea.addEventListener(eventName, unhighlight, false); + }); // Handle dropped files - dropArea.addEventListener('drop', handleDrop, false) + dropArea.addEventListener('drop', handleDrop, false); function preventDefaults(e) { - e.preventDefault() - e.stopPropagation() + e.preventDefault(); + e.stopPropagation(); } function highlight(e) { - dropArea.classList.add('highlight') + dropArea.classList.add('highlight'); } function unhighlight(e) { - dropArea.classList.remove('highlight') + dropArea.classList.remove('highlight'); } function handleDrop(e) { - var dt = e.dataTransfer - var files = dt.files + var dt = e.dataTransfer; + var files = dt.files; - handleFiles(files) + handleFiles(files); } + var uploadList = {}; + function handleFiles(files) { - files = [...files] - files.forEach(uploadFile) - window.location.reload() + files = [...files]; + files.forEach(startUpload); + renderProgress(); + files.forEach(uploadFile); + } + + function startUpload(file, i) { + uploadList[file.name] = {'name': file.name, 'percent': 0, 'finish': false}; + } + + function renderProgress() { + var values = Object.values(uploadList); + var html = '<table class="progress-table">\n'; + for (let i of values) { + html += '<tr>\n<td class="progress-table-file-name">' + i.name + '<\/td>\n'; + html += '<td class="progress-table-percent">' + i.percent + '% <\/td>\n<\/tr>\n'; + } + html += '<\/table>\n'; + progressArea.innerHTML = html; + if (values.length > 0) { + progressArea.attributes.style.value = ''; + } + console.log('Render Progress', values); + } + + function reportProgress(file, percent) { + var item = uploadList[file] + item.percent = percent; + renderProgress(); + } + + function finishUpload(file) { + uploadList[file]['finish'] = true; + renderProgress(); + var allFinish = true; + for (let i of Object.values(uploadList)) { + if (!i.finish) { + allFinish = false; + break; + } + } + if (allFinish) { + console.log('All Finish'); + window.location.reload(); + } } function uploadFile(file, i) { - var url = window.location.href - var xhr = new XMLHttpRequest() - var formData = new FormData() - xhr.open('POST', url, false) + var url = window.location.href; + var xhr = new XMLHttpRequest(); + var fileName = file.name; + xhr.upload.addEventListener('progress', function(e) { + if (e.lengthComputable) { + var percent = Math.ceil((e.loaded / e.total) * 100); + reportProgress(fileName, percent) + } + }); + xhr.upload.addEventListener('loadend', function(e) { + finishUpload(fileName); + }); + var formData = new FormData(); + xhr.open('POST', url, true); + formData.append('file', file); + xhr.send(formData); + } + + function handleCreateDir() { + var dirName = prompt('Directory Name:', ''); + dirName = dirName.trim(); + if (dirName == null || dirName == '') { + return; + } + var baseUrl = window.location.href; + if (!baseUrl.endsWith('/')) { + baseUrl += '/'; + } + var url = baseUrl + dirName; + if (!url.endsWith('/')) { + url += '/'; + } + var xhr = new XMLHttpRequest(); + xhr.open('POST', url, false); + xhr.setRequestHeader('Content-Type', ''); + xhr.send(); + window.location.reload(); + } + + function handleRename(originName, basePath) { + var newName = prompt('New Name:', originName); + if (newName == null || newName == '') { + return; + } + var url = basePath + newName; + var originPath = basePath + originName; + url += '?mv.from=' + originPath; + var xhr = new XMLHttpRequest(); + xhr.open('POST', url, false); + xhr.setRequestHeader('Content-Type', ''); + xhr.send(); + window.location.reload(); + } + + function handleDelete(path) { + if (!confirm('Are you sure to delete ' + path + '?')) { + return; + } + var url = path; + if (url.endsWith('/')) { + url += '?recursive=true'; + } - formData.append('file', file) - xhr.send(formData) + var xhr = new XMLHttpRequest(); + xhr.open('DELETE', url, false); + xhr.send(); + window.location.reload(); } </script> </html> diff --git a/weed/server/master_grpc_server.go b/weed/server/master_grpc_server.go index 50fcc0d62..1ad8edf91 100644 --- a/weed/server/master_grpc_server.go +++ b/weed/server/master_grpc_server.go @@ -133,13 +133,13 @@ func (ms *MasterServer) SendHeartbeat(stream master_pb.Seaweed_SendHeartbeatServ ms.Topo.IncrementalSyncDataNodeEcShards(heartbeat.NewEcShards, heartbeat.DeletedEcShards, dn) for _, s := range heartbeat.NewEcShards { - message.NewVids = append(message.NewVids, s.Id) + message.NewEcVids = append(message.NewEcVids, s.Id) } for _, s := range heartbeat.DeletedEcShards { - if dn.HasVolumesById(needle.VolumeId(s.Id)) { + if dn.HasEcShards(needle.VolumeId(s.Id)) { continue } - message.DeletedVids = append(message.DeletedVids, s.Id) + message.DeletedEcVids = append(message.DeletedEcVids, s.Id) } } @@ -151,17 +151,17 @@ func (ms *MasterServer) SendHeartbeat(stream master_pb.Seaweed_SendHeartbeatServ // broadcast the ec vid changes to master clients for _, s := range newShards { - message.NewVids = append(message.NewVids, uint32(s.VolumeId)) + message.NewEcVids = append(message.NewEcVids, uint32(s.VolumeId)) } for _, s := range deletedShards { if dn.HasVolumesById(s.VolumeId) { continue } - message.DeletedVids = append(message.DeletedVids, uint32(s.VolumeId)) + message.DeletedEcVids = append(message.DeletedEcVids, uint32(s.VolumeId)) } } - if len(message.NewVids) > 0 || len(message.DeletedVids) > 0 { + if len(message.NewVids) > 0 || len(message.DeletedVids) > 0 || len(message.NewEcVids) > 0 || len(message.DeletedEcVids) > 0 { ms.broadcastToClients(&master_pb.KeepConnectedResponse{VolumeLocation: message}) } |
