Skip to content

Commit

Permalink
Simplify file service.
Browse files Browse the repository at this point in the history
Instead of having worker goroutines, we use a channel as a semaphore to
limit the number of concurrent requests for the file service, but
perform all the work synchronously.
  • Loading branch information
dustin committed Jun 4, 2013
1 parent ecdb512 commit 2f42633
Showing 1 changed file with 11 additions and 32 deletions.
43 changes: 11 additions & 32 deletions file_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,12 @@ import (
"os"
)

type fileRequest struct {
path string
flags int
f func(f *os.File) error
res chan error
}

type FileService struct {
reqs chan fileRequest
reqs chan bool
}

func NewFileService(workers int) *FileService {
fs := &FileService{make(chan fileRequest, 1000)}
for i := 0; i < workers; i++ {
go fs.worker()
}
return fs
func NewFileService(concurrency int) *FileService {
return &FileService{make(chan bool, concurrency)}
}

// Open a FileLike thing that works within this FileService.
Expand All @@ -34,27 +23,17 @@ func (fs *FileService) OpenFile(path string, mode int) (FileLike, error) {
}

func (f *FileService) Do(path string, flags int, fn func(*os.File) error) error {
r := fileRequest{path, flags, fn, make(chan error, 1)}
f.reqs <- r
return <-r.res
f.reqs <- true
defer func() { <-f.reqs }()
file, err := os.OpenFile(path, flags, 0666)
if err != nil {
return err
}
defer file.Close()
return fn(file)
}

func (f *FileService) Close() error {
close(f.reqs)
return nil
}

func serviceFileRequest(r fileRequest) {
f, err := os.OpenFile(r.path, r.flags, 0666)
if err == nil {
defer f.Close()
err = r.f(f)
}
r.res <- err
}

func (f *FileService) worker() {
for req := range f.reqs {
serviceFileRequest(req)
}
}

0 comments on commit 2f42633

Please sign in to comment.