Spracherkennung für: .go vermutete Sprache: Abap {ABAP[58] C[51] Corba[51]} [Methode: maximale Elemente, drei Dimensionen]
// Copyright
2018 Google Inc. All rights reserved.
//
// Licensed
under the Apache License, Version
2.
0 (the
"License");
// you may not use this
file except
in compliance with the License.
// You may obtain a
copy of the License
at
//
//
http://www.apache.org/licenses/LICENSE-2.
0
//
// Unless required
by applicable law
or agreed
to in writing, software
// distributed
under the License
is distributed
on an
"AS IS" BASIS,
// WITHOUT WARRANTIES
OR CONDITIONS
OF ANY KIND, either express
or implied.
// See the License
for the specific
language governing permissions
and
// limitations
under the License.
// Package status tracks actions
run by various tools, combining the counts
// (total actions, currently running, started, finished),
and giving that
to
// multiple outputs.
package status
import (
"sync"
"time"
)
// Action describes an action taken (
or as Ninja calls them, Edges).
type Action struct {
// Description
is a shorter, more readable
form of the command, meant
//
for users. It
's optional, but one of either Description or Command
// should be
set.
Description
string
// Outputs
is the (optional) list
of outputs. Usually these are files,
// but they can be
any string.
Outputs []
string
// Inputs
is the (optional) list
of inputs. Usually these are files,
// but they can be
any string.
Inputs []
string
// Command
is the actual command
line executed
to perform the action.
// It
's optional, but one of either Description or Command should be
//
set.
Command
string
// ChangedInputs
is the (optional) list
of inputs that have changed
// since last
time this action was
run.
ChangedInputs []
string
}
// ActionResult describes the result
of running an Action.
type ActionResult struct {
// Action
is a pointer
to the original Action struct.
*Action
// Output
is the output produced
by the command (usually stdout&stderr
//
for Actions that
run commands)
Output
string
// Error
is nil
if the Action succeeded,
or set to an error
if it
// failed.
Error error
Stats ActionResultStats
}
type ActionResultStats struct {
// Number
of milliseconds spent executing
in user mode
UserTime uint32
// Number
of milliseconds spent executing
in kernel mode
SystemTime uint32
//
Max resident
set size in kB
MaxRssKB uint64
// Minor
page faults
MinorPageFaults uint64
// Major
page faults
MajorPageFaults uint64
// IO
input in kB
IOInputKB uint64
// IO output
in kB
IOOutputKB uint64
// Voluntary context switches
VoluntaryContextSwitches uint64
// Involuntary context switches
InvoluntaryContextSwitches uint64
Tags
string
}
// Counts describes the number
of actions
in each state
type Counts struct {
// TotalActions
is the total number
of expected changes. This can
// generally
change up
or down during a build, but it should never go
// below the number
of StartedActions
TotalActions int
// RunningActions are the number
of actions that are currently running
// -- the number that have called StartAction, but not FinishAction.
RunningActions int
// StartedActions are the number
of actions that have been started with
// StartAction.
StartedActions int
// FinishedActions are the number
of actions that have been finished
// with FinishAction.
FinishedActions int
EstimatedTime
time.
Time
}
// ToolStatus
is the
interface used
by tools
to report on their Actions,
and to
// present other information through a
set of messaging functions.
type ToolStatus
interface {
// SetTotalActions sets the expected total number
of actions that will
// be started
by this tool.
//
// This
call be will ignored
if it sets a number that
is less than the
// current number
of started actions.
SetTotalActions(total int)
SetEstimatedTime(estimatedTime
time.
Time)
// StartAction specifies that the associated action has been started
by
// the tool.
//
// A specific
*Action should not be specified to StartAction more than
// once, even
if the previous action has already been finished,
and the
// contents rewritten.
//
//
Do not re-use
*Actions between different ToolStatus interfaces
// either.
StartAction(action
*Action)
// FinishAction specifies the result
of a particular Action.
//
// The
*Action embedded in the ActionResult structure must have already
// been passed
to StartAction (
on this
interface).
//
//
Do not
call FinishAction twice
for the same
*Action.
FinishAction(result ActionResult)
// Verbose takes a non-important
message that
is never printed
to the
//
screen, but
is in the verbose build
log, etc
Verbose(msg
string)
// Status takes a less important
message that may be printed
to the
//
screen, but overwritten
by another status
message. The full
message
// will still appear
in the verbose build
log.
Status(msg
string)
//
Print takes an
message and displays it
to the
screen and other
// output logs, etc.
Print(msg
string)
// Error
is similar
to Print, but treats it similarly
to a failed
// action, showing it
in the error logs, etc.
Error(msg
string)
// Finish marks the end
of all Actions being
run by this tool.
//
// SetTotalEdges, StartAction,
and FinishAction should not be called
// after Finish.
Finish()
}
// MsgLevel specifies the importance
of a particular
log message. See the
// descriptions
in ToolStatus: Verbose, Status,
Print, Error.
type MsgLevel int
const (
VerboseLvl MsgLevel = iota
StatusLvl
PrintLvl
ErrorLvl
)
func (l MsgLevel) Prefix()
string {
switch l {
case VerboseLvl:
return
"verbose: "
case StatusLvl:
return
"status: "
case PrintLvl:
return
""
case ErrorLvl:
return
"error: "
default:
panic(
"Unknown message level")
}
}
// StatusOutput
is the
interface used
to get status information
as a Status
// output.
//
// All
of the functions here are guaranteed
to be called
by Status
while
// holding it
's internal lock, so it's safe
to assume a
single caller
at any
//
time,
and that the ordering
of calls will be correct. It
is not safe
to call
//
back into the Status,
or one
of its ToolStatus
interfaces.
type StatusOutput
interface {
// StartAction will be called once every
time ToolStatus.StartAction
is
// called. counts will
include the current counters across all
// ToolStatus instances, including ones that have been finished.
StartAction(action
*Action, counts Counts)
// FinishAction will be called once every
time ToolStatus.FinishAction
//
is called. counts will
include the current counters across all
// ToolStatus instances, including ones that have been finished.
FinishAction(result ActionResult, counts Counts)
//
Message is the equivalent
of ToolStatus.Verbose/Status/
Print/Error,
// but the level
is specified as an argument.
Message(level MsgLevel, msg
string)
// Flush
is called
when your outputs should be flushed / closed. No
// output
is expected after this
call.
Flush()
//
Write lets StatusOutput implement io.Writer
Write(p []byte) (n int, err error)
}
// Status
is the multiplexer / accumulator
between ToolStatus instances (via
// StartTool)
and StatusOutputs (via AddOutput). There
's generally one of these
// per build process (though tools
like multiproduct_kati may have multiple
// independent versions).
type Status struct {
counts Counts
outputs []StatusOutput
// Protects counts
and outputs,
and allows each output
to
// expect only a
single caller
at a
time.
lock sync.Mutex
}
// AddOutput attaches an output
to this
object. It
's generally expected that an
// output
is attached
to a
single Status instance.
func (s
*Status) AddOutput(output StatusOutput) {
if output == nil {
return
}
s.lock.Lock()
defer s.lock.Unlock()
s.outputs =
append(s.outputs, output)
}
// StartTool returns a new ToolStatus instance
to report the status
of a tool.
func (s
*Status) StartTool() ToolStatus {
return &toolStatus{
status: s,
}
}
// Finish will
call Flush
on all the outputs, generally flushing
or closing all
//
of their outputs.
Do not
call any other functions
on this instance
or any
// associated ToolStatus instances after this has been called.
func (s
*Status) Finish() {
s.lock.Lock()
defer s.lock.Unlock()
for _, o := range s.outputs {
o.Flush()
}
}
func (s
*Status) updateTotalActions(diff int) {
s.lock.Lock()
defer s.lock.Unlock()
s.counts.TotalActions += diff
}
func (s
*Status) SetEstimatedTime(estimatedTime time.Time) {
s.lock.Lock()
defer s.lock.Unlock()
s.counts.EstimatedTime = estimatedTime
}
func (s
*Status) startAction(action *Action) {
s.lock.Lock()
defer s.lock.Unlock()
s.counts.RunningActions +=
1
s.counts.StartedActions +=
1
for _, o := range s.outputs {
o.StartAction(action, s.counts)
}
}
func (s
*Status) finishAction(result ActionResult) {
s.lock.Lock()
defer s.lock.Unlock()
s.counts.RunningActions -=
1
s.counts.FinishedActions +=
1
for _, o := range s.outputs {
o.FinishAction(result, s.counts)
}
}
func (s
*Status) message(level MsgLevel, msg string) {
s.lock.Lock()
defer s.lock.Unlock()
for _, o := range s.outputs {
o.
Message(level, msg)
}
}
func (s
*Status) Status(msg string) {
s.
message(StatusLvl, msg)
}
func (s
*Status) Error(msg string) {
s.
message(ErrorLvl, msg)
}
type toolStatus struct {
status
*Status
counts Counts
// Protects counts
lock sync.Mutex
}
var _ ToolStatus = (
*toolStatus)(nil)
func (d
*toolStatus) SetTotalActions(total int) {
diff :=
0
d.lock.Lock()
if total >= d.counts.StartedActions && total != d.counts.TotalActions {
diff = total - d.counts.TotalActions
d.counts.TotalActions = total
}
d.lock.Unlock()
if diff !=
0 {
d.status.updateTotalActions(diff)
}
}
func (d
*toolStatus) SetEstimatedTime(estimatedTime time.Time) {
d.status.SetEstimatedTime(estimatedTime)
}
func (d
*toolStatus) StartAction(action *Action) {
totalDiff :=
0
d.lock.Lock()
d.counts.RunningActions +=
1
d.counts.StartedActions +=
1
if d.counts.StartedActions > d.counts.TotalActions {
totalDiff = d.counts.StartedActions - d.counts.TotalActions
d.counts.TotalActions = d.counts.StartedActions
}
d.lock.Unlock()
if totalDiff !=
0 {
d.status.updateTotalActions(totalDiff)
}
d.status.startAction(action)
}
func (d
*toolStatus) FinishAction(result ActionResult) {
d.lock.Lock()
d.counts.RunningActions -=
1
d.counts.FinishedActions +=
1
d.lock.Unlock()
d.status.finishAction(result)
}
func (d
*toolStatus) Verbose(msg string) {
d.status.
message(VerboseLvl, msg)
}
func (d
*toolStatus) Status(msg string) {
d.status.
message(StatusLvl, msg)
}
func (d
*toolStatus) Print(msg string) {
d.status.
message(PrintLvl, msg)
}
func (d
*toolStatus) Error(msg string) {
d.status.
message(ErrorLvl, msg)
}
func (d
*toolStatus) Finish() {
d.lock.Lock()
defer d.lock.Unlock()
if d.counts.TotalActions != d.counts.StartedActions {
d.status.updateTotalActions(d.counts.StartedActions - d.counts.TotalActions)
}
// TODO:
update status
to correct running/finished edges?
d.counts.RunningActions =
0
d.counts.TotalActions = d.counts.StartedActions
}