120 lines
1.9 KiB
Go
120 lines
1.9 KiB
Go
package tape
|
|
|
|
import (
|
|
"io"
|
|
"os"
|
|
"sync"
|
|
|
|
"github.com/pojntfx/stfs/pkg/config"
|
|
)
|
|
|
|
type TapeManager struct {
|
|
drive string
|
|
mt config.MagneticTapeIO
|
|
recordSize int
|
|
overwrite bool
|
|
|
|
physicalLock sync.Mutex
|
|
|
|
readerLock sync.Mutex
|
|
reader *os.File
|
|
readerIsRegular bool
|
|
|
|
closer func() error
|
|
|
|
overwrote bool
|
|
}
|
|
|
|
func NewTapeManager(
|
|
drive string,
|
|
mt config.MagneticTapeIO,
|
|
recordSize int,
|
|
overwrite bool,
|
|
) *TapeManager {
|
|
return &TapeManager{
|
|
drive: drive,
|
|
mt: mt,
|
|
recordSize: recordSize,
|
|
overwrite: overwrite,
|
|
}
|
|
}
|
|
|
|
func (m *TapeManager) GetWriter() (config.DriveWriterConfig, error) {
|
|
m.physicalLock.Lock()
|
|
|
|
overwrite := m.overwrite
|
|
if m.overwrote {
|
|
overwrite = false
|
|
}
|
|
m.overwrote = true
|
|
|
|
writer, writerIsRegular, err := OpenTapeWriteOnly(
|
|
m.drive,
|
|
m.mt,
|
|
m.recordSize,
|
|
overwrite,
|
|
)
|
|
if err != nil {
|
|
return config.DriveWriterConfig{}, err
|
|
}
|
|
|
|
m.closer = writer.Close
|
|
|
|
return config.DriveWriterConfig{
|
|
Drive: writer,
|
|
DriveIsRegular: writerIsRegular,
|
|
}, nil
|
|
}
|
|
|
|
func (m *TapeManager) GetReader() (config.DriveReaderConfig, error) {
|
|
if err := m.openOrReuseReader(); err != nil {
|
|
return config.DriveReaderConfig{}, err
|
|
}
|
|
|
|
return config.DriveReaderConfig{
|
|
Drive: m.reader,
|
|
DriveIsRegular: m.readerIsRegular,
|
|
}, nil
|
|
}
|
|
|
|
func (m *TapeManager) Close() error {
|
|
if m.closer != nil {
|
|
if err := m.closer(); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
m.physicalLock.Unlock()
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m *TapeManager) openOrReuseReader() error {
|
|
m.readerLock.Lock()
|
|
defer m.readerLock.Unlock()
|
|
|
|
reopen := false
|
|
if m.reader == nil {
|
|
reopen = true
|
|
} else if _, err := m.reader.Seek(0, io.SeekCurrent); err != nil {
|
|
// File is closed
|
|
reopen = true
|
|
}
|
|
|
|
if reopen {
|
|
m.physicalLock.Lock()
|
|
|
|
r, rr, err := OpenTapeReadOnly(m.drive)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
m.reader = r
|
|
m.readerIsRegular = rr
|
|
|
|
m.closer = r.Close
|
|
}
|
|
|
|
return nil
|
|
}
|