common

package
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 26, 2017 License: BSD-3-Clause Imports: 26 Imported by: 0

Documentation

Index

Constants

View Source
const (
	EventBegin     = "B"
	EventClockSync = "c"
	EventEnd       = "E"
	EventComplete  = "X"
	EventInstant   = "i"
	EventMetadata  = "M"
)

Variables

View Source
var (
	DefaultLiteralLimitSettings = LimitsSettings{
		TimeLimit:            1000,
		MemoryLimit:          67108864,
		OverallWallTimeLimit: 5000,
		ExtraWallTime:        0,
		OutputLimit:          10240,
		ValidatorTimeLimit:   1000,
	}

	DefaultLiteralValidatorSettings = LiteralValidatorSettings{
		Name: "token-caseless",
	}

	DefaultValidatorTolerance = 1e-6
)

Default values for some of the settings.

Functions

func AcceptsMimeType

func AcceptsMimeType(r *http.Request, mimeType string) bool

func NewAttemptID

func NewAttemptID() uint64

NewAttemptID allocates a locally-unique AttemptID. A counter is initialized to a random 63-bit integer on startup and then atomically incremented eacn time a new ID is needed.

func NewSyncID

func NewSyncID() uint64

NewSyncID allocates a locally-unique SyncID. A counter is initialized to a random 63-bit integer on startup and then atomically incremented each time a new ID is needed.

func RunServer

func RunServer(
	tlsConfig *TLSConfig,
	handler http.Handler,
	addr string,
	insecure bool,
)

func Sha1sum

func Sha1sum(filename string) ([]byte, error)

Sha1sum is an utility function that obtains the SHA1 hash of a file (as referenced to by the filename parameter).

Types

type Arg

type Arg struct {
	Name  string
	Value interface{}
}

type BaseInput

type BaseInput struct {
	sync.Mutex
	// contains filtered or unexported fields
}

BaseInput is an abstract struct that provides most of the functions required to implement Input.

func NewBaseInput

func NewBaseInput(hash string, mgr *InputManager) *BaseInput

func (*BaseInput) Acquire

func (input *BaseInput) Acquire()

func (*BaseInput) Commit

func (input *BaseInput) Commit(size int64)

func (*BaseInput) Committed

func (input *BaseInput) Committed() bool

func (*BaseInput) Delete

func (input *BaseInput) Delete() error

func (*BaseInput) Hash

func (input *BaseInput) Hash() string

func (*BaseInput) Path

func (input *BaseInput) Path() string

func (*BaseInput) Persist

func (input *BaseInput) Persist() error

func (*BaseInput) Release

func (input *BaseInput) Release(outerInput Input)

func (*BaseInput) Reserve

func (input *BaseInput) Reserve(size int64)

func (*BaseInput) Settings

func (input *BaseInput) Settings() *ProblemSettings

func (*BaseInput) Size

func (input *BaseInput) Size() int64

func (*BaseInput) Transmit

func (input *BaseInput) Transmit(w http.ResponseWriter) error

func (*BaseInput) Verify

func (input *BaseInput) Verify() error

type BroadcasterConfig

type BroadcasterConfig struct {
	ChannelLength           int
	EventsPort              uint16
	FrontendURL             string
	PingPeriod              int64
	Port                    uint16
	Proxied                 bool
	ScoreboardUpdateSecret  string
	ScoreboardUpdateTimeout int64     // seconds
	TLS                     TLSConfig // only used if Proxied == false
	WriteDeadline           time.Duration
}

Configuration

type ByCaseName

type ByCaseName []CaseSettings

func (ByCaseName) Len

func (c ByCaseName) Len() int

func (ByCaseName) Less

func (c ByCaseName) Less(i, j int) bool

func (ByCaseName) Swap

func (c ByCaseName) Swap(i, j int)

type ByGroupName

type ByGroupName []GroupSettings

func (ByGroupName) Len

func (g ByGroupName) Len() int

func (ByGroupName) Less

func (g ByGroupName) Less(i, j int) bool

func (ByGroupName) Swap

func (g ByGroupName) Swap(i, j int)

type CachedInputFactory

type CachedInputFactory interface {
	InputFactory

	// GetInputHash returns both the hash of the input for the specified
	// os.FileInfo. It returns ok = false in case the os.FileInfo does not refer
	// to an Input.
	GetInputHash(dirname string, info os.FileInfo) (hash string, ok bool)
}

CachedInputFactory is an InputFactory that also can validate Inputs that are already in the filesystem.

type CaseSettings

type CaseSettings struct {
	Name   string
	Weight float64
}

CaseSettings contains the information of a single test case.

type CompleteEvent

type CompleteEvent struct {
	NormalEvent
	Duration int64 `json:"dur"`
}

func (*CompleteEvent) Finalize

func (e *CompleteEvent) Finalize()

type Config

type Config struct {
	Broadcaster  BroadcasterConfig
	InputManager InputManagerConfig
	Grader       GraderConfig
	Db           DbConfig
	Logging      LoggingConfig
	Metrics      MetricsConfig
	Tracing      TracingConfig
	Runner       RunnerConfig
	TLS          TLSConfig
}

func DefaultConfig

func DefaultConfig() Config

func NewConfig

func NewConfig(reader io.Reader) (*Config, error)

NewConfig creates a new Config from the specified reader.

func (*Config) String

func (config *Config) String() string

type Context

type Context struct {
	Config         Config
	Log            log15.Logger
	EventCollector EventCollector
	EventFactory   *EventFactory
	// contains filtered or unexported fields
}

Context

func NewContext

func NewContext(config *Config) (*Context, error)

NewContext creates a new Context from the specified Config. This also creates a Logger.

func NewContextFromReader

func NewContextFromReader(reader io.Reader) (*Context, error)

NewContextFromReader creates a new Context from the specified reader. This also creates a Logger.

func (*Context) AppendLogSection

func (context *Context) AppendLogSection(sectionName string, contents []byte)

func (*Context) Close

func (context *Context) Close()

Close releases all resources owned by the context.

func (*Context) DebugContext

func (context *Context) DebugContext(logCtx ...interface{}) *Context

DebugContext returns a new Context with an additional handler with a more verbose filter (using the Debug level) and a Buffer in which all logging statements will be (also) written to.

func (*Context) LogBuffer

func (context *Context) LogBuffer() []byte

func (*Context) TraceBuffer

func (context *Context) TraceBuffer() []byte

type DbConfig

type DbConfig struct {
	Driver         string
	DataSourceName string
}

type Event

type Event interface {
	Finalize()
}

type EventCollector

type EventCollector interface {
	Add(Event) error
}

type EventFactory

type EventFactory struct {
	// contains filtered or unexported fields
}

func NewEventFactory

func NewEventFactory(processName, threadName string) *EventFactory

func (*EventFactory) NewCompleteEvent

func (factory *EventFactory) NewCompleteEvent(
	name string,
	args ...Arg,
) *CompleteEvent

func (*EventFactory) NewEvent

func (factory *EventFactory) NewEvent(
	name string,
	eventType string,
	args ...Arg,
) *NormalEvent

func (*EventFactory) NewIssuerClockSyncEvent

func (factory *EventFactory) NewIssuerClockSyncEvent() *IssuerClockSyncEvent

func (*EventFactory) NewReceiverClockSyncEvent

func (factory *EventFactory) NewReceiverClockSyncEvent(syncID uint64) *NormalEvent

func (*EventFactory) Register

func (factory *EventFactory) Register(collector EventCollector) error

type FairMutex

type FairMutex struct {
	// contains filtered or unexported fields
}

fairMutex is similar to a sync.Mutex but has an outer mutex protecting the real (inner) one. This attempts to reduce the unfairness by allowing other threads to "barge in" and block the next acquisition of the mutex until they have had their chance. See https://github.com/golang/go/issues/13086 for details.

func (*FairMutex) Lock

func (m *FairMutex) Lock()

func (*FairMutex) Unlock

func (m *FairMutex) Unlock()

type GraderConfig

type GraderConfig struct {
	ChannelLength   int
	Port            uint16
	RuntimePath     string
	MaxGradeRetries int
	BroadcasterURL  string
	V1              V1Config
	WriteGradeFiles bool // TODO(lhchavez): Remove once migration is done.
}

type GroupSettings

type GroupSettings struct {
	Cases  []CaseSettings
	Name   string
	Weight float64
}

GroupSettings contains the information of the test case groups.

type HashReader

type HashReader struct {
	// contains filtered or unexported fields
}

HashReader is a Reader that provides a Sum function. After having completely read the Reader, the Sum function will provide the hash of the complete stream.

func NewHashReader

func NewHashReader(r io.Reader, h hash.Hash) *HashReader

NewHashReader returns a new HashReader for a given Reader and Hash.

func (*HashReader) Length

func (r *HashReader) Length() int64

Length returns the number of bytes involved in the hash computation so far.

func (*HashReader) Read

func (r *HashReader) Read(b []byte) (int, error)

Read calls the underlying Reader's Read function and updates the Hash with the read bytes.

func (*HashReader) Sum

func (r *HashReader) Sum(b []byte) []byte

Sum returns the hash of the Reader. Typically invoked after Read reaches EOF. Will consume any non-consumed data.

type IdentityInputFactory

type IdentityInputFactory struct {
	// contains filtered or unexported fields
}

IdentityInputFactory is an InputFactory that only constructs one Input.

func NewIdentityInputFactory

func NewIdentityInputFactory(input Input) *IdentityInputFactory

NewIdentityInputFactory returns an IdentityInputFactory associated with the provided Input.

func (*IdentityInputFactory) NewInput

func (factory *IdentityInputFactory) NewInput(hash string, mgr *InputManager) Input

NewInput returns the Input provided in the constructor. Panics if the requested hash does not match the one of the Input.

type Input

type Input interface {
	Lockable
	RefCounted

	// Path returns the path to the uncompressed representation of the Input
	// on-disk.
	Path() string

	// Hash is the identifier of the Input. It is typically the Git hash of the
	// tree that it represents.
	Hash() string

	// Commited returns true if the input has been verified and is committed into
	// its InputManager.
	Committed() bool

	// Size returns the number of bytes of the Input's on-disk representation.
	Size() int64

	// Verify ensures that the version of the Input stored in the filesystem
	// exists and is consistent, and commits it so that it can be added to the
	// InputManager. It is expected that Size() returns a valid size after
	// Verify() returns successfully.
	Verify() error

	// Persist stores the Input into the filesystem in a form that is
	// easily consumed and can be verified for consistency after restarting.
	Persist() error

	// Delete removes the filesystem version of the Input to free space.
	Delete() error

	// Settings returns the problem's settings for the Input. Problems can have
	// different ProblemSettings on different Inputs.
	Settings() *ProblemSettings

	// Transmit sends a serialized version of the Input over HTTP. It should be a
	// .tar.gz file with the Content-SHA1 header set to the hexadecimal
	// representation of the SHA-1 hash of the file.
	Transmit(http.ResponseWriter) error
}

Input represents a problem's input set.

Input is reference-counted, so it will keep the input in memory (and disk) while there is at least one reference to it. Once the last reference is released, it will be inserted into its associated InputManager.

type InputFactory

type InputFactory interface {
	NewInput(hash string, mgr *InputManager) Input
}

InputFactory creates Input objects for an InputManager based on a hash. The hash is just an opaque identifier that just so happens to be the SHA1 hash of the git tree representation of the Input.

InputFactory is provided so that the Grader and the Runner can have different implementations of how to create, read, and write an Input in disk.

type InputManager

type InputManager struct {
	sync.Mutex
	// contains filtered or unexported fields
}

InputManager handles a pool of recently-used input sets. The pool has a fixed maximum size with a least-recently used eviction policy.

func NewInputManager

func NewInputManager(ctx *Context) *InputManager

NewInputManager creates a new InputManager with the provided Context.

func (*InputManager) Add

func (mgr *InputManager) Add(hash string, factory InputFactory) (Input, error)

Add associates an opaque identifier (the hash) with an Input in the InputManager.

The InputFactory is responsible to create the Input if it has not yet been created. The Input will be validated if it has not been committed to the InputManager, but will still not be accounted into the size limit since there is at least one live reference to it.

func (*InputManager) Get

func (mgr *InputManager) Get(hash string) (Input, error)

Get returns the Input for a specified hash, if it is already present in the pool. If it is present, it will increment its reference-count and transfer the ownership of the reference to the caller. It is the caller's responsibility to release the ownership of the Input.

func (*InputManager) Insert

func (mgr *InputManager) Insert(input Input)

Insert adds an already-created Input to the pool, possibly evicting old entries to free enough space such that the total size of Inputs in the pool is still within the limit. This should only be called when there are no references to the Input.

func (*InputManager) MarshalJSON

func (mgr *InputManager) MarshalJSON() ([]byte, error)

func (*InputManager) PreloadInputs

func (mgr *InputManager) PreloadInputs(
	rootdir string,
	factory CachedInputFactory,
	ioLock sync.Locker,
) error

PreloadInputs reads all files in path, runs them through the specified filter, and tries to add them into the InputManager. PreloadInputs acquires the ioLock just before doing I/O in order to guarantee that the system will not be doing expensive I/O operations in the middle of a performance-sensitive operation (like running contestants' code).

func (*InputManager) Reserve

func (mgr *InputManager) Reserve(size int64)

Reserve evicts Inputs from the pool to make the specified size available.

func (*InputManager) Size

func (mgr *InputManager) Size() int64

Size returns the total size (in bytes) of cached Inputs in the InputManager. This does not count any Inputs with live references.

type InputManagerConfig

type InputManagerConfig struct {
	CacheSize int64
}

type InteractiveInterface

type InteractiveInterface struct {
	MakefileRules []struct {
		Targets    []string
		Requisites []string
		Compiler   string
		Params     string
		Debug      bool
	}
	ExecutableDescription struct {
		Args []string
		Env  map[string]string
	}
	Files map[string]string
}

type InteractiveSettings

type InteractiveSettings struct {
	Interfaces            map[string]map[string]*InteractiveInterface
	Main                  string
	ModuleName            string
	ParentLang            string
	LibinteractiveVersion string
}

InteractiveSettings contains the information needed by libinteractive to generate interactive shims.

type IssuerClockSyncEvent

type IssuerClockSyncEvent struct {
	NormalEvent
	SyncID uint64 `json:"-"`
}

func (*IssuerClockSyncEvent) Finalize

func (e *IssuerClockSyncEvent) Finalize()

type LimitsSettings

type LimitsSettings struct {
	ExtraWallTime        int64
	MemoryLimit          int64
	OutputLimit          int64
	OverallWallTimeLimit int64
	TimeLimit            int64
	ValidatorTimeLimit   int64
}

LimitsSettings represents runtime limits for the Input.

type LiteralCaseSettings

type LiteralCaseSettings struct {
	Input          string   `json:"in"`
	ExpectedOutput string   `json:"out"`
	Weight         *float64 `json:"weight,omitempty"`
}

LiteralCaseSettings stores the input, expected output, and the weight of a particular test case.

type LiteralCustomValidatorSettings

type LiteralCustomValidatorSettings struct {
	Source   string `json:"source"`
	Language string `json:"language"`
}

LiteralCustomValidatorSettings stores the source of the program that will validate the contestant's outputs.

type LiteralInput

type LiteralInput struct {
	Cases       map[string]LiteralCaseSettings `json:"cases"`
	Limits      *LimitsSettings                `json:"limits,omitempty"`
	Validator   *LiteralValidatorSettings      `json:"validator,omitempty"`
	Interactive *LiteralInteractiveSettings    `json:"interactive,omitempty"`
}

LiteralInput is a standalone representation of an Input (although it cannot be used directly as an Input). It is useful for testing and to evaluate a run that doesn't have a problem associated with it.

type LiteralInputFactory

type LiteralInputFactory struct {
	// contains filtered or unexported fields
}

LiteralInputFactory is an InputFactory that will return an Input version of the specified LiteralInput when asked for an input.

func NewLiteralInputFactory

func NewLiteralInputFactory(
	input *LiteralInput,
	runtimePath string,
) (*LiteralInputFactory, error)

NewLiteralInputFactory validates the LiteralInput and stores it so it can be returned when NewInput is called.

func (*LiteralInputFactory) Hash

func (factory *LiteralInputFactory) Hash() string

func (*LiteralInputFactory) NewInput

func (factory *LiteralInputFactory) NewInput(hash string, mgr *InputManager) Input

NewInput returns the LiteralInput that was specified as the LiteralInputFactory's Input in its constructor.

type LiteralInteractiveSettings

type LiteralInteractiveSettings struct {
	IDLSource  string `json:"idl"`
	ModuleName string `json:"module_name"`
	ParentLang string `json:"language"`
	MainSource string `json:"main_source"`
}

LiteralInteractiveSettings stores the settings for a problem that uses libinteractive.

type LiteralRun

type LiteralRun struct {
	Source   string `json:"source"`
	Language string `json:"language"`
	Input    string `json:"input"`
}

LiteralRun is a standalone representation of a Run. It is useful for testing and to evaluate a run that doesn't have a problem associated with it.

type LiteralValidatorSettings

type LiteralValidatorSettings struct {
	Name            string                          `json:"name"`
	Tolerance       *float64                        `json:"tolerance,omitempty"`
	CustomValidator *LiteralCustomValidatorSettings `json:"custom_validator,omitempty"`
}

LiteralValidatorSettings stores the settings for the validator, that will calculate a per-case grade. Valid values for Name are "custom", "literal", "token", "token-caseless", "token-numeric". If "custom" is chosen, a valid CustomValidator must be provided. If "token-numeric" is chosen, Tolerance must contain a numeric tolerance (typically a small number).

type Lockable

type Lockable interface {
	Lock()
	Unlock()
}

Lockable is the interface that sync.Mutex implements.

type LoggingConfig

type LoggingConfig struct {
	File  string
	Level string
}

type MemoryEventCollector

type MemoryEventCollector struct {
	Events []Event
	// contains filtered or unexported fields
}

func NewMemoryEventCollector

func NewMemoryEventCollector() *MemoryEventCollector

func (*MemoryEventCollector) Add

func (collector *MemoryEventCollector) Add(e Event) error

func (*MemoryEventCollector) MarshalJSON

func (collector *MemoryEventCollector) MarshalJSON() ([]byte, error)

func (*MemoryEventCollector) UnmarshalJSON

func (collector *MemoryEventCollector) UnmarshalJSON(buf []byte) error

type MetricsConfig

type MetricsConfig struct {
	Port uint16
}

type MultiEventCollector

type MultiEventCollector struct {
	// contains filtered or unexported fields
}

func NewMultiEventCollector

func NewMultiEventCollector(collectors ...EventCollector) *MultiEventCollector

func (*MultiEventCollector) Add

func (collector *MultiEventCollector) Add(e Event) error

type NormalEvent

type NormalEvent struct {
	Name      string                 `json:"name"`
	Type      string                 `json:"ph"`
	Timestamp int64                  `json:"ts"`
	PID       int                    `json:"pid"`
	TID       int                    `json:"tid"`
	Args      map[string]interface{} `json:"args,omitempty"`
	// contains filtered or unexported fields
}

func (*NormalEvent) Finalize

func (e *NormalEvent) Finalize()

type NullEventCollector

type NullEventCollector struct {
}

func (*NullEventCollector) Add

func (collector *NullEventCollector) Add(e Event) error

type ProblemSettings

type ProblemSettings struct {
	Cases       []GroupSettings      `json:"Cases"`
	Interactive *InteractiveSettings `json:"Interactive,omitempty"`
	Limits      LimitsSettings       `json:"Limits"`
	Slow        bool                 `json:"Slow"`
	Validator   ValidatorSettings    `json:"Validator"`
}

ProblemSettings represents the settings of a problem for a particular Input set.

type RefCounted

type RefCounted interface {
	Acquire()

	// Unfortunately, Go always invokes the methods of an embedded type with the
	// embedded type as the receiver (rather than the outer type), effectively
	// upcasting the pointer and losing the actual type. In order to avoid that,
	// we need to pass the Input again as a parameter.
	Release(Input)
}

RefCounted is the interface that provides reference-counted semantics.

Once the final reference has been released, the object is expected to release all resources.

type Run

type Run struct {
	AttemptID uint64  `json:"attempt_id"`
	Source    string  `json:"source"`
	Language  string  `json:"language"`
	InputHash string  `json:"input_hash"`
	MaxScore  float64 `json:"max_score"`
	Debug     bool    `json:"debug"`
}

An omegaUp run.

func (*Run) String

func (run *Run) String() string

func (*Run) UpdateAttemptID

func (run *Run) UpdateAttemptID() uint64

UpdateID assigns a new AttemptID to a run.

type RunnerConfig

type RunnerConfig struct {
	GraderURL           string
	RuntimePath         string
	CompileTimeLimit    int
	CompileOutputLimit  int
	JavaVmEstimatedSize int64
	PreserveFiles       bool
}

type TLSConfig

type TLSConfig struct {
	CertFile string
	KeyFile  string
}

type TracingConfig

type TracingConfig struct {
	Enabled bool
	File    string
}

type V1Config

type V1Config struct {
	Enabled          bool
	Port             uint16
	RuntimeGradePath string
	RuntimePath      string
	SendBroadcast    bool
	UpdateDatabase   bool
	WriteResults     bool
}

type ValidatorSettings

type ValidatorSettings struct {
	Lang      *string  `json:"Lang,omitempty"`
	Name      string   `json:"Name"`
	Tolerance *float64 `json:"Tolerance,omitempty"`
}

ValidatorSettings represents the options used to validate outputs.

type WriterEventCollector

type WriterEventCollector struct {
	// contains filtered or unexported fields
}

func NewWriterEventCollector

func NewWriterEventCollector(
	output io.Writer,
	appending bool,
) (*WriterEventCollector, error)

func (*WriterEventCollector) Add

func (collector *WriterEventCollector) Add(e Event) error

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL