Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/build/build/soong/ui/status/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 10 kB image not shown  

Quelle  status.go   Sprache: unbekannt

 
Spracherkennung für: .go vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs 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
}

[Dauer der Verarbeitung: 0.28 Sekunden, vorverarbeitet 2026-06-28]