Skip to content

Commit

Permalink
feat: useable
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelncui committed Dec 12, 2022
1 parent af8c37b commit f87ec06
Show file tree
Hide file tree
Showing 134 changed files with 18,715 additions and 1,343 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,8 @@
# Dependency directories (remove the comment below to include it)
# vendor/
output/
frontend/node_modules/
client/node_modules/

tapes.db
upload_test.sh
7 changes: 7 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"protoc": {
"options": [
"--proto_path=./entity"
]
}
}
21 changes: 21 additions & 0 deletions apis/api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package apis

import (
"github.com/abc950309/tapewriter/entity"
"github.com/abc950309/tapewriter/executor"
"github.com/abc950309/tapewriter/library"
)

// JobGet(context.Context, *entity.JobGetRequest) (*entity.JobGetReply, error)

type API struct {
entity.UnimplementedServiceServer

lib *library.Library
exe *executor.Executor
sourceBase string
}

func New(base string, lib *library.Library, exe *executor.Executor) *API {
return &API{lib: lib, exe: exe, sourceBase: base}
}
98 changes: 98 additions & 0 deletions apis/converts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package apis

import (
"io/fs"
"path"
"path/filepath"
"time"

"github.com/abc950309/tapewriter/entity"
"github.com/abc950309/tapewriter/executor"
"github.com/abc950309/tapewriter/library"
)

func convertFiles(files ...*library.File) []*entity.File {
results := make([]*entity.File, 0, len(files))
for _, f := range files {
results = append(results, &entity.File{
Id: f.ID,
ParentId: f.ParentID,
Name: f.Name,
Mode: int64(f.Mode),
ModTime: f.ModTime.Unix(),
Size: f.Size,
Hash: f.Hash,
})
}
return results
}

func convertPositions(positions ...*library.Position) []*entity.Position {
results := make([]*entity.Position, 0, len(positions))
for _, p := range positions {
results = append(results, &entity.Position{
Id: p.ID,
FileId: p.FileID,
TapeId: p.TapeID,
Path: p.Path,
Mode: int64(p.Mode),
ModTime: p.ModTime.Unix(),
WriteTime: p.WriteTime.Unix(),
Size: p.Size,
Hash: p.Hash,
})
}
return results
}

func convertSourceFiles(parent string, files ...fs.FileInfo) []*entity.SourceFile {
results := make([]*entity.SourceFile, 0, len(files))
for _, f := range files {
if !f.Mode().IsDir() && !f.Mode().IsRegular() {
continue
}

_, file := path.Split(f.Name())
results = append(results, &entity.SourceFile{
Path: filepath.Join(parent, file),
ParentPath: parent,
Name: file,
Mode: int64(f.Mode()),
ModTime: f.ModTime().Unix(),
Size: f.Size(),
})
}
return results
}

func convertJobs(jobs ...*executor.Job) []*entity.Job {
converted := make([]*entity.Job, 0, len(jobs))
for _, job := range jobs {
converted = append(converted, &entity.Job{
Id: job.ID,
Status: job.Status,
Priority: job.Priority,
CreateTime: job.CreateTime.Unix(),
UpdateTime: job.UpdateTime.Unix(),
State: job.State,
})
}
return converted
}

func convertOptionalTime(t *time.Time) *int64 {
if t == nil {
return nil
}

u := t.Unix()
return &u
}

func map2list[K, T comparable](mapping map[K]T) []T {
result := make([]T, 0, len(mapping))
for _, v := range mapping {
result = append(result, v)
}
return result
}
11 changes: 11 additions & 0 deletions apis/device_list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package apis

import (
"context"

"github.com/abc950309/tapewriter/entity"
)

func (api *API) DeviceList(ctx context.Context, req *entity.DeviceListRequest) (*entity.DeviceListReply, error) {
return &entity.DeviceListReply{Devices: api.exe.ListAvailableDevices()}, nil
}
16 changes: 16 additions & 0 deletions apis/file_delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package apis

import (
"context"

"github.com/abc950309/tapewriter/entity"
mapset "github.com/deckarep/golang-set/v2"
)

func (api *API) FileDelete(ctx context.Context, req *entity.FileDeleteRequest) (*entity.FileDeleteReply, error) {
ids := mapset.NewThreadUnsafeSet(req.Ids...)
if err := api.lib.Delete(ctx, ids.ToSlice()); err != nil {
return nil, err
}
return new(entity.FileDeleteReply), nil
}
54 changes: 54 additions & 0 deletions apis/file_edit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package apis

import (
"context"
"fmt"
"io/fs"
"path"
"strings"

"github.com/abc950309/tapewriter/entity"
)

func (api *API) FileEdit(ctx context.Context, req *entity.FileEditRequest) (*entity.FileEditReply, error) {
file, err := api.lib.GetFile(ctx, req.Id)
if err != nil {
return nil, err
}
if file == nil {
return nil, fmt.Errorf("file not found, id= %d", req.Id)
}

if req.File.ParentId != nil {
file.ParentID = *req.File.ParentId
}
if req.File.Name != nil {
name := strings.TrimSpace(*req.File.Name)
if name == "" {
return nil, fmt.Errorf("unexpected target name, not a string")
}

if !strings.ContainsAny(name, `\/`) {
file.Name = name
} else {
name = path.Clean(strings.ReplaceAll(name, `\`, `/`))

dirname, filename := path.Split(name)
if filename == "" {
return nil, fmt.Errorf("unexpected target name, end with slash, '%s'", name)
}

dir, err := api.lib.MkdirAll(ctx, file.ParentID, dirname, fs.ModePerm)
if err != nil {
return nil, err
}

file.ParentID = dir.ID
}
}

if err := api.lib.MoveFile(ctx, file); err != nil {
return nil, err
}
return &entity.FileEditReply{File: convertFiles(file)[0]}, nil
}
37 changes: 37 additions & 0 deletions apis/file_get.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package apis

import (
"context"
"errors"

"github.com/abc950309/tapewriter/entity"
"github.com/abc950309/tapewriter/library"
)

func (api *API) FileGet(ctx context.Context, req *entity.FileGetRequest) (*entity.FileGetReply, error) {
libFile, err := api.lib.GetFile(ctx, req.Id)
if err != nil && !errors.Is(err, library.ErrFileNotFound) {
return nil, err
}

var file *entity.File
if libFile != nil {
file = convertFiles(libFile)[0]
}

positions, err := api.lib.GetPositionByFileID(ctx, req.Id)
if err != nil {
return nil, err
}

children, err := api.lib.List(ctx, req.Id)
if err != nil {
return nil, err
}

return &entity.FileGetReply{
File: file,
Positions: convertPositions(positions...),
Children: convertFiles(children...),
}, nil
}
16 changes: 16 additions & 0 deletions apis/file_list_parents.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package apis

import (
"context"

"github.com/abc950309/tapewriter/entity"
)

func (api *API) FileListParents(ctx context.Context, req *entity.FileListParentsRequest) (*entity.FileListParentsReply, error) {
files, err := api.lib.ListParents(ctx, req.Id)
if err != nil {
return nil, err
}

return &entity.FileListParentsReply{Parents: convertFiles(files...)}, nil
}
28 changes: 28 additions & 0 deletions apis/file_mkdir.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package apis

import (
"context"
"fmt"
"io/fs"

"github.com/abc950309/tapewriter/entity"
)

func (api *API) FileMkdir(ctx context.Context, req *entity.FileMkdirRequest) (*entity.FileMkdirReply, error) {
if req.ParentId != 0 {
parent, err := api.lib.GetFile(ctx, req.ParentId)
if err != nil || parent == nil {
return nil, err
}
if parent == nil {
return nil, fmt.Errorf("file not found, id= %d", req.ParentId)
}
}

dir, err := api.lib.MkdirAll(ctx, req.ParentId, req.Path, fs.ModePerm)
if err != nil {
return nil, err
}

return &entity.FileMkdirReply{File: convertFiles(dir)[0]}, nil
}
24 changes: 24 additions & 0 deletions apis/job_create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package apis

import (
"context"

"github.com/abc950309/tapewriter/entity"
"github.com/abc950309/tapewriter/executor"
)

func (api *API) JobCreate(ctx context.Context, req *entity.JobCreateRequest) (*entity.JobCreateReply, error) {
job, err := api.exe.CreateJob(ctx, &executor.Job{
Status: entity.JobStatus_Pending,
Priority: req.Job.Priority,
}, req.Job.Param)
if err != nil {
return nil, err
}

if err := api.exe.Start(ctx, job); err != nil {
return nil, err
}

return &entity.JobCreateReply{Job: convertJobs(job)[0]}, nil
}
21 changes: 21 additions & 0 deletions apis/job_display.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package apis

import (
"context"

"github.com/abc950309/tapewriter/entity"
)

func (api *API) JobDisplay(ctx context.Context, req *entity.JobDisplayRequest) (*entity.JobDisplayReply, error) {
job, err := api.exe.GetJob(ctx, req.Id)
if err != nil {
return &entity.JobDisplayReply{}, nil
}

result, err := api.exe.Display(ctx, job)
if err != nil {
return &entity.JobDisplayReply{}, nil
}

return &entity.JobDisplayReply{Display: result}, nil
}
32 changes: 32 additions & 0 deletions apis/job_get_log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package apis

import (
"context"
"fmt"
"io"

"github.com/abc950309/tapewriter/entity"
)

func (api *API) JobGetLog(ctx context.Context, req *entity.JobGetLogRequest) (*entity.JobGetLogReply, error) {
reader, err := api.exe.NewLogReader(req.JobId)
if err != nil {
return nil, fmt.Errorf("open log fail, %w", err)
}
if reader == nil {
return &entity.JobGetLogReply{Logs: []byte{}}, nil
}

if req.Offset > 0 {
if _, err := reader.Seek(req.Offset, 0); err != nil {
return nil, fmt.Errorf("seek log file fail, offset= %d, %w", req.Offset, err)
}
}

buf, err := io.ReadAll(reader)
if err != nil {
return nil, fmt.Errorf("read log fail, %w", err)
}

return &entity.JobGetLogReply{Logs: buf}, nil
}
Loading

0 comments on commit f87ec06

Please sign in to comment.