blob: 63488e5ba66f54bbf7a6e6ae78f319161a93aa9b [file] [log] [blame]
// Copyright (C) 2016 The Android Open Source Project
//
// 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 robotester
import (
"time"
"android.googlesource.com/platform/tools/gpu/client/git"
"android.googlesource.com/platform/tools/gpu/framework/device"
"android.googlesource.com/platform/tools/gpu/framework/log"
"android.googlesource.com/platform/tools/gpu/framework/task"
"android.googlesource.com/platform/tools/gpu/tools/robotester/build"
"android.googlesource.com/platform/tools/gpu/tools/robotester/db"
"android.googlesource.com/platform/tools/gpu/tools/robotester/db/sql/storage"
"android.googlesource.com/platform/tools/gpu/tools/robotester/replay"
"android.googlesource.com/platform/tools/gpu/tools/robotester/service"
"android.googlesource.com/platform/tools/gpu/tools/robotester/sync"
"android.googlesource.com/platform/tools/gpu/tools/robotester/trace"
)
var (
// The time between updates of the state.
updateStateInterval = time.Second * 5
// The time between git pull requests.
syncFrequency = time.Minute * 5
)
// Run begins execution of the service using the specified config and database.
func Run(ctx log.Context, cfg service.Config, database *db.DB) error {
state := &service.State{
Config: cfg,
DB: database,
Host: device.Host(ctx),
}
g, err := git.New(state.Config.Source)
if err != nil {
return err
}
state.Git = g
// Check there are no local changes.
if !state.Config.IgnoreLocalChanges {
status, err := g.Status(ctx)
if err != nil {
return err
}
if !status.Clean() {
return ctx.V("Status", status).AsError("Project has local changes")
}
}
// Register the host device.
if err := state.DB.AddDevices(ctx, state.Host); err != nil {
return ctx.V("Host", state.Host).WrapError(err, "Failed to add the host device to the database")
}
// Find any tasks that were left in a running state. Change these to aborted.
tasks, err := state.DB.QueryTasks(ctx, db.TaskQuery{
Status: db.Running,
Host: storage.DeviceID(&state.Host),
})
if err != nil {
return err
}
for _, t := range tasks {
t.Status = db.Aborted
ctx.Warning().V("Task", t).Log("Changing task from state RUNNING -> ABORTED")
if err := state.DB.AddTasks(ctx, t); err != nil {
ctx.Fail(err, "Failed to update task")
}
}
return poll(ctx, state)
}
func poll(ctx log.Context, state *service.State) error {
traceEvents := task.Events{}
replayEvents := task.Events{}
childContext, childCancel := task.WithCancel(ctx)
for {
// Wait for either the update interval, or service shutdown
if task.ShouldStop(ctx).TryWait(updateStateInterval) {
// service is shutting down
return task.StopReason(ctx)
}
if time.Since(state.LastSync) > syncFrequency {
// Always true on the first time through
if err := sync.Run(childContext, state); err != nil {
return err
}
}
if !state.Config.NoBuild {
if !state.HeadCL.SHA.IsValid() {
// No cl yet, do nothing
continue
}
status, err := build.GetStatus(childContext, state)
if err != nil {
return err
}
if status == db.InvalidStatus {
childCancel()
traceEvents.Wait(ctx)
replayEvents.Wait(ctx)
childContext, childCancel = task.WithCancel(ctx)
if err = build.Run(childContext, state).Result(); err != nil {
ctx.Fail(err, "build errored")
continue
}
if status, err = build.GetStatus(childContext, state); err != nil {
return err
}
}
if status != db.Success {
// not a successful build cl, do nothing else
continue
}
}
if err := trace.Run(childContext, state, &traceEvents); err != nil {
ctx.Fail(err, "trace errored")
}
if err := replay.Run(childContext, state, &replayEvents); err != nil {
ctx.Fail(err, "replay errored")
}
}
}