blob: 3ccb4699d18b4808f7370d2251255fc9dc14454c [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"
Fumitoshi Ukai7655f182015-07-15 14:05:41 +090030 "strings"
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +090031 "time"
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +090032
33 "github.com/golang/glog"
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +090034)
35
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +090036const (
Fumitoshi Ukaia78fce02015-06-25 12:29:09 +090037 valueTypeRecursive = 'R'
38 valueTypeSimple = 'S'
39 valueTypeTSV = 'T'
40 valueTypeUndefined = 'U'
41 valueTypeAssign = 'a'
42 valueTypeExpr = 'e'
43 valueTypeFunc = 'f'
44 valueTypeLiteral = 'l'
45 valueTypeNop = 'n'
46 valueTypeParamref = 'p'
47 valueTypeVarref = 'r'
48 valueTypeVarsubst = 's'
49 valueTypeTmpval = 't'
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +090050)
51
Fumitoshi Ukai65c72332015-06-26 21:32:50 +090052// JSON is a json loader/saver.
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +090053var JSON LoadSaver
Fumitoshi Ukai65c72332015-06-26 21:32:50 +090054
55// GOB is a gob loader/saver.
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +090056var GOB LoadSaver
57
58func init() {
59 JSON = jsonLoadSaver{}
60 GOB = gobLoadSaver{}
61}
62
63type jsonLoadSaver struct{}
64type gobLoadSaver struct{}
65
Fumitoshi Ukai65c72332015-06-26 21:32:50 +090066type dumpbuf struct {
67 w bytes.Buffer
68 err error
69}
70
71func (d *dumpbuf) Int(i int) {
72 if d.err != nil {
73 return
74 }
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +090075 v := int32(i)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +090076 d.err = binary.Write(&d.w, binary.LittleEndian, &v)
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +090077}
78
Fumitoshi Ukai65c72332015-06-26 21:32:50 +090079func (d *dumpbuf) Str(s string) {
80 if d.err != nil {
81 return
Fumitoshi Ukai145598a2015-06-19 10:08:17 +090082 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +090083 d.Int(len(s))
84 if d.err != nil {
85 return
86 }
87 _, d.err = io.WriteString(&d.w, s)
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +090088}
89
Fumitoshi Ukai65c72332015-06-26 21:32:50 +090090func (d *dumpbuf) Bytes(b []byte) {
91 if d.err != nil {
92 return
Fumitoshi Ukai145598a2015-06-19 10:08:17 +090093 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +090094 d.Int(len(b))
95 if d.err != nil {
96 return
97 }
98 _, d.err = d.w.Write(b)
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +090099}
100
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900101func (d *dumpbuf) Byte(b byte) {
102 if d.err != nil {
103 return
Fumitoshi Ukai145598a2015-06-19 10:08:17 +0900104 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900105 d.err = writeByte(&d.w, b)
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +0900106}
107
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900108type serializableVar struct {
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900109 Type string
110 V string
111 Origin string
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900112 Children []serializableVar
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900113}
114
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900115type serializableDepNode struct {
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900116 Output int
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900117 Cmds []string
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900118 Deps []int
Fumitoshi Ukaic916ea22015-06-30 09:52:13 +0900119 OrderOnlys []int
Shinichiro Hamaji744b1392015-05-14 23:29:14 +0900120 Parents []int
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900121 HasRule bool
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900122 IsPhony bool
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900123 ActualInputs []int
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900124 TargetSpecificVars []int
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900125 Filename string
126 Lineno int
127}
128
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900129type serializableTargetSpecificVar struct {
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900130 Name string
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900131 Value serializableVar
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900132}
133
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900134type serializableGraph struct {
Fumitoshi Ukai0af44522015-06-25 15:26:08 +0900135 Nodes []*serializableDepNode
136 Vars map[string]serializableVar
137 Tsvs []serializableTargetSpecificVar
138 Targets []string
139 Roots []string
140 AccessedMks []*accessedMakefile
141 Exports map[string]bool
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900142}
143
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900144func encGob(v interface{}) (string, error) {
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900145 var buf bytes.Buffer
146 e := gob.NewEncoder(&buf)
147 err := e.Encode(v)
148 if err != nil {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900149 return "", err
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900150 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900151 return buf.String(), nil
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900152}
153
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900154func encVar(k string, v Var) (string, error) {
155 var dump dumpbuf
156 dump.Str(k)
157 v.dump(&dump)
158 return dump.w.String(), dump.err
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +0900159}
160
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900161type depNodesSerializer struct {
162 nodes []*serializableDepNode
163 tsvs []serializableTargetSpecificVar
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900164 tsvMap map[string]int
165 targets []string
166 targetMap map[string]int
167 done map[string]bool
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900168 err error
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900169}
170
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900171func newDepNodesSerializer() *depNodesSerializer {
172 return &depNodesSerializer{
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900173 tsvMap: make(map[string]int),
174 targetMap: make(map[string]int),
175 done: make(map[string]bool),
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900176 }
177}
178
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900179func (ns *depNodesSerializer) serializeTarget(t string) int {
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900180 id, present := ns.targetMap[t]
181 if present {
182 return id
183 }
184 id = len(ns.targets)
185 ns.targetMap[t] = id
186 ns.targets = append(ns.targets, t)
187 return id
188}
189
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900190func (ns *depNodesSerializer) serializeDepNodes(nodes []*DepNode) {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900191 if ns.err != nil {
192 return
193 }
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900194 for _, n := range nodes {
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900195 if ns.done[n.Output] {
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900196 continue
197 }
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900198 ns.done[n.Output] = true
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900199
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900200 var deps []int
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900201 for _, d := range n.Deps {
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900202 deps = append(deps, ns.serializeTarget(d.Output))
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900203 }
Fumitoshi Ukaic916ea22015-06-30 09:52:13 +0900204 var orderonlys []int
205 for _, d := range n.OrderOnlys {
206 orderonlys = append(orderonlys, ns.serializeTarget(d.Output))
207 }
Shinichiro Hamaji744b1392015-05-14 23:29:14 +0900208 var parents []int
209 for _, d := range n.Parents {
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900210 parents = append(parents, ns.serializeTarget(d.Output))
Shinichiro Hamaji744b1392015-05-14 23:29:14 +0900211 }
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900212 var actualInputs []int
213 for _, i := range n.ActualInputs {
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900214 actualInputs = append(actualInputs, ns.serializeTarget(i))
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900215 }
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900216
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900217 // Sort keys for consistent serialization.
218 var tsvKeys []string
219 for k := range n.TargetSpecificVars {
220 tsvKeys = append(tsvKeys, k)
221 }
222 sort.Strings(tsvKeys)
223
224 var vars []int
225 for _, k := range tsvKeys {
226 v := n.TargetSpecificVars[k]
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900227 sv := serializableTargetSpecificVar{Name: k, Value: v.serialize()}
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +0900228 //gob := encGob(sv)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900229 gob, err := encVar(k, v)
230 if err != nil {
231 ns.err = err
232 return
233 }
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900234 id, present := ns.tsvMap[gob]
235 if !present {
236 id = len(ns.tsvs)
237 ns.tsvMap[gob] = id
238 ns.tsvs = append(ns.tsvs, sv)
239 }
240 vars = append(vars, id)
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900241 }
242
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900243 ns.nodes = append(ns.nodes, &serializableDepNode{
244 Output: ns.serializeTarget(n.Output),
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900245 Cmds: n.Cmds,
246 Deps: deps,
Fumitoshi Ukaic916ea22015-06-30 09:52:13 +0900247 OrderOnlys: orderonlys,
Shinichiro Hamaji744b1392015-05-14 23:29:14 +0900248 Parents: parents,
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900249 HasRule: n.HasRule,
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900250 IsPhony: n.IsPhony,
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900251 ActualInputs: actualInputs,
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900252 TargetSpecificVars: vars,
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900253 Filename: n.Filename,
254 Lineno: n.Lineno,
255 })
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900256 ns.serializeDepNodes(n.Deps)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900257 if ns.err != nil {
258 return
259 }
Fumitoshi Ukaic916ea22015-06-30 09:52:13 +0900260 ns.serializeDepNodes(n.OrderOnlys)
261 if ns.err != nil {
262 return
263 }
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900264 }
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900265}
266
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900267func makeSerializableVars(vars Vars) (r map[string]serializableVar) {
268 r = make(map[string]serializableVar)
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900269 for k, v := range vars {
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900270 r[k] = v.serialize()
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900271 }
272 return r
273}
274
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900275func makeSerializableGraph(g *DepGraph, roots []string) (serializableGraph, error) {
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900276 ns := newDepNodesSerializer()
277 ns.serializeDepNodes(g.nodes)
278 v := makeSerializableVars(g.vars)
279 return serializableGraph{
Fumitoshi Ukai0af44522015-06-25 15:26:08 +0900280 Nodes: ns.nodes,
281 Vars: v,
282 Tsvs: ns.tsvs,
283 Targets: ns.targets,
284 Roots: roots,
285 AccessedMks: g.accessedMks,
286 Exports: g.exports,
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900287 }, ns.err
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900288}
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900289
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +0900290func (jsonLoadSaver) Save(g *DepGraph, filename string, roots []string) error {
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900291 startTime := time.Now()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900292 sg, err := makeSerializableGraph(g, roots)
293 if err != nil {
294 return err
295 }
Shinichiro Hamaji750ae2e2015-05-20 12:59:15 +0900296 o, err := json.MarshalIndent(sg, " ", " ")
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900297 if err != nil {
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +0900298 return err
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900299 }
Shinichiro Hamaji1833c282015-04-28 05:02:27 +0900300 f, err := os.Create(filename)
301 if err != nil {
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +0900302 return err
303 }
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900304 _, err = f.Write(o)
305 if err != nil {
306 f.Close()
307 return err
308 }
309 err = f.Close()
310 if err != nil {
311 return err
312 }
313 logStats("json serialize time: %q", time.Since(startTime))
314 return nil
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +0900315}
316
317func (gobLoadSaver) Save(g *DepGraph, filename string, roots []string) error {
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900318 startTime := time.Now()
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +0900319 f, err := os.Create(filename)
320 if err != nil {
321 return err
Shinichiro Hamaji1833c282015-04-28 05:02:27 +0900322 }
323 e := gob.NewEncoder(f)
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900324 var sg serializableGraph
325 {
326 startTime := time.Now()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900327 sg, err = makeSerializableGraph(g, roots)
328 if err != nil {
329 return err
330 }
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900331 logStats("gob serialize prepare time: %q", time.Since(startTime))
332 }
333 {
334 startTime := time.Now()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900335 err = e.Encode(sg)
336 if err != nil {
337 return err
338 }
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900339 logStats("gob serialize output time: %q", time.Since(startTime))
340 }
341 err = f.Close()
342 if err != nil {
343 return err
344 }
345 logStats("gob serialize time: %q", time.Since(startTime))
346 return nil
Shinichiro Hamaji1833c282015-04-28 05:02:27 +0900347}
348
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900349func cacheFilename(mk string, roots []string) string {
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900350 filename := ".kati_cache." + mk
351 for _, r := range roots {
352 filename += "." + r
353 }
354 return url.QueryEscape(filename)
355}
356
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900357func saveCache(g *DepGraph, roots []string) error {
Fumitoshi Ukai0af44522015-06-25 15:26:08 +0900358 if len(g.accessedMks) == 0 {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900359 return fmt.Errorf("no Makefile is read")
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900360 }
Fumitoshi Ukai0af44522015-06-25 15:26:08 +0900361 cacheFile := cacheFilename(g.accessedMks[0].Filename, roots)
362 for _, mk := range g.accessedMks {
Shinichiro Hamajif3ea5d02015-05-20 17:13:00 +0900363 // Inconsistent, do not dump this result.
Fumitoshi Ukai0af44522015-06-25 15:26:08 +0900364 if mk.State == fileInconsistent {
Shinichiro Hamajif3ea5d02015-05-20 17:13:00 +0900365 if exists(cacheFile) {
366 os.Remove(cacheFile)
367 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900368 return nil
Shinichiro Hamajif3ea5d02015-05-20 17:13:00 +0900369 }
370 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900371 return GOB.Save(g, cacheFile, roots)
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900372}
373
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900374func deserializeSingleChild(sv serializableVar) (Value, error) {
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900375 if len(sv.Children) != 1 {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900376 return nil, fmt.Errorf("unexpected number of children: %q", sv)
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900377 }
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900378 return deserializeVar(sv.Children[0])
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900379}
380
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900381func deserializeVar(sv serializableVar) (r Value, err error) {
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900382 switch sv.Type {
383 case "literal":
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900384 return literal(sv.V), nil
Shinichiro Hamajic8dea2a2015-04-28 17:15:30 +0900385 case "tmpval":
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900386 return tmpval([]byte(sv.V)), nil
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900387 case "expr":
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900388 var e expr
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900389 for _, v := range sv.Children {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900390 dv, err := deserializeVar(v)
391 if err != nil {
392 return nil, err
393 }
394 e = append(e, dv)
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900395 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900396 return e, nil
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900397 case "varref":
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900398 dv, err := deserializeSingleChild(sv)
399 if err != nil {
400 return nil, err
401 }
Fumitoshi Ukaibbb0db52015-06-30 16:51:27 +0900402 return &varref{varname: dv, paren: sv.V[0]}, nil
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900403 case "paramref":
404 v, err := strconv.Atoi(sv.V)
405 if err != nil {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900406 return nil, err
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900407 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900408 return paramref(v), nil
Shinichiro Hamajic8dea2a2015-04-28 17:15:30 +0900409 case "varsubst":
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900410 varname, err := deserializeVar(sv.Children[0])
411 if err != nil {
412 return nil, err
Shinichiro Hamajic8dea2a2015-04-28 17:15:30 +0900413 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900414 pat, err := deserializeVar(sv.Children[1])
415 if err != nil {
416 return nil, err
417 }
418 subst, err := deserializeVar(sv.Children[2])
419 if err != nil {
420 return nil, err
421 }
422 return varsubst{
423 varname: varname,
424 pat: pat,
425 subst: subst,
Fumitoshi Ukaibbb0db52015-06-30 16:51:27 +0900426 paren: sv.V[0],
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900427 }, nil
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900428
429 case "func":
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900430 dv, err := deserializeVar(sv.Children[0])
431 if err != nil {
432 return nil, err
433 }
434 name, ok := dv.(literal)
435 if !ok {
436 return nil, fmt.Errorf("func name is not literal %s: %T", dv, dv)
437 }
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900438 f := funcMap[string(name[1:])]()
439 f.AddArg(name)
440 for _, a := range sv.Children[1:] {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900441 dv, err := deserializeVar(a)
442 if err != nil {
443 return nil, err
444 }
445 f.AddArg(dv)
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900446 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900447 return f, nil
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900448 case "funcEvalAssign":
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900449 rhs, err := deserializeVar(sv.Children[2])
450 if err != nil {
451 return nil, err
452 }
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900453 return &funcEvalAssign{
454 lhs: sv.Children[0].V,
Shinichiro Hamaji3d6d0aa2015-04-28 16:18:44 +0900455 op: sv.Children[1].V,
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900456 rhs: rhs,
457 }, nil
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900458 case "funcNop":
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900459 return &funcNop{expr: sv.V}, nil
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900460
461 case "simple":
Fumitoshi Ukai7bf992d2015-06-25 12:42:19 +0900462 return &simpleVar{
Fumitoshi Ukai7655f182015-07-15 14:05:41 +0900463 value: strings.Split(sv.V, " "),
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900464 origin: sv.Origin,
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900465 }, nil
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900466 case "recursive":
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900467 expr, err := deserializeSingleChild(sv)
468 if err != nil {
469 return nil, err
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900470 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900471 return &recursiveVar{
472 expr: expr,
473 origin: sv.Origin,
474 }, nil
Shinichiro Hamajif8f075c2015-04-28 04:25:37 +0900475
476 case ":=", "=", "+=", "?=":
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900477 dv, err := deserializeSingleChild(sv)
478 if err != nil {
479 return nil, err
Shinichiro Hamajif8f075c2015-04-28 04:25:37 +0900480 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900481 v, ok := dv.(Var)
482 if !ok {
483 return nil, fmt.Errorf("not var: target specific var %s %T", dv, dv)
484 }
485 return &targetSpecificVar{
486 v: v,
487 op: sv.Type,
488 }, nil
Shinichiro Hamajif8f075c2015-04-28 04:25:37 +0900489
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900490 default:
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900491 return nil, fmt.Errorf("unknown serialized variable type: %q", sv)
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900492 }
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900493}
494
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900495func deserializeVars(vars map[string]serializableVar) (Vars, error) {
Shinichiro Hamaji79a56932015-04-28 03:53:57 +0900496 r := make(Vars)
497 for k, v := range vars {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900498 dv, err := deserializeVar(v)
499 if err != nil {
500 return nil, err
501 }
502 vv, ok := dv.(Var)
503 if !ok {
504 return nil, fmt.Errorf("not var: %s: %T", dv, dv)
505 }
506 r[k] = vv
Shinichiro Hamaji79a56932015-04-28 03:53:57 +0900507 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900508 return r, nil
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900509}
510
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900511func deserializeNodes(g serializableGraph) (r []*DepNode, err error) {
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900512 nodes := g.Nodes
513 tsvs := g.Tsvs
514 targets := g.Targets
Shinichiro Hamaji7a65e682015-04-28 18:00:12 +0900515 // Deserialize all TSVs first so that multiple rules can share memory.
516 var tsvValues []Var
517 for _, sv := range tsvs {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900518 dv, err := deserializeVar(sv.Value)
519 if err != nil {
520 return nil, err
521 }
522 vv, ok := dv.(Var)
523 if !ok {
524 return nil, fmt.Errorf("not var: %s %T", dv, dv)
525 }
526 tsvValues = append(tsvValues, vv)
Shinichiro Hamaji7a65e682015-04-28 18:00:12 +0900527 }
528
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900529 nodeMap := make(map[string]*DepNode)
530 for _, n := range nodes {
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900531 var actualInputs []string
532 for _, i := range n.ActualInputs {
533 actualInputs = append(actualInputs, targets[i])
534 }
535
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900536 d := &DepNode{
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900537 Output: targets[n.Output],
Shinichiro Hamaji3d6d0aa2015-04-28 16:18:44 +0900538 Cmds: n.Cmds,
539 HasRule: n.HasRule,
Shinichiro Hamaji3d6d0aa2015-04-28 16:18:44 +0900540 IsPhony: n.IsPhony,
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900541 ActualInputs: actualInputs,
Shinichiro Hamaji3d6d0aa2015-04-28 16:18:44 +0900542 Filename: n.Filename,
543 Lineno: n.Lineno,
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900544 TargetSpecificVars: make(Vars),
545 }
546
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900547 for _, id := range n.TargetSpecificVars {
548 sv := tsvs[id]
Shinichiro Hamaji7a65e682015-04-28 18:00:12 +0900549 d.TargetSpecificVars[sv.Name] = tsvValues[id]
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900550 }
551
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900552 nodeMap[targets[n.Output]] = d
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900553 r = append(r, d)
554 }
555
556 for _, n := range nodes {
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900557 d := nodeMap[targets[n.Output]]
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900558 for _, o := range n.Deps {
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900559 c, present := nodeMap[targets[o]]
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900560 if !present {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900561 return nil, fmt.Errorf("unknown target: %d (%s)", o, targets[o])
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900562 }
563 d.Deps = append(d.Deps, c)
564 }
Fumitoshi Ukaic916ea22015-06-30 09:52:13 +0900565 for _, o := range n.OrderOnlys {
566 c, present := nodeMap[targets[o]]
567 if !present {
568 return nil, fmt.Errorf("unknown target: %d (%s)", o, targets[o])
569 }
570 d.OrderOnlys = append(d.OrderOnlys, c)
571 }
Shinichiro Hamaji744b1392015-05-14 23:29:14 +0900572 for _, o := range n.Parents {
573 c, present := nodeMap[targets[o]]
574 if !present {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900575 return nil, fmt.Errorf("unknown target: %d (%s)", o, targets[o])
Shinichiro Hamaji744b1392015-05-14 23:29:14 +0900576 }
577 d.Parents = append(d.Parents, c)
578 }
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900579 }
580
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900581 return r, nil
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900582}
583
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900584func human(n int) string {
Shinichiro Hamaji744b1392015-05-14 23:29:14 +0900585 if n >= 10*1000*1000*1000 {
586 return fmt.Sprintf("%.2fGB", float32(n)/1000/1000/1000)
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900587 }
Fumitoshi Ukai936de102015-06-08 11:21:16 +0900588 if n >= 10*1000*1000 {
589 return fmt.Sprintf("%.2fMB", float32(n)/1000/1000)
590 }
591 if n >= 10*1000 {
592 return fmt.Sprintf("%.2fkB", float32(n)/1000)
593 }
594 return fmt.Sprintf("%dB", n)
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900595}
596
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900597func showSerializedNodesStats(nodes []*serializableDepNode) {
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900598 outputSize := 0
599 cmdSize := 0
600 depsSize := 0
Fumitoshi Ukaic916ea22015-06-30 09:52:13 +0900601 orderOnlysSize := 0
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900602 actualInputSize := 0
603 tsvSize := 0
604 filenameSize := 0
605 linenoSize := 0
606 for _, n := range nodes {
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900607 outputSize += 4
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900608 for _, c := range n.Cmds {
609 cmdSize += len(c)
610 }
Fumitoshi Ukaic916ea22015-06-30 09:52:13 +0900611 depsSize += 4 * len(n.Deps)
612 orderOnlysSize += 4 * len(n.OrderOnlys)
613 actualInputSize += 4 * len(n.ActualInputs)
614 tsvSize += 4 * len(n.TargetSpecificVars)
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900615 filenameSize += len(n.Filename)
616 linenoSize += 4
617 }
Fumitoshi Ukaic916ea22015-06-30 09:52:13 +0900618 size := outputSize + cmdSize + depsSize + orderOnlysSize + actualInputSize + tsvSize + filenameSize + linenoSize
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900619 logStats("%d nodes %s", len(nodes), human(size))
620 logStats(" output %s", human(outputSize))
621 logStats(" command %s", human(cmdSize))
622 logStats(" deps %s", human(depsSize))
Fumitoshi Ukaic916ea22015-06-30 09:52:13 +0900623 logStats(" orderonlys %s", human(orderOnlysSize))
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900624 logStats(" inputs %s", human(actualInputSize))
625 logStats(" tsv %s", human(tsvSize))
626 logStats(" filename %s", human(filenameSize))
627 logStats(" lineno %s", human(linenoSize))
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900628}
629
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900630func (v serializableVar) size() int {
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900631 size := 0
632 size += len(v.Type)
633 size += len(v.V)
634 size += len(v.Origin)
635 for _, c := range v.Children {
636 size += c.size()
637 }
638 return size
639}
640
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900641func showSerializedVarsStats(vars map[string]serializableVar) {
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900642 nameSize := 0
643 valueSize := 0
644 for k, v := range vars {
645 nameSize += len(k)
646 valueSize += v.size()
647 }
648 size := nameSize + valueSize
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900649 logStats("%d vars %s", len(vars), human(size))
650 logStats(" name %s", human(nameSize))
651 logStats(" value %s", human(valueSize))
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900652}
653
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900654func showSerializedTsvsStats(vars []serializableTargetSpecificVar) {
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900655 nameSize := 0
656 valueSize := 0
657 for _, v := range vars {
658 nameSize += len(v.Name)
659 valueSize += v.Value.size()
660 }
661 size := nameSize + valueSize
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900662 logStats("%d tsvs %s", len(vars), human(size))
663 logStats(" name %s", human(nameSize))
664 logStats(" value %s", human(valueSize))
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900665}
666
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900667func showSerializedTargetsStats(targets []string) {
668 size := 0
669 for _, t := range targets {
670 size += len(t)
671 }
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900672 logStats("%d targets %s", len(targets), human(size))
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900673}
674
Fumitoshi Ukai0af44522015-06-25 15:26:08 +0900675func showSerializedAccessedMksStats(accessedMks []*accessedMakefile) {
Shinichiro Hamaji006adbf2015-05-25 18:42:12 +0900676 size := 0
Fumitoshi Ukai0af44522015-06-25 15:26:08 +0900677 for _, rm := range accessedMks {
Shinichiro Hamaji4220be32015-05-26 13:30:18 +0900678 size += len(rm.Filename) + len(rm.Hash) + 4
Shinichiro Hamaji006adbf2015-05-25 18:42:12 +0900679 }
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900680 logStats("%d makefiles %s", len(accessedMks), human(size))
Shinichiro Hamaji006adbf2015-05-25 18:42:12 +0900681}
682
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900683func showSerializedGraphStats(g serializableGraph) {
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900684 showSerializedNodesStats(g.Nodes)
685 showSerializedVarsStats(g.Vars)
686 showSerializedTsvsStats(g.Tsvs)
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900687 showSerializedTargetsStats(g.Targets)
Fumitoshi Ukai0af44522015-06-25 15:26:08 +0900688 showSerializedAccessedMksStats(g.AccessedMks)
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900689}
690
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900691func deserializeGraph(g serializableGraph) (*DepGraph, error) {
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +0900692 if StatsFlag {
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900693 showSerializedGraphStats(g)
694 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900695 nodes, err := deserializeNodes(g)
696 if err != nil {
697 return nil, err
698 }
699 vars, err := deserializeVars(g.Vars)
700 if err != nil {
701 return nil, err
702 }
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900703 return &DepGraph{
Fumitoshi Ukai0af44522015-06-25 15:26:08 +0900704 nodes: nodes,
705 vars: vars,
706 accessedMks: g.AccessedMks,
707 exports: g.Exports,
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900708 }, nil
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900709}
710
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +0900711func (jsonLoadSaver) Load(filename string) (*DepGraph, error) {
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900712 startTime := time.Now()
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900713 f, err := os.Open(filename)
714 if err != nil {
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +0900715 return nil, err
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900716 }
Fumitoshi Ukaied9a6152015-06-02 15:28:55 +0900717 defer f.Close()
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900718
719 d := json.NewDecoder(f)
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900720 g := serializableGraph{Vars: make(map[string]serializableVar)}
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900721 err = d.Decode(&g)
722 if err != nil {
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +0900723 return nil, err
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900724 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900725 dg, err := deserializeGraph(g)
726 if err != nil {
727 return nil, err
728 }
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900729 logStats("gob deserialize time: %q", time.Since(startTime))
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +0900730 return dg, nil
Shinichiro Hamaji1833c282015-04-28 05:02:27 +0900731}
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900732
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +0900733func (gobLoadSaver) Load(filename string) (*DepGraph, error) {
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900734 startTime := time.Now()
Shinichiro Hamaji1833c282015-04-28 05:02:27 +0900735 f, err := os.Open(filename)
736 if err != nil {
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +0900737 return nil, err
Shinichiro Hamaji1833c282015-04-28 05:02:27 +0900738 }
Fumitoshi Ukaied9a6152015-06-02 15:28:55 +0900739 defer f.Close()
Shinichiro Hamaji1833c282015-04-28 05:02:27 +0900740
741 d := gob.NewDecoder(f)
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900742 g := serializableGraph{Vars: make(map[string]serializableVar)}
Shinichiro Hamaji1833c282015-04-28 05:02:27 +0900743 err = d.Decode(&g)
744 if err != nil {
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +0900745 return nil, err
Shinichiro Hamaji1833c282015-04-28 05:02:27 +0900746 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900747 dg, err := deserializeGraph(g)
748 if err != nil {
749 return nil, err
750 }
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900751 logStats("json deserialize time: %q", time.Since(startTime))
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +0900752 return dg, nil
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900753}
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900754
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900755func loadCache(makefile string, roots []string) (*DepGraph, error) {
Shinichiro Hamaji82ecff92015-05-25 18:36:04 +0900756 startTime := time.Now()
757 defer func() {
Fumitoshi Ukai49599e52015-06-26 10:10:24 +0900758 logStats("Cache lookup time: %q", time.Since(startTime))
Shinichiro Hamaji82ecff92015-05-25 18:36:04 +0900759 }()
760
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900761 filename := cacheFilename(makefile, roots)
Shinichiro Hamaji39e62402015-05-20 19:34:58 +0900762 if !exists(filename) {
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +0900763 glog.Warningf("Cache not found %q", filename)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900764 return nil, fmt.Errorf("cache not found: %s", filename)
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900765 }
Shinichiro Hamaji39e62402015-05-20 19:34:58 +0900766
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +0900767 g, err := GOB.Load(filename)
768 if err != nil {
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +0900769 glog.Warning("Cache load error %q: %v", filename, err)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900770 return nil, err
Fumitoshi Ukai4bb4cd52015-06-25 18:07:21 +0900771 }
Fumitoshi Ukai0af44522015-06-25 15:26:08 +0900772 for _, mk := range g.accessedMks {
773 if mk.State != fileExists && mk.State != fileNotExists {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900774 return nil, fmt.Errorf("internal error: broken state: %d", mk.State)
Shinichiro Hamaji0ba75a92015-05-20 19:42:43 +0900775 }
Fumitoshi Ukai0af44522015-06-25 15:26:08 +0900776 if mk.State == fileNotExists {
Shinichiro Hamaji45cde1d2015-05-25 18:21:23 +0900777 if exists(mk.Filename) {
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +0900778 glog.Infof("Cache expired: %s", mk.Filename)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900779 return nil, fmt.Errorf("cache expired: %s", mk.Filename)
Shinichiro Hamaji45cde1d2015-05-25 18:21:23 +0900780 }
781 } else {
Fumitoshi Ukaibc40a462015-06-02 15:51:16 +0900782 c, err := ioutil.ReadFile(mk.Filename)
Shinichiro Hamaji4220be32015-05-26 13:30:18 +0900783 if err != nil {
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +0900784 glog.Infof("Cache expired: %s", mk.Filename)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900785 return nil, fmt.Errorf("cache expired: %s", mk.Filename)
Shinichiro Hamaji4220be32015-05-26 13:30:18 +0900786 }
787 h := sha1.Sum(c)
788 if !bytes.Equal(h[:], mk.Hash[:]) {
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +0900789 glog.Infof("Cache expired: %s", mk.Filename)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900790 return nil, fmt.Errorf("cache expired: %s", mk.Filename)
Shinichiro Hamaji45cde1d2015-05-25 18:21:23 +0900791 }
Shinichiro Hamaji39e62402015-05-20 19:34:58 +0900792 }
793 }
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +0900794 glog.Info("Cache found in %q", filename)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900795 return g, nil
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900796}