Files
yatm/library/tape.go
2023-09-26 16:47:06 +08:00

150 lines
3.9 KiB
Go

package library
import (
"context"
"fmt"
"os"
"time"
"github.com/samuelncui/yatm/entity"
)
var (
ModelTape = new(Tape)
)
type Tape struct {
ID int64 `gorm:"primaryKey;autoIncrement" json:"id,omitempty"`
Barcode string `gorm:"type:varchar(15);index:idx_barcode,unique" json:"barcode,omitempty"`
Name string `gorm:"type:varchar(256)" json:"name,omitempty"`
Encryption string `gorm:"type:varchar(2048)" json:"encryption,omitempty"`
CreateTime time.Time `json:"create_time,omitempty"`
DestroyTime *time.Time `json:"destroy_time,omitempty"`
CapacityBytes int64 `json:"capacity_bytes,omitempty"`
WritenBytes int64 `json:"writen_bytes,omitempty"`
}
type TapeFile struct {
Path string `json:"path"`
Size int64 `json:"size"`
Mode os.FileMode `json:"mode"`
ModTime time.Time `json:"mod_time"`
WriteTime time.Time `json:"write_time"`
Hash []byte `json:"hash"` // sha256
}
func (l *Library) CreateTape(ctx context.Context, tape *Tape, files []*TapeFile) (*Tape, error) {
tape.WritenBytes = 0
for _, file := range files {
tape.WritenBytes += file.Size
}
if tape.CapacityBytes == 0 {
tape.CapacityBytes = tape.WritenBytes
}
if r := l.db.WithContext(ctx).Save(tape); r.Error != nil {
return nil, fmt.Errorf("save tape fail, err= %w", r.Error)
}
positions := make([]*Position, 0, len(files))
for _, file := range files {
positions = append(positions, &Position{
TapeID: tape.ID,
Path: file.Path,
Mode: uint32(file.Mode),
ModTime: file.ModTime,
WriteTime: file.WriteTime,
Size: file.Size,
Hash: file.Hash,
})
}
if r := l.db.WithContext(ctx).CreateInBatches(positions, batchSize); r.Error != nil {
return nil, fmt.Errorf("save tape position fail, %w", r.Error)
}
return tape, nil
}
func (l *Library) GetTape(ctx context.Context, id int64) (*Tape, error) {
tapes, err := l.MGetTape(ctx, id)
if err != nil {
return nil, err
}
tape, ok := tapes[id]
if !ok || tape == nil {
return nil, ErrFileNotFound
}
return tape, nil
}
func (l *Library) DeleteTapes(ctx context.Context, ids ...int64) error {
// if r := l.db.WithContext(ctx).Where("tape_id IN (?)", ids).Delete(ModelPosition); r.Error != nil {
// return fmt.Errorf("delete file position fail, err= %w", r.Error)
// }
if r := l.db.WithContext(ctx).Where("id IN (?)", ids).Delete(ModelTape); r.Error != nil {
return fmt.Errorf("delete tapes fail, err= %w", r.Error)
}
return nil
}
func (l *Library) ListTape(ctx context.Context, filter *entity.TapeFilter) ([]*Tape, error) {
db := l.db.WithContext(ctx)
if filter.Limit != nil {
db = db.Limit(int(*filter.Limit))
} else {
db = db.Limit(20)
}
if filter.Offset != nil {
db = db.Offset(int(*filter.Offset))
}
db = db.Order("create_time DESC")
tapes := make([]*Tape, 0, 20)
if r := db.Find(&tapes); r.Error != nil {
return nil, fmt.Errorf("list tapes fail, err= %w", r.Error)
}
return tapes, nil
}
func (l *Library) MGetTape(ctx context.Context, tapeIDs ...int64) (map[int64]*Tape, error) {
if len(tapeIDs) == 0 {
return map[int64]*Tape{}, nil
}
tapes := make([]*Tape, 0, len(tapeIDs))
if r := l.db.WithContext(ctx).Where("id IN (?)", tapeIDs).Find(&tapes); r.Error != nil {
return nil, fmt.Errorf("mget tapes fail, err= %w", r.Error)
}
result := make(map[int64]*Tape, len(tapes))
for _, tape := range tapes {
result[tape.ID] = tape
}
return result, nil
}
func (l *Library) MGetTapeByBarcode(ctx context.Context, barcodes ...string) (map[string]*Tape, error) {
if len(barcodes) == 0 {
return map[string]*Tape{}, nil
}
tapes := make([]*Tape, 0, len(barcodes))
if r := l.db.WithContext(ctx).Where("barcode IN (?)", barcodes).Find(&tapes); r.Error != nil {
return nil, fmt.Errorf("mget tapes by barcode fail, err= %w", r.Error)
}
result := make(map[string]*Tape, len(tapes))
for _, tape := range tapes {
result[tape.Barcode] = tape
}
return result, nil
}