blob: 3d49d2f1e95c1e27a0d86be493b2fd9df0b00c81 [file] [log] [blame]
Shinichiro Hamajib69bf8a2015-06-10 14:52:06 +09001// Copyright 2015 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
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +090015package kati
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +090016
17import (
Shinichiro Hamaji530136b2015-04-28 17:12:48 +090018 "bytes"
Shinichiro Hamaji4220be32015-05-26 13:30:18 +090019 "crypto/sha1"
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +090020 "encoding/binary"
Shinichiro Hamaji1833c282015-04-28 05:02:27 +090021 "encoding/gob"
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +090022 "encoding/json"
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +090023 "fmt"
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +090024 "io"
Fumitoshi Ukaibc40a462015-06-02 15:51:16 +090025 "io/ioutil"
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +090026 "net/url"
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +090027 "os"
Shinichiro Hamaji530136b2015-04-28 17:12:48 +090028 "sort"
Shinichiro Hamajie666ac82015-04-28 04:18:13 +090029 "strconv"
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +090030 "time"
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +090031
32 "github.com/golang/glog"
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +090033)
34
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +090035const (
Fumitoshi Ukaia78fce02015-06-25 12:29:09 +090036 valueTypeRecursive = 'R'
37 valueTypeSimple = 'S'
38 valueTypeTSV = 'T'
39 valueTypeUndefined = 'U'
40 valueTypeAssign = 'a'
41 valueTypeExpr = 'e'
42 valueTypeFunc = 'f'
43 valueTypeLiteral = 'l'
44 valueTypeNop = 'n'
45 valueTypeParamref = 'p'
46 valueTypeVarref = 'r'
47 valueTypeVarsubst = 's'
48 valueTypeTmpval = 't'
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +090049)
50
Fumitoshi Ukai65c72332015-06-26 21:32:50 +090051// JSON is a json loader/saver.
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +090052var JSON LoadSaver
Fumitoshi Ukai65c72332015-06-26 21:32:50 +090053
54// GOB is a gob loader/saver.
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +090055var GOB LoadSaver
56
57func init() {
58 JSON = jsonLoadSaver{}
59 GOB = gobLoadSaver{}
60}
61
62type jsonLoadSaver struct{}
63type gobLoadSaver struct{}
64
Fumitoshi Ukai65c72332015-06-26 21:32:50 +090065type dumpbuf struct {
66 w bytes.Buffer
67 err error
68}
69
70func (d *dumpbuf) Int(i int) {
71 if d.err != nil {
72 return
73 }
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +090074 v := int32(i)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +090075 d.err = binary.Write(&d.w, binary.LittleEndian, &v)
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +090076}
77
Fumitoshi Ukai65c72332015-06-26 21:32:50 +090078func (d *dumpbuf) Str(s string) {
79 if d.err != nil {
80 return
Fumitoshi Ukai145598a2015-06-19 10:08:17 +090081 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +090082 d.Int(len(s))
83 if d.err != nil {
84 return
85 }
86 _, d.err = io.WriteString(&d.w, s)
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +090087}
88
Fumitoshi Ukai65c72332015-06-26 21:32:50 +090089func (d *dumpbuf) Bytes(b []byte) {
90 if d.err != nil {
91 return
Fumitoshi Ukai145598a2015-06-19 10:08:17 +090092 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +090093 d.Int(len(b))
94 if d.err != nil {
95 return
96 }
97 _, d.err = d.w.Write(b)
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +090098}
99
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900100func (d *dumpbuf) Byte(b byte) {
101 if d.err != nil {
102 return
Fumitoshi Ukai145598a2015-06-19 10:08:17 +0900103 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900104 d.err = writeByte(&d.w, b)
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +0900105}
106
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900107type serializableVar struct {
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900108 Type string
109 V string
110 Origin string
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900111 Children []serializableVar
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900112}
113
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900114type serializableDepNode struct {
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900115 Output int
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900116 Cmds []string
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900117 Deps []int
Fumitoshi Ukaic916ea22015-06-30 09:52:13 +0900118 OrderOnlys []int
Shinichiro Hamaji744b1392015-05-14 23:29:14 +0900119 Parents []int
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900120 HasRule bool
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900121 IsPhony bool
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900122 ActualInputs []int
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900123 TargetSpecificVars []int
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900124 Filename string
125 Lineno int
126}
127
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900128type serializableTargetSpecificVar struct {
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900129 Name string
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900130 Value serializableVar
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900131}
132
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900133type serializableGraph struct {
Fumitoshi Ukai0af44522015-06-25 15:26:08 +0900134 Nodes []*serializableDepNode
135 Vars map[string]serializableVar
136 Tsvs []serializableTargetSpecificVar
137 Targets []string
138 Roots []string
139 AccessedMks []*accessedMakefile
140 Exports map[string]bool
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900141}
142
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900143func encGob(v interface{}) (string, error) {
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900144 var buf bytes.Buffer
145 e := gob.NewEncoder(&buf)
146 err := e.Encode(v)
147 if err != nil {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900148 return "", err
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900149 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900150 return buf.String(), nil
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900151}
152
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900153func encVar(k string, v Var) (string, error) {
154 var dump dumpbuf
155 dump.Str(k)
156 v.dump(&dump)
157 return dump.w.String(), dump.err
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +0900158}
159
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900160type depNodesSerializer struct {
161 nodes []*serializableDepNode
162 tsvs []serializableTargetSpecificVar
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900163 tsvMap map[string]int
164 targets []string
165 targetMap map[string]int
166 done map[string]bool
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900167 err error
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900168}
169
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900170func newDepNodesSerializer() *depNodesSerializer {
171 return &depNodesSerializer{
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900172 tsvMap: make(map[string]int),
173 targetMap: make(map[string]int),
174 done: make(map[string]bool),
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900175 }
176}
177
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900178func (ns *depNodesSerializer) serializeTarget(t string) int {
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900179 id, present := ns.targetMap[t]
180 if present {
181 return id
182 }
183 id = len(ns.targets)
184 ns.targetMap[t] = id
185 ns.targets = append(ns.targets, t)
186 return id
187}
188
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900189func (ns *depNodesSerializer) serializeDepNodes(nodes []*DepNode) {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900190 if ns.err != nil {
191 return
192 }
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900193 for _, n := range nodes {
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900194 if ns.done[n.Output] {
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900195 continue
196 }
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900197 ns.done[n.Output] = true
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900198
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900199 var deps []int
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900200 for _, d := range n.Deps {
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900201 deps = append(deps, ns.serializeTarget(d.Output))
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900202 }
Fumitoshi Ukaic916ea22015-06-30 09:52:13 +0900203 var orderonlys []int
204 for _, d := range n.OrderOnlys {
205 orderonlys = append(orderonlys, ns.serializeTarget(d.Output))
206 }
Shinichiro Hamaji744b1392015-05-14 23:29:14 +0900207 var parents []int
208 for _, d := range n.Parents {
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900209 parents = append(parents, ns.serializeTarget(d.Output))
Shinichiro Hamaji744b1392015-05-14 23:29:14 +0900210 }
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900211 var actualInputs []int
212 for _, i := range n.ActualInputs {
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900213 actualInputs = append(actualInputs, ns.serializeTarget(i))
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900214 }
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900215
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900216 // Sort keys for consistent serialization.
217 var tsvKeys []string
218 for k := range n.TargetSpecificVars {
219 tsvKeys = append(tsvKeys, k)
220 }
221 sort.Strings(tsvKeys)
222
223 var vars []int
224 for _, k := range tsvKeys {
225 v := n.TargetSpecificVars[k]
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900226 sv := serializableTargetSpecificVar{Name: k, Value: v.serialize()}
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +0900227 //gob := encGob(sv)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900228 gob, err := encVar(k, v)
229 if err != nil {
230 ns.err = err
231 return
232 }
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900233 id, present := ns.tsvMap[gob]
234 if !present {
235 id = len(ns.tsvs)
236 ns.tsvMap[gob] = id
237 ns.tsvs = append(ns.tsvs, sv)
238 }
239 vars = append(vars, id)
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900240 }
241
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900242 ns.nodes = append(ns.nodes, &serializableDepNode{
243 Output: ns.serializeTarget(n.Output),
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900244 Cmds: n.Cmds,
245 Deps: deps,
Fumitoshi Ukaic916ea22015-06-30 09:52:13 +0900246 OrderOnlys: orderonlys,
Shinichiro Hamaji744b1392015-05-14 23:29:14 +0900247 Parents: parents,
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900248 HasRule: n.HasRule,
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900249 IsPhony: n.IsPhony,
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900250 ActualInputs: actualInputs,
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900251 TargetSpecificVars: vars,
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900252 Filename: n.Filename,
253 Lineno: n.Lineno,
254 })
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900255 ns.serializeDepNodes(n.Deps)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900256 if ns.err != nil {
257 return
258 }
Fumitoshi Ukaic916ea22015-06-30 09:52:13 +0900259 ns.serializeDepNodes(n.OrderOnlys)
260 if ns.err != nil {
261 return
262 }
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900263 }
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900264}
265
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900266func makeSerializableVars(vars Vars) (r map[string]serializableVar) {
267 r = make(map[string]serializableVar)
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900268 for k, v := range vars {
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900269 r[k] = v.serialize()
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900270 }
271 return r
272}
273
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900274func makeSerializableGraph(g *DepGraph, roots []string) (serializableGraph, error) {
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900275 ns := newDepNodesSerializer()
276 ns.serializeDepNodes(g.nodes)
277 v := makeSerializableVars(g.vars)
278 return serializableGraph{
Fumitoshi Ukai0af44522015-06-25 15:26:08 +0900279 Nodes: ns.nodes,
280 Vars: v,
281 Tsvs: ns.tsvs,
282 Targets: ns.targets,
283 Roots: roots,
284 AccessedMks: g.accessedMks,
285 Exports: g.exports,
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900286 }, ns.err
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900287}
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900288
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +0900289func (jsonLoadSaver) Save(g *DepGraph, filename string, roots []string) error {
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900290 startTime := time.Now()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900291 sg, err := makeSerializableGraph(g, roots)
292 if err != nil {
293 return err
294 }
Shinichiro Hamaji750ae2e2015-05-20 12:59:15 +0900295 o, err := json.MarshalIndent(sg, " ", " ")
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900296 if err != nil {
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +0900297 return err
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900298 }
Shinichiro Hamaji1833c282015-04-28 05:02:27 +0900299 f, err := os.Create(filename)
300 if err != nil {
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +0900301 return err
302 }
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900303 _, err = f.Write(o)
304 if err != nil {
305 f.Close()
306 return err
307 }
308 err = f.Close()
309 if err != nil {
310 return err
311 }
312 logStats("json serialize time: %q", time.Since(startTime))
313 return nil
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +0900314}
315
316func (gobLoadSaver) Save(g *DepGraph, filename string, roots []string) error {
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900317 startTime := time.Now()
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +0900318 f, err := os.Create(filename)
319 if err != nil {
320 return err
Shinichiro Hamaji1833c282015-04-28 05:02:27 +0900321 }
322 e := gob.NewEncoder(f)
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900323 var sg serializableGraph
324 {
325 startTime := time.Now()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900326 sg, err = makeSerializableGraph(g, roots)
327 if err != nil {
328 return err
329 }
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900330 logStats("gob serialize prepare time: %q", time.Since(startTime))
331 }
332 {
333 startTime := time.Now()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900334 err = e.Encode(sg)
335 if err != nil {
336 return err
337 }
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900338 logStats("gob serialize output time: %q", time.Since(startTime))
339 }
340 err = f.Close()
341 if err != nil {
342 return err
343 }
344 logStats("gob serialize time: %q", time.Since(startTime))
345 return nil
Shinichiro Hamaji1833c282015-04-28 05:02:27 +0900346}
347
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900348func cacheFilename(mk string, roots []string) string {
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900349 filename := ".kati_cache." + mk
350 for _, r := range roots {
351 filename += "." + r
352 }
353 return url.QueryEscape(filename)
354}
355
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900356func saveCache(g *DepGraph, roots []string) error {
Fumitoshi Ukai0af44522015-06-25 15:26:08 +0900357 if len(g.accessedMks) == 0 {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900358 return fmt.Errorf("no Makefile is read")
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900359 }
Fumitoshi Ukai0af44522015-06-25 15:26:08 +0900360 cacheFile := cacheFilename(g.accessedMks[0].Filename, roots)
361 for _, mk := range g.accessedMks {
Shinichiro Hamajif3ea5d02015-05-20 17:13:00 +0900362 // Inconsistent, do not dump this result.
Fumitoshi Ukai0af44522015-06-25 15:26:08 +0900363 if mk.State == fileInconsistent {
Shinichiro Hamajif3ea5d02015-05-20 17:13:00 +0900364 if exists(cacheFile) {
365 os.Remove(cacheFile)
366 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900367 return nil
Shinichiro Hamajif3ea5d02015-05-20 17:13:00 +0900368 }
369 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900370 return GOB.Save(g, cacheFile, roots)
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900371}
372
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900373func deserializeSingleChild(sv serializableVar) (Value, error) {
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900374 if len(sv.Children) != 1 {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900375 return nil, fmt.Errorf("unexpected number of children: %q", sv)
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900376 }
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900377 return deserializeVar(sv.Children[0])
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900378}
379
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900380func deserializeVar(sv serializableVar) (r Value, err error) {
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900381 switch sv.Type {
382 case "literal":
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900383 return literal(sv.V), nil
Shinichiro Hamajic8dea2a2015-04-28 17:15:30 +0900384 case "tmpval":
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900385 return tmpval([]byte(sv.V)), nil
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900386 case "expr":
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900387 var e expr
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900388 for _, v := range sv.Children {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900389 dv, err := deserializeVar(v)
390 if err != nil {
391 return nil, err
392 }
393 e = append(e, dv)
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900394 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900395 return e, nil
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900396 case "varref":
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900397 dv, err := deserializeSingleChild(sv)
398 if err != nil {
399 return nil, err
400 }
Fumitoshi Ukaibbb0db52015-06-30 16:51:27 +0900401 return &varref{varname: dv, paren: sv.V[0]}, nil
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900402 case "paramref":
403 v, err := strconv.Atoi(sv.V)
404 if err != nil {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900405 return nil, err
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900406 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900407 return paramref(v), nil
Shinichiro Hamajic8dea2a2015-04-28 17:15:30 +0900408 case "varsubst":
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900409 varname, err := deserializeVar(sv.Children[0])
410 if err != nil {
411 return nil, err
Shinichiro Hamajic8dea2a2015-04-28 17:15:30 +0900412 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900413 pat, err := deserializeVar(sv.Children[1])
414 if err != nil {
415 return nil, err
416 }
417 subst, err := deserializeVar(sv.Children[2])
418 if err != nil {
419 return nil, err
420 }
421 return varsubst{
422 varname: varname,
423 pat: pat,
424 subst: subst,
Fumitoshi Ukaibbb0db52015-06-30 16:51:27 +0900425 paren: sv.V[0],
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900426 }, nil
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900427
428 case "func":
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900429 dv, err := deserializeVar(sv.Children[0])
430 if err != nil {
431 return nil, err
432 }
433 name, ok := dv.(literal)
434 if !ok {
435 return nil, fmt.Errorf("func name is not literal %s: %T", dv, dv)
436 }
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900437 f := funcMap[string(name[1:])]()
438 f.AddArg(name)
439 for _, a := range sv.Children[1:] {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900440 dv, err := deserializeVar(a)
441 if err != nil {
442 return nil, err
443 }
444 f.AddArg(dv)
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900445 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900446 return f, nil
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900447 case "funcEvalAssign":
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900448 rhs, err := deserializeVar(sv.Children[2])
449 if err != nil {
450 return nil, err
451 }
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900452 return &funcEvalAssign{
453 lhs: sv.Children[0].V,
Shinichiro Hamaji3d6d0aa2015-04-28 16:18:44 +0900454 op: sv.Children[1].V,
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900455 rhs: rhs,
456 }, nil
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900457 case "funcNop":
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900458 return &funcNop{expr: sv.V}, nil
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900459
460 case "simple":
Fumitoshi Ukai7bf992d2015-06-25 12:42:19 +0900461 return &simpleVar{
Fumitoshi Ukaidd248f22015-06-18 23:04:28 +0900462 value: sv.V,
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900463 origin: sv.Origin,
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900464 }, nil
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900465 case "recursive":
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900466 expr, err := deserializeSingleChild(sv)
467 if err != nil {
468 return nil, err
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900469 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900470 return &recursiveVar{
471 expr: expr,
472 origin: sv.Origin,
473 }, nil
Shinichiro Hamajif8f075c2015-04-28 04:25:37 +0900474
475 case ":=", "=", "+=", "?=":
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900476 dv, err := deserializeSingleChild(sv)
477 if err != nil {
478 return nil, err
Shinichiro Hamajif8f075c2015-04-28 04:25:37 +0900479 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900480 v, ok := dv.(Var)
481 if !ok {
482 return nil, fmt.Errorf("not var: target specific var %s %T", dv, dv)
483 }
484 return &targetSpecificVar{
485 v: v,
486 op: sv.Type,
487 }, nil
Shinichiro Hamajif8f075c2015-04-28 04:25:37 +0900488
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900489 default:
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900490 return nil, fmt.Errorf("unknown serialized variable type: %q", sv)
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900491 }
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900492}
493
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900494func deserializeVars(vars map[string]serializableVar) (Vars, error) {
Shinichiro Hamaji79a56932015-04-28 03:53:57 +0900495 r := make(Vars)
496 for k, v := range vars {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900497 dv, err := deserializeVar(v)
498 if err != nil {
499 return nil, err
500 }
501 vv, ok := dv.(Var)
502 if !ok {
503 return nil, fmt.Errorf("not var: %s: %T", dv, dv)
504 }
505 r[k] = vv
Shinichiro Hamaji79a56932015-04-28 03:53:57 +0900506 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900507 return r, nil
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900508}
509
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900510func deserializeNodes(g serializableGraph) (r []*DepNode, err error) {
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900511 nodes := g.Nodes
512 tsvs := g.Tsvs
513 targets := g.Targets
Shinichiro Hamaji7a65e682015-04-28 18:00:12 +0900514 // Deserialize all TSVs first so that multiple rules can share memory.
515 var tsvValues []Var
516 for _, sv := range tsvs {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900517 dv, err := deserializeVar(sv.Value)
518 if err != nil {
519 return nil, err
520 }
521 vv, ok := dv.(Var)
522 if !ok {
523 return nil, fmt.Errorf("not var: %s %T", dv, dv)
524 }
525 tsvValues = append(tsvValues, vv)
Shinichiro Hamaji7a65e682015-04-28 18:00:12 +0900526 }
527
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900528 nodeMap := make(map[string]*DepNode)
529 for _, n := range nodes {
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900530 var actualInputs []string
531 for _, i := range n.ActualInputs {
532 actualInputs = append(actualInputs, targets[i])
533 }
534
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900535 d := &DepNode{
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900536 Output: targets[n.Output],
Shinichiro Hamaji3d6d0aa2015-04-28 16:18:44 +0900537 Cmds: n.Cmds,
538 HasRule: n.HasRule,
Shinichiro Hamaji3d6d0aa2015-04-28 16:18:44 +0900539 IsPhony: n.IsPhony,
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900540 ActualInputs: actualInputs,
Shinichiro Hamaji3d6d0aa2015-04-28 16:18:44 +0900541 Filename: n.Filename,
542 Lineno: n.Lineno,
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900543 TargetSpecificVars: make(Vars),
544 }
545
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900546 for _, id := range n.TargetSpecificVars {
547 sv := tsvs[id]
Shinichiro Hamaji7a65e682015-04-28 18:00:12 +0900548 d.TargetSpecificVars[sv.Name] = tsvValues[id]
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900549 }
550
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900551 nodeMap[targets[n.Output]] = d
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900552 r = append(r, d)
553 }
554
555 for _, n := range nodes {
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900556 d := nodeMap[targets[n.Output]]
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900557 for _, o := range n.Deps {
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900558 c, present := nodeMap[targets[o]]
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900559 if !present {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900560 return nil, fmt.Errorf("unknown target: %d (%s)", o, targets[o])
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900561 }
562 d.Deps = append(d.Deps, c)
563 }
Fumitoshi Ukaic916ea22015-06-30 09:52:13 +0900564 for _, o := range n.OrderOnlys {
565 c, present := nodeMap[targets[o]]
566 if !present {
567 return nil, fmt.Errorf("unknown target: %d (%s)", o, targets[o])
568 }
569 d.OrderOnlys = append(d.OrderOnlys, c)
570 }
Shinichiro Hamaji744b1392015-05-14 23:29:14 +0900571 for _, o := range n.Parents {
572 c, present := nodeMap[targets[o]]
573 if !present {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900574 return nil, fmt.Errorf("unknown target: %d (%s)", o, targets[o])
Shinichiro Hamaji744b1392015-05-14 23:29:14 +0900575 }
576 d.Parents = append(d.Parents, c)
577 }
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900578 }
579
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900580 return r, nil
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900581}
582
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900583func human(n int) string {
Shinichiro Hamaji744b1392015-05-14 23:29:14 +0900584 if n >= 10*1000*1000*1000 {
585 return fmt.Sprintf("%.2fGB", float32(n)/1000/1000/1000)
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900586 }
Fumitoshi Ukai936de102015-06-08 11:21:16 +0900587 if n >= 10*1000*1000 {
588 return fmt.Sprintf("%.2fMB", float32(n)/1000/1000)
589 }
590 if n >= 10*1000 {
591 return fmt.Sprintf("%.2fkB", float32(n)/1000)
592 }
593 return fmt.Sprintf("%dB", n)
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900594}
595
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900596func showSerializedNodesStats(nodes []*serializableDepNode) {
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900597 outputSize := 0
598 cmdSize := 0
599 depsSize := 0
Fumitoshi Ukaic916ea22015-06-30 09:52:13 +0900600 orderOnlysSize := 0
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900601 actualInputSize := 0
602 tsvSize := 0
603 filenameSize := 0
604 linenoSize := 0
605 for _, n := range nodes {
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900606 outputSize += 4
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900607 for _, c := range n.Cmds {
608 cmdSize += len(c)
609 }
Fumitoshi Ukaic916ea22015-06-30 09:52:13 +0900610 depsSize += 4 * len(n.Deps)
611 orderOnlysSize += 4 * len(n.OrderOnlys)
612 actualInputSize += 4 * len(n.ActualInputs)
613 tsvSize += 4 * len(n.TargetSpecificVars)
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900614 filenameSize += len(n.Filename)
615 linenoSize += 4
616 }
Fumitoshi Ukaic916ea22015-06-30 09:52:13 +0900617 size := outputSize + cmdSize + depsSize + orderOnlysSize + actualInputSize + tsvSize + filenameSize + linenoSize
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900618 logStats("%d nodes %s", len(nodes), human(size))
619 logStats(" output %s", human(outputSize))
620 logStats(" command %s", human(cmdSize))
621 logStats(" deps %s", human(depsSize))
Fumitoshi Ukaic916ea22015-06-30 09:52:13 +0900622 logStats(" orderonlys %s", human(orderOnlysSize))
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900623 logStats(" inputs %s", human(actualInputSize))
624 logStats(" tsv %s", human(tsvSize))
625 logStats(" filename %s", human(filenameSize))
626 logStats(" lineno %s", human(linenoSize))
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900627}
628
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900629func (v serializableVar) size() int {
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900630 size := 0
631 size += len(v.Type)
632 size += len(v.V)
633 size += len(v.Origin)
634 for _, c := range v.Children {
635 size += c.size()
636 }
637 return size
638}
639
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900640func showSerializedVarsStats(vars map[string]serializableVar) {
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900641 nameSize := 0
642 valueSize := 0
643 for k, v := range vars {
644 nameSize += len(k)
645 valueSize += v.size()
646 }
647 size := nameSize + valueSize
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900648 logStats("%d vars %s", len(vars), human(size))
649 logStats(" name %s", human(nameSize))
650 logStats(" value %s", human(valueSize))
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900651}
652
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900653func showSerializedTsvsStats(vars []serializableTargetSpecificVar) {
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900654 nameSize := 0
655 valueSize := 0
656 for _, v := range vars {
657 nameSize += len(v.Name)
658 valueSize += v.Value.size()
659 }
660 size := nameSize + valueSize
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900661 logStats("%d tsvs %s", len(vars), human(size))
662 logStats(" name %s", human(nameSize))
663 logStats(" value %s", human(valueSize))
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900664}
665
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900666func showSerializedTargetsStats(targets []string) {
667 size := 0
668 for _, t := range targets {
669 size += len(t)
670 }
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900671 logStats("%d targets %s", len(targets), human(size))
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900672}
673
Fumitoshi Ukai0af44522015-06-25 15:26:08 +0900674func showSerializedAccessedMksStats(accessedMks []*accessedMakefile) {
Shinichiro Hamaji006adbf2015-05-25 18:42:12 +0900675 size := 0
Fumitoshi Ukai0af44522015-06-25 15:26:08 +0900676 for _, rm := range accessedMks {
Shinichiro Hamaji4220be32015-05-26 13:30:18 +0900677 size += len(rm.Filename) + len(rm.Hash) + 4
Shinichiro Hamaji006adbf2015-05-25 18:42:12 +0900678 }
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900679 logStats("%d makefiles %s", len(accessedMks), human(size))
Shinichiro Hamaji006adbf2015-05-25 18:42:12 +0900680}
681
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900682func showSerializedGraphStats(g serializableGraph) {
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900683 showSerializedNodesStats(g.Nodes)
684 showSerializedVarsStats(g.Vars)
685 showSerializedTsvsStats(g.Tsvs)
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900686 showSerializedTargetsStats(g.Targets)
Fumitoshi Ukai0af44522015-06-25 15:26:08 +0900687 showSerializedAccessedMksStats(g.AccessedMks)
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900688}
689
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900690func deserializeGraph(g serializableGraph) (*DepGraph, error) {
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +0900691 if StatsFlag {
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900692 showSerializedGraphStats(g)
693 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900694 nodes, err := deserializeNodes(g)
695 if err != nil {
696 return nil, err
697 }
698 vars, err := deserializeVars(g.Vars)
699 if err != nil {
700 return nil, err
701 }
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900702 return &DepGraph{
Fumitoshi Ukai0af44522015-06-25 15:26:08 +0900703 nodes: nodes,
704 vars: vars,
705 accessedMks: g.AccessedMks,
706 exports: g.Exports,
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900707 }, nil
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900708}
709
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +0900710func (jsonLoadSaver) Load(filename string) (*DepGraph, error) {
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900711 startTime := time.Now()
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900712 f, err := os.Open(filename)
713 if err != nil {
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +0900714 return nil, err
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900715 }
Fumitoshi Ukaied9a6152015-06-02 15:28:55 +0900716 defer f.Close()
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900717
718 d := json.NewDecoder(f)
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900719 g := serializableGraph{Vars: make(map[string]serializableVar)}
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900720 err = d.Decode(&g)
721 if err != nil {
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +0900722 return nil, err
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900723 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900724 dg, err := deserializeGraph(g)
725 if err != nil {
726 return nil, err
727 }
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900728 logStats("gob deserialize time: %q", time.Since(startTime))
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +0900729 return dg, nil
Shinichiro Hamaji1833c282015-04-28 05:02:27 +0900730}
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900731
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +0900732func (gobLoadSaver) Load(filename string) (*DepGraph, error) {
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900733 startTime := time.Now()
Shinichiro Hamaji1833c282015-04-28 05:02:27 +0900734 f, err := os.Open(filename)
735 if err != nil {
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +0900736 return nil, err
Shinichiro Hamaji1833c282015-04-28 05:02:27 +0900737 }
Fumitoshi Ukaied9a6152015-06-02 15:28:55 +0900738 defer f.Close()
Shinichiro Hamaji1833c282015-04-28 05:02:27 +0900739
740 d := gob.NewDecoder(f)
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900741 g := serializableGraph{Vars: make(map[string]serializableVar)}
Shinichiro Hamaji1833c282015-04-28 05:02:27 +0900742 err = d.Decode(&g)
743 if err != nil {
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +0900744 return nil, err
Shinichiro Hamaji1833c282015-04-28 05:02:27 +0900745 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900746 dg, err := deserializeGraph(g)
747 if err != nil {
748 return nil, err
749 }
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900750 logStats("json deserialize time: %q", time.Since(startTime))
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +0900751 return dg, nil
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900752}
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900753
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900754func loadCache(makefile string, roots []string) (*DepGraph, error) {
Shinichiro Hamaji82ecff92015-05-25 18:36:04 +0900755 startTime := time.Now()
756 defer func() {
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900757 logStats("Cache lookup time: %q", time.Since(startTime))
Shinichiro Hamaji82ecff92015-05-25 18:36:04 +0900758 }()
759
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900760 filename := cacheFilename(makefile, roots)
Shinichiro Hamaji39e62402015-05-20 19:34:58 +0900761 if !exists(filename) {
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +0900762 glog.Warningf("Cache not found %q", filename)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900763 return nil, fmt.Errorf("cache not found: %s", filename)
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900764 }
Shinichiro Hamaji39e62402015-05-20 19:34:58 +0900765
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +0900766 g, err := GOB.Load(filename)
767 if err != nil {
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +0900768 glog.Warning("Cache load error %q: %v", filename, err)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900769 return nil, err
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +0900770 }
Fumitoshi Ukai0af44522015-06-25 15:26:08 +0900771 for _, mk := range g.accessedMks {
772 if mk.State != fileExists && mk.State != fileNotExists {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900773 return nil, fmt.Errorf("internal error: broken state: %d", mk.State)
Shinichiro Hamaji0ba75a92015-05-20 19:42:43 +0900774 }
Fumitoshi Ukai0af44522015-06-25 15:26:08 +0900775 if mk.State == fileNotExists {
Shinichiro Hamaji45cde1d2015-05-25 18:21:23 +0900776 if exists(mk.Filename) {
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +0900777 glog.Infof("Cache expired: %s", mk.Filename)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900778 return nil, fmt.Errorf("cache expired: %s", mk.Filename)
Shinichiro Hamaji45cde1d2015-05-25 18:21:23 +0900779 }
780 } else {
Fumitoshi Ukaibc40a462015-06-02 15:51:16 +0900781 c, err := ioutil.ReadFile(mk.Filename)
Shinichiro Hamaji4220be32015-05-26 13:30:18 +0900782 if err != nil {
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +0900783 glog.Infof("Cache expired: %s", mk.Filename)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900784 return nil, fmt.Errorf("cache expired: %s", mk.Filename)
Shinichiro Hamaji4220be32015-05-26 13:30:18 +0900785 }
786 h := sha1.Sum(c)
787 if !bytes.Equal(h[:], mk.Hash[:]) {
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +0900788 glog.Infof("Cache expired: %s", mk.Filename)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900789 return nil, fmt.Errorf("cache expired: %s", mk.Filename)
Shinichiro Hamaji45cde1d2015-05-25 18:21:23 +0900790 }
Shinichiro Hamaji39e62402015-05-20 19:34:58 +0900791 }
792 }
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +0900793 glog.Info("Cache found in %q", filename)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900794 return g, nil
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900795}