2019-01-24 20:15:10 +00:00
|
|
|
// Copyright (C) 2019 Storj Labs, Inc.
|
2018-12-20 14:51:39 +00:00
|
|
|
// See LICENSE for copying information
|
|
|
|
|
|
|
|
package sync2
|
|
|
|
|
|
|
|
import (
|
|
|
|
"io"
|
|
|
|
"os"
|
|
|
|
"sync/atomic"
|
2019-01-11 15:35:26 +00:00
|
|
|
|
|
|
|
"github.com/zeebo/errs"
|
2018-12-20 14:51:39 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// ReadAtWriteAtCloser implements all io.ReaderAt, io.WriterAt and io.Closer
|
|
|
|
type ReadAtWriteAtCloser interface {
|
|
|
|
io.ReaderAt
|
|
|
|
io.WriterAt
|
|
|
|
io.Closer
|
|
|
|
}
|
|
|
|
|
|
|
|
// PipeWriter allows closing the writer with an error
|
|
|
|
type PipeWriter interface {
|
|
|
|
io.WriteCloser
|
|
|
|
CloseWithError(reason error) error
|
|
|
|
}
|
|
|
|
|
|
|
|
// PipeReader allows closing the reader with an error
|
|
|
|
type PipeReader interface {
|
|
|
|
io.ReadCloser
|
|
|
|
CloseWithError(reason error) error
|
|
|
|
}
|
|
|
|
|
|
|
|
// memory implements ReadAtWriteAtCloser on a memory buffer
|
|
|
|
type memory []byte
|
|
|
|
|
|
|
|
// Size returns size of memory buffer
|
|
|
|
func (memory memory) Size() int { return len(memory) }
|
|
|
|
|
|
|
|
// ReadAt implements io.ReaderAt methods
|
|
|
|
func (memory memory) ReadAt(data []byte, at int64) (amount int, err error) {
|
|
|
|
if at > int64(len(memory)) {
|
|
|
|
return 0, io.ErrClosedPipe
|
|
|
|
}
|
|
|
|
amount = copy(data, memory[at:])
|
|
|
|
return amount, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// WriteAt implements io.WriterAt methods
|
|
|
|
func (memory memory) WriteAt(data []byte, at int64) (amount int, err error) {
|
|
|
|
if at > int64(len(memory)) {
|
|
|
|
return 0, io.ErrClosedPipe
|
|
|
|
}
|
|
|
|
amount = copy(memory[at:], data)
|
|
|
|
return amount, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Close implements io.Closer implementation
|
|
|
|
func (memory memory) Close() error { return nil }
|
|
|
|
|
|
|
|
// offsetFile implements ReadAt, WriteAt offset to the file with reference counting
|
|
|
|
type offsetFile struct {
|
|
|
|
file *os.File
|
|
|
|
offset int64
|
2019-01-11 15:35:26 +00:00
|
|
|
open *int64 // number of handles open
|
2018-12-20 14:51:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ReadAt implements io.ReaderAt methods
|
|
|
|
func (file offsetFile) ReadAt(data []byte, at int64) (amount int, err error) {
|
|
|
|
return file.file.ReadAt(data, file.offset+at)
|
|
|
|
}
|
|
|
|
|
|
|
|
// WriteAt implements io.WriterAt methods
|
|
|
|
func (file offsetFile) WriteAt(data []byte, at int64) (amount int, err error) {
|
|
|
|
return file.file.WriteAt(data, file.offset+at)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Close implements io.Closer methods
|
|
|
|
func (file offsetFile) Close() error {
|
|
|
|
if atomic.AddInt64(file.open, -1) == 0 {
|
2019-01-11 15:35:26 +00:00
|
|
|
return errs.Combine(
|
2019-01-24 20:48:54 +00:00
|
|
|
file.file.Close(),
|
2019-01-11 15:35:26 +00:00
|
|
|
os.Remove(file.file.Name()),
|
|
|
|
)
|
2018-12-20 14:51:39 +00:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|