save+backup: Process the save & backup with a sequential channel

As advantage we don't need to synchonize them any longer and
don't need further insufficient lock mechanisms.
This commit is contained in:
Jöran Karl
2024-10-01 21:53:47 +02:00
parent 35d295dd04
commit 771aab251c
2 changed files with 50 additions and 25 deletions

View File

@@ -6,8 +6,6 @@ import (
"io/fs"
"os"
"path/filepath"
"sync/atomic"
"time"
"github.com/zyedidia/micro/v2/internal/config"
"github.com/zyedidia/micro/v2/internal/screen"
@@ -34,27 +32,7 @@ The backup was created on %s and its path is:
Options: [r]ecover, [i]gnore, [a]bort: `
var backupRequestChan chan *Buffer
func backupThread() {
for {
time.Sleep(time.Second * 8)
for len(backupRequestChan) > 0 {
b := <-backupRequestChan
bfini := atomic.LoadInt32(&(b.fini)) != 0
if !bfini {
b.Backup()
}
}
}
}
func init() {
backupRequestChan = make(chan *Buffer, 10)
go backupThread()
}
const backupSeconds = 8
func (b *Buffer) RequestBackup() {
if !b.requestedBackup {

View File

@@ -11,6 +11,8 @@ import (
"os/signal"
"path/filepath"
"runtime"
"sync/atomic"
"time"
"unicode"
"github.com/zyedidia/micro/v2/internal/config"
@@ -32,6 +34,48 @@ type wrappedFile struct {
sigChan chan os.Signal
}
type saveResponse struct {
size int
err error
}
type saveRequest struct {
buf *Buffer
path string
withSudo bool
newFile bool
saveResponseChan chan saveResponse
}
var saveRequestChan chan saveRequest
var backupRequestChan chan *Buffer
func init() {
saveRequestChan = make(chan saveRequest, 10)
backupRequestChan = make(chan *Buffer, 10)
go func() {
duration := backupSeconds * float64(time.Second)
backupTicker := time.NewTicker(time.Duration(duration))
for {
select {
case sr := <-saveRequestChan:
size, err := sr.buf.safeWrite(sr.path, sr.withSudo, sr.newFile)
sr.saveResponseChan <- saveResponse{size, err}
case <-backupTicker.C:
for len(backupRequestChan) > 0 {
b := <-backupRequestChan
bfini := atomic.LoadInt32(&(b.fini)) != 0
if !bfini {
b.Backup()
}
}
}
}
}()
}
func openFile(name string, withSudo bool) (wrappedFile, error) {
var err error
var writeCloser io.WriteCloser
@@ -267,13 +311,16 @@ func (b *Buffer) saveToFile(filename string, withSudo bool, autoSave bool) error
}
}
size, err := b.safeWrite(absFilename, withSudo, newFile)
saveResponseChan := make(chan saveResponse)
saveRequestChan <- saveRequest{b, absFilename, withSudo, newFile, saveResponseChan}
result := <-saveResponseChan
err = result.err
if err != nil {
return err
}
if !b.Settings["fastdirty"].(bool) {
if size > LargeFileThreshold {
if result.size > LargeFileThreshold {
// For large files 'fastdirty' needs to be on
b.Settings["fastdirty"] = true
} else {