1// Copyright 2018 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package tracer
16
17import (
18	"android/soong/ui/status"
19	"time"
20)
21
22func (t *tracerImpl) StatusTracer() status.StatusOutput {
23	return &statusOutput{
24		tracer: t,
25
26		running: map[*status.Action]actionStatus{},
27	}
28}
29
30type actionStatus struct {
31	cpu   int
32	start time.Time
33}
34
35type statusOutput struct {
36	tracer *tracerImpl
37
38	cpus    []bool
39	running map[*status.Action]actionStatus
40}
41
42func (s *statusOutput) StartAction(action *status.Action, counts status.Counts) {
43	cpu := -1
44	for i, busy := range s.cpus {
45		if !busy {
46			cpu = i
47			s.cpus[i] = true
48			break
49		}
50	}
51
52	if cpu == -1 {
53		cpu = len(s.cpus)
54		s.cpus = append(s.cpus, true)
55	}
56
57	s.running[action] = actionStatus{
58		cpu:   cpu,
59		start: time.Now(),
60	}
61}
62
63func (s *statusOutput) FinishAction(result status.ActionResult, counts status.Counts) {
64	start, ok := s.running[result.Action]
65	if !ok {
66		return
67	}
68	delete(s.running, result.Action)
69	s.cpus[start.cpu] = false
70
71	str := result.Action.Description
72	if len(result.Action.Outputs) > 0 {
73		str = result.Action.Outputs[0]
74	}
75
76	s.tracer.writeEvent(&viewerEvent{
77		Name:  str,
78		Phase: "X",
79		Time:  uint64(start.start.UnixNano()) / 1000,
80		Dur:   uint64(time.Since(start.start).Nanoseconds()) / 1000,
81		Pid:   1,
82		Tid:   uint64(start.cpu),
83	})
84}
85
86func (s *statusOutput) Flush()                                        {}
87func (s *statusOutput) Message(level status.MsgLevel, message string) {}
88
89func (s *statusOutput) Write(p []byte) (int, error) {
90	// Discard writes
91	return len(p), nil
92}
93