in cli_tools/common/image/importer/inflater.go [209:283]
func (facade *shadowTestInflaterFacade) Inflate() (persistentDisk, inflationInfo, error) {
inflaterChan := make(chan string)
// Launch main inflater.
var pd persistentDisk
var ii inflationInfo
var err error
go func() {
pd, ii, err = facade.mainInflater.Inflate()
if err != nil {
inflaterChan <- sigMainInflaterErr
} else {
inflaterChan <- sigMainInflaterDone
}
}()
// Launch shadow inflater.
var shadowPd persistentDisk
var shadowIi inflationInfo
var shadowErr error
go func() {
shadowPd, shadowIi, shadowErr = facade.shadowInflater.Inflate()
if shadowErr != nil {
inflaterChan <- sigShadowInflaterErr
} else {
inflaterChan <- sigShadowInflaterDone
}
}()
var matchResult string
// Return early if main inflater finished first.
result := <-inflaterChan
if result == sigMainInflaterDone || result == sigMainInflaterErr {
if result == sigMainInflaterDone {
matchResult = "Main inflater finished earlier"
} else {
matchResult = "Main inflater failed earlier"
}
// Wait for shadowInflater.inflate() to be canceled. Otherwise, shadowInflater.inflate() may
// be interrupted with temporary resources left: b/169073057
cancelResult := facade.shadowInflater.Cancel("cleanup shadow PD")
if cancelResult == false {
matchResult += " cleanup failed"
}
return pd, ii, err
}
// Wait for main inflater to finish, then process shadow inflater's result.
mainResult := <-inflaterChan
if result == sigShadowInflaterDone {
if mainResult == sigMainInflaterErr {
matchResult = "Main inflater failed while shadow inflater succeeded"
} else {
matchResult = facade.compareWithShadowInflater(&pd, &shadowPd, &ii, &shadowIi)
}
} else if result == sigShadowInflaterErr && mainResult == sigMainInflaterDone {
if isCausedByUnsupportedFormat(shadowErr) {
matchResult = "Shadow inflater doesn't support the format while main inflater supports"
} else if isCausedByAlphaAPIAccess(shadowErr) {
matchResult = "Shadow inflater not executed: no Alpha API access"
} else {
matchResult = fmt.Sprintf("Shadow inflater failed while main inflater succeeded: [%v]", shadowErr)
}
}
facade.logger.Metric(&pb.OutputInfo{
ShadowDiskMatchResult: matchResult,
InflationType: ii.inflationType,
InflationTimeMs: []int64{ii.inflationTime.Milliseconds()},
ShadowInflationTimeMs: []int64{shadowIi.inflationTime.Milliseconds()},
})
return pd, ii, err
}