mirror of
https://github.com/criyle/go-judge.git
synced 2025-09-26 22:39:12 +08:00
212 lines
4.3 KiB
Go
212 lines
4.3 KiB
Go
package main
|
|
|
|
import "C"
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"log"
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/criyle/go-judge/cmd/executorserver/model"
|
|
"github.com/criyle/go-judge/env"
|
|
"github.com/criyle/go-judge/env/pool"
|
|
"github.com/criyle/go-judge/filestore"
|
|
"github.com/criyle/go-judge/worker"
|
|
)
|
|
|
|
type initParameter struct {
|
|
CInitPath string `json:"cinitPath"`
|
|
Parallelism int `json:"parallelism"`
|
|
TmpFsParam string `json:"tmpfsParam"`
|
|
Dir string `json:"dir"`
|
|
NetShare bool `json:"netShare"`
|
|
MountConf string `json:"mountConf"`
|
|
SrcPrefix string `json:"srcPrefix"`
|
|
CgroupPrefix string `json:"cgroupPrefix"`
|
|
CPUSet string `json:"cpuset"`
|
|
CredStart int `json:"credStart"`
|
|
}
|
|
|
|
var (
|
|
fs filestore.FileStore
|
|
work worker.Worker
|
|
|
|
srcPrefix string
|
|
)
|
|
|
|
func newFilsStore(dir string) filestore.FileStore {
|
|
var fs filestore.FileStore
|
|
if dir == "" {
|
|
fs = filestore.NewFileMemoryStore()
|
|
} else {
|
|
os.MkdirAll(dir, 0755)
|
|
fs = filestore.NewFileLocalStore(dir)
|
|
}
|
|
return fs
|
|
}
|
|
|
|
// Init initialize the sandbox environment
|
|
//export Init
|
|
func Init(i *C.char) C.int {
|
|
is := C.GoString(i)
|
|
var ip initParameter
|
|
if err := json.NewDecoder(bytes.NewBufferString(is)).Decode(&ip); err != nil {
|
|
return -1
|
|
}
|
|
|
|
if ip.Parallelism == 0 {
|
|
ip.Parallelism = 4
|
|
}
|
|
|
|
if ip.TmpFsParam == "" {
|
|
ip.TmpFsParam = "size=16m,nr_inodes=4k"
|
|
}
|
|
|
|
if ip.MountConf == "" {
|
|
ip.MountConf = "mount.yaml"
|
|
}
|
|
|
|
srcPrefix = ip.SrcPrefix
|
|
|
|
fs = newFilsStore(ip.Dir)
|
|
|
|
b, err := env.NewBuilder(env.Config{
|
|
ContainerInitPath: ip.CInitPath,
|
|
MountConf: ip.MountConf,
|
|
TmpFsParam: ip.TmpFsParam,
|
|
NetShare: ip.NetShare,
|
|
CgroupPrefix: ip.CgroupPrefix,
|
|
Cpuset: ip.CPUSet,
|
|
ContainerCredStart: ip.CredStart,
|
|
Logger: nopLogger{},
|
|
})
|
|
if err != nil {
|
|
log.Fatalln("create environment builder failed", err)
|
|
}
|
|
envPool := pool.NewPool(b)
|
|
work = worker.New(worker.Config{
|
|
FileStore: fs,
|
|
EnvironmentPool: envPool,
|
|
Parallelism: ip.Parallelism,
|
|
WorkDir: ip.Dir,
|
|
TimeLimitTickInterval: 100 * time.Millisecond,
|
|
})
|
|
work.Start()
|
|
|
|
return 0
|
|
}
|
|
|
|
// Exec runs command inside container runner
|
|
//export Exec
|
|
func Exec(e *C.char) *C.char {
|
|
es := C.GoString(e)
|
|
var req model.Request
|
|
if err := json.NewDecoder(bytes.NewBufferString(es)).Decode(&req); err != nil {
|
|
return nil
|
|
}
|
|
r, err := model.ConvertRequest(&req, srcPrefix)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
rt := <-work.Submit(context.TODO(), r)
|
|
ret := model.ConvertResponse(rt)
|
|
var buf bytes.Buffer
|
|
if err := json.NewEncoder(&buf).Encode(ret); err != nil {
|
|
return nil
|
|
}
|
|
return C.CString(buf.String())
|
|
}
|
|
|
|
// FileList get the list of files in the file store
|
|
//export FileList
|
|
func FileList() *C.char {
|
|
ids := fs.List()
|
|
|
|
var buf bytes.Buffer
|
|
if err := json.NewEncoder(&buf).Encode(ids); err != nil {
|
|
return nil
|
|
}
|
|
return C.CString(buf.String())
|
|
}
|
|
|
|
// FileAdd adds file to the file store
|
|
//export FileAdd
|
|
func FileAdd(e *C.char) *C.char {
|
|
type fileAdd struct {
|
|
Name string `json:"name"`
|
|
Content string `json:"content"`
|
|
}
|
|
es := C.GoString(e)
|
|
|
|
var f fileAdd
|
|
if err := json.NewDecoder(bytes.NewBufferString(es)).Decode(&f); err != nil {
|
|
return nil
|
|
}
|
|
|
|
id, err := fs.Add(f.Name, []byte(f.Content))
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
return C.CString(id)
|
|
}
|
|
|
|
// FileGet gets file from file store by id
|
|
//export FileGet
|
|
func FileGet(e *C.char) *C.char {
|
|
type fileGet struct {
|
|
ID string `json:"id"`
|
|
}
|
|
es := C.GoString(e)
|
|
|
|
var f fileGet
|
|
if err := json.NewDecoder(bytes.NewBufferString(es)).Decode(&f); err != nil {
|
|
return nil
|
|
}
|
|
file := fs.Get(f.ID)
|
|
if file == nil {
|
|
return nil
|
|
}
|
|
c, err := file.Content()
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
return C.CString(string(c))
|
|
}
|
|
|
|
// FileDelete deletes file from file store by id
|
|
//export FileDelete
|
|
func FileDelete(e *C.char) *C.char {
|
|
type fileDelete struct {
|
|
ID string `json:"id"`
|
|
}
|
|
es := C.GoString(e)
|
|
|
|
var f fileDelete
|
|
if err := json.NewDecoder(bytes.NewBufferString(es)).Decode(&f); err != nil {
|
|
return nil
|
|
}
|
|
ok := fs.Remove(f.ID)
|
|
if !ok {
|
|
return nil
|
|
}
|
|
return C.CString("")
|
|
}
|
|
|
|
type nopLogger struct {
|
|
}
|
|
|
|
func (nopLogger) Debug(args ...interface{}) {
|
|
}
|
|
|
|
func (nopLogger) Info(args ...interface{}) {
|
|
}
|
|
|
|
func (nopLogger) Warn(args ...interface{}) {
|
|
}
|
|
|
|
func (nopLogger) Error(args ...interface{}) {
|
|
}
|