blob: d9f2d94bf79e3d657b77db2cc0eef0707e0fed6e [file] [log] [blame]
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +09001package main
2
3import (
Shinichiro Hamaji530136b2015-04-28 17:12:48 +09004 "bytes"
Shinichiro Hamaji4220be32015-05-26 13:30:18 +09005 "crypto/sha1"
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +09006 "encoding/binary"
Shinichiro Hamaji1833c282015-04-28 05:02:27 +09007 "encoding/gob"
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +09008 "encoding/json"
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +09009 "fmt"
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +090010 "io"
Fumitoshi Ukaibc40a462015-06-02 15:51:16 +090011 "io/ioutil"
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +090012 "net/url"
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +090013 "os"
Shinichiro Hamaji530136b2015-04-28 17:12:48 +090014 "sort"
Shinichiro Hamajie666ac82015-04-28 04:18:13 +090015 "strconv"
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +090016 "time"
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +090017)
18
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +090019const (
Fumitoshi Ukai936de102015-06-08 11:21:16 +090020 ValueTypeRecursive = 'R'
21 ValueTypeSimple = 'S'
22 ValueTypeTSV = 'T'
23 ValueTypeUndefined = 'U'
24 ValueTypeAssign = 'a'
25 ValueTypeExpr = 'e'
26 ValueTypeFunc = 'f'
27 ValueTypeLiteral = 'l'
28 ValueTypeNop = 'n'
29 ValueTypeParamref = 'p'
30 ValueTypeVarref = 'r'
31 ValueTypeVarsubst = 's'
32 ValueTypeTmpval = 't'
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +090033)
34
35func dumpData(w io.Writer, data []byte) {
36 for len(data) != 0 {
37 written, err := w.Write(data)
38 if err == io.EOF {
39 return
40 }
41 if err != nil {
42 panic(err)
43 }
44 data = data[written:]
45 }
46}
47
48func dumpInt(w io.Writer, i int) {
49 v := int32(i)
50 binary.Write(w, binary.LittleEndian, &v)
51}
52
53func dumpString(w io.Writer, s string) {
54 dumpInt(w, len(s))
55 dumpData(w, []byte(s))
56}
57
58func dumpBytes(w io.Writer, b []byte) {
59 dumpInt(w, len(b))
60 dumpData(w, b)
61}
62
63func dumpByte(w io.Writer, b byte) {
64 w.Write([]byte{b})
65}
66
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +090067type SerializableVar struct {
68 Type string
69 V string
70 Origin string
71 Children []SerializableVar
72}
73
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +090074type SerializableDepNode struct {
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +090075 Output int
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +090076 Cmds []string
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +090077 Deps []int
Shinichiro Hamaji744b1392015-05-14 23:29:14 +090078 Parents []int
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +090079 HasRule bool
80 IsOrderOnly bool
81 IsPhony bool
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +090082 ActualInputs []int
Shinichiro Hamaji530136b2015-04-28 17:12:48 +090083 TargetSpecificVars []int
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +090084 Filename string
85 Lineno int
86}
87
Shinichiro Hamaji530136b2015-04-28 17:12:48 +090088type SerializableTargetSpecificVar struct {
89 Name string
90 Value SerializableVar
91}
92
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +090093type SerializableGraph struct {
Shinichiro Hamajif3ea5d02015-05-20 17:13:00 +090094 Nodes []*SerializableDepNode
95 Vars map[string]SerializableVar
96 Tsvs []SerializableTargetSpecificVar
97 Targets []string
98 Roots []string
Shinichiro Hamaji45cde1d2015-05-25 18:21:23 +090099 ReadMks []*ReadMakefile
Shinichiro Hamaji98500372015-05-29 17:05:43 +0900100 Exports map[string]bool
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900101}
102
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900103func encGob(v interface{}) string {
104 var buf bytes.Buffer
105 e := gob.NewEncoder(&buf)
106 err := e.Encode(v)
107 if err != nil {
108 panic(err)
109 }
110 return buf.String()
111}
112
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +0900113func encVar(k string, v Var) string {
114 var buf bytes.Buffer
115 dumpString(&buf, k)
116 v.Dump(&buf)
117 return buf.String()
118}
119
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900120type DepNodesSerializer struct {
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900121 nodes []*SerializableDepNode
122 tsvs []SerializableTargetSpecificVar
123 tsvMap map[string]int
124 targets []string
125 targetMap map[string]int
126 done map[string]bool
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900127}
128
129func NewDepNodesSerializer() *DepNodesSerializer {
130 return &DepNodesSerializer{
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900131 tsvMap: make(map[string]int),
132 targetMap: make(map[string]int),
133 done: make(map[string]bool),
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900134 }
135}
136
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900137func (ns *DepNodesSerializer) SerializeTarget(t string) int {
138 id, present := ns.targetMap[t]
139 if present {
140 return id
141 }
142 id = len(ns.targets)
143 ns.targetMap[t] = id
144 ns.targets = append(ns.targets, t)
145 return id
146}
147
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900148func (ns *DepNodesSerializer) SerializeDepNodes(nodes []*DepNode) {
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900149 for _, n := range nodes {
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900150 if ns.done[n.Output] {
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900151 continue
152 }
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900153 ns.done[n.Output] = true
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900154
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900155 var deps []int
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900156 for _, d := range n.Deps {
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900157 deps = append(deps, ns.SerializeTarget(d.Output))
158 }
Shinichiro Hamaji744b1392015-05-14 23:29:14 +0900159 var parents []int
160 for _, d := range n.Parents {
161 parents = append(parents, ns.SerializeTarget(d.Output))
162 }
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900163 var actualInputs []int
164 for _, i := range n.ActualInputs {
165 actualInputs = append(actualInputs, ns.SerializeTarget(i))
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900166 }
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900167
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900168 // Sort keys for consistent serialization.
169 var tsvKeys []string
170 for k := range n.TargetSpecificVars {
171 tsvKeys = append(tsvKeys, k)
172 }
173 sort.Strings(tsvKeys)
174
175 var vars []int
176 for _, k := range tsvKeys {
177 v := n.TargetSpecificVars[k]
178 sv := SerializableTargetSpecificVar{Name: k, Value: v.Serialize()}
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +0900179 //gob := encGob(sv)
180 gob := encVar(k, v)
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900181 id, present := ns.tsvMap[gob]
182 if !present {
183 id = len(ns.tsvs)
184 ns.tsvMap[gob] = id
185 ns.tsvs = append(ns.tsvs, sv)
186 }
187 vars = append(vars, id)
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900188 }
189
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900190 ns.nodes = append(ns.nodes, &SerializableDepNode{
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900191 Output: ns.SerializeTarget(n.Output),
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900192 Cmds: n.Cmds,
193 Deps: deps,
Shinichiro Hamaji744b1392015-05-14 23:29:14 +0900194 Parents: parents,
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900195 HasRule: n.HasRule,
196 IsOrderOnly: n.IsOrderOnly,
197 IsPhony: n.IsPhony,
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900198 ActualInputs: actualInputs,
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900199 TargetSpecificVars: vars,
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900200 Filename: n.Filename,
201 Lineno: n.Lineno,
202 })
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900203 ns.SerializeDepNodes(n.Deps)
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900204 }
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900205}
206
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900207func MakeSerializableVars(vars Vars) (r map[string]SerializableVar) {
208 r = make(map[string]SerializableVar)
209 for k, v := range vars {
210 r[k] = v.Serialize()
211 }
212 return r
213}
214
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900215func MakeSerializableGraph(g *DepGraph, roots []string) SerializableGraph {
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900216 ns := NewDepNodesSerializer()
Shinichiro Hamaji750ae2e2015-05-20 12:59:15 +0900217 ns.SerializeDepNodes(g.nodes)
218 v := MakeSerializableVars(g.vars)
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900219 return SerializableGraph{
Shinichiro Hamajif3ea5d02015-05-20 17:13:00 +0900220 Nodes: ns.nodes,
221 Vars: v,
222 Tsvs: ns.tsvs,
223 Targets: ns.targets,
224 Roots: roots,
225 ReadMks: g.readMks,
Shinichiro Hamaji98500372015-05-29 17:05:43 +0900226 Exports: g.exports,
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900227 }
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900228}
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900229
Fumitoshi Ukai936de102015-06-08 11:21:16 +0900230func DumpDepGraphAsJSON(g *DepGraph, filename string, roots []string) {
Shinichiro Hamaji750ae2e2015-05-20 12:59:15 +0900231 sg := MakeSerializableGraph(g, roots)
232 o, err := json.MarshalIndent(sg, " ", " ")
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900233 if err != nil {
234 panic(err)
235 }
236 f, err2 := os.Create(filename)
237 if err2 != nil {
238 panic(err2)
239 }
240 f.Write(o)
Fumitoshi Ukaied9a6152015-06-02 15:28:55 +0900241 err = f.Close()
242 if err != nil {
243 panic(err)
244 }
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900245}
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900246
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900247func DumpDepGraph(g *DepGraph, filename string, roots []string) {
Shinichiro Hamaji1833c282015-04-28 05:02:27 +0900248 f, err := os.Create(filename)
249 if err != nil {
250 panic(err)
251 }
252 e := gob.NewEncoder(f)
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +0900253 startTime := time.Now()
Shinichiro Hamaji750ae2e2015-05-20 12:59:15 +0900254 sg := MakeSerializableGraph(g, roots)
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +0900255 LogStats("serialize prepare time: %q", time.Now().Sub(startTime))
256 startTime = time.Now()
Shinichiro Hamaji750ae2e2015-05-20 12:59:15 +0900257 e.Encode(sg)
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +0900258 LogStats("serialize output time: %q", time.Now().Sub(startTime))
Fumitoshi Ukaied9a6152015-06-02 15:28:55 +0900259 err = f.Close()
260 if err != nil {
261 panic(err)
262 }
Shinichiro Hamaji1833c282015-04-28 05:02:27 +0900263}
264
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900265func GetCacheFilename(mk string, roots []string) string {
266 filename := ".kati_cache." + mk
267 for _, r := range roots {
268 filename += "." + r
269 }
270 return url.QueryEscape(filename)
271}
272
273func DumpDepGraphCache(g *DepGraph, roots []string) {
274 if len(g.readMks) == 0 {
275 panic("No Makefile is read")
276 }
Shinichiro Hamajif3ea5d02015-05-20 17:13:00 +0900277 cacheFile := GetCacheFilename(g.readMks[0].Filename, roots)
278 for _, mk := range g.readMks {
279 // Inconsistent, do not dump this result.
Shinichiro Hamaji45cde1d2015-05-25 18:21:23 +0900280 if mk.State == 2 {
Shinichiro Hamajif3ea5d02015-05-20 17:13:00 +0900281 if exists(cacheFile) {
282 os.Remove(cacheFile)
283 }
284 return
285 }
286 }
287 DumpDepGraph(g, cacheFile, roots)
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900288}
289
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900290func DeserializeSingleChild(sv SerializableVar) Value {
291 if len(sv.Children) != 1 {
292 panic(fmt.Sprintf("unexpected number of children: %q", sv))
293 }
294 return DeserializeVar(sv.Children[0])
295}
296
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900297func DeserializeVar(sv SerializableVar) (r Value) {
298 switch sv.Type {
299 case "literal":
300 return literal(sv.V)
Shinichiro Hamajic8dea2a2015-04-28 17:15:30 +0900301 case "tmpval":
302 return tmpval([]byte(sv.V))
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900303 case "expr":
304 var e Expr
305 for _, v := range sv.Children {
306 e = append(e, DeserializeVar(v))
307 }
308 return e
309 case "varref":
Shinichiro Hamaji3d6d0aa2015-04-28 16:18:44 +0900310 return varref{varname: DeserializeSingleChild(sv)}
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900311 case "paramref":
312 v, err := strconv.Atoi(sv.V)
313 if err != nil {
314 panic(err)
315 }
316 return paramref(v)
Shinichiro Hamajic8dea2a2015-04-28 17:15:30 +0900317 case "varsubst":
318 return varsubst{
319 varname: DeserializeVar(sv.Children[0]),
320 pat: DeserializeVar(sv.Children[1]),
321 subst: DeserializeVar(sv.Children[2]),
322 }
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900323
324 case "func":
325 name := DeserializeVar(sv.Children[0]).(literal)
326 f := funcMap[string(name[1:])]()
327 f.AddArg(name)
328 for _, a := range sv.Children[1:] {
329 f.AddArg(DeserializeVar(a))
330 }
331 return f
332 case "funcEvalAssign":
333 return &funcEvalAssign{
334 lhs: sv.Children[0].V,
Shinichiro Hamaji3d6d0aa2015-04-28 16:18:44 +0900335 op: sv.Children[1].V,
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900336 rhs: DeserializeVar(sv.Children[2]),
337 }
338 case "funcNop":
Shinichiro Hamaji3d6d0aa2015-04-28 16:18:44 +0900339 return &funcNop{expr: sv.V}
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900340
341 case "simple":
342 return SimpleVar{
Shinichiro Hamaji3d6d0aa2015-04-28 16:18:44 +0900343 value: []byte(sv.V),
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900344 origin: sv.Origin,
345 }
346 case "recursive":
347 return RecursiveVar{
Shinichiro Hamaji3d6d0aa2015-04-28 16:18:44 +0900348 expr: DeserializeSingleChild(sv),
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900349 origin: sv.Origin,
350 }
Shinichiro Hamajif8f075c2015-04-28 04:25:37 +0900351
352 case ":=", "=", "+=", "?=":
353 return TargetSpecificVar{
Shinichiro Hamaji3d6d0aa2015-04-28 16:18:44 +0900354 v: DeserializeSingleChild(sv).(Var),
Shinichiro Hamajif8f075c2015-04-28 04:25:37 +0900355 op: sv.Type,
356 }
357
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900358 default:
359 panic(fmt.Sprintf("unknown serialized variable type: %q", sv))
360 }
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900361}
362
Shinichiro Hamaji3d6d0aa2015-04-28 16:18:44 +0900363func DeserializeVars(vars map[string]SerializableVar) Vars {
Shinichiro Hamaji79a56932015-04-28 03:53:57 +0900364 r := make(Vars)
365 for k, v := range vars {
366 r[k] = DeserializeVar(v).(Var)
367 }
368 return r
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900369}
370
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900371func DeserializeNodes(g SerializableGraph) (r []*DepNode) {
372 nodes := g.Nodes
373 tsvs := g.Tsvs
374 targets := g.Targets
Shinichiro Hamaji7a65e682015-04-28 18:00:12 +0900375 // Deserialize all TSVs first so that multiple rules can share memory.
376 var tsvValues []Var
377 for _, sv := range tsvs {
378 tsvValues = append(tsvValues, DeserializeVar(sv.Value).(Var))
379 }
380
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900381 nodeMap := make(map[string]*DepNode)
382 for _, n := range nodes {
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900383 var actualInputs []string
384 for _, i := range n.ActualInputs {
385 actualInputs = append(actualInputs, targets[i])
386 }
387
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900388 d := &DepNode{
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900389 Output: targets[n.Output],
Shinichiro Hamaji3d6d0aa2015-04-28 16:18:44 +0900390 Cmds: n.Cmds,
391 HasRule: n.HasRule,
392 IsOrderOnly: n.IsOrderOnly,
393 IsPhony: n.IsPhony,
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900394 ActualInputs: actualInputs,
Shinichiro Hamaji3d6d0aa2015-04-28 16:18:44 +0900395 Filename: n.Filename,
396 Lineno: n.Lineno,
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900397 TargetSpecificVars: make(Vars),
398 }
399
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900400 for _, id := range n.TargetSpecificVars {
401 sv := tsvs[id]
Shinichiro Hamaji7a65e682015-04-28 18:00:12 +0900402 d.TargetSpecificVars[sv.Name] = tsvValues[id]
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900403 }
404
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900405 nodeMap[targets[n.Output]] = d
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900406 r = append(r, d)
407 }
408
409 for _, n := range nodes {
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900410 d := nodeMap[targets[n.Output]]
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900411 for _, o := range n.Deps {
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900412 c, present := nodeMap[targets[o]]
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900413 if !present {
Fumitoshi Ukai36c510b2015-06-08 10:21:13 +0900414 panic(fmt.Sprintf("unknown target: %d (%s)", o, targets[o]))
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900415 }
416 d.Deps = append(d.Deps, c)
417 }
Shinichiro Hamaji744b1392015-05-14 23:29:14 +0900418 for _, o := range n.Parents {
419 c, present := nodeMap[targets[o]]
420 if !present {
Fumitoshi Ukai36c510b2015-06-08 10:21:13 +0900421 panic(fmt.Sprintf("unknown target: %d (%s)", o, targets[o]))
Shinichiro Hamaji744b1392015-05-14 23:29:14 +0900422 }
423 d.Parents = append(d.Parents, c)
424 }
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900425 }
426
427 return r
428}
429
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900430func human(n int) string {
Shinichiro Hamaji744b1392015-05-14 23:29:14 +0900431 if n >= 10*1000*1000*1000 {
432 return fmt.Sprintf("%.2fGB", float32(n)/1000/1000/1000)
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900433 }
Fumitoshi Ukai936de102015-06-08 11:21:16 +0900434 if n >= 10*1000*1000 {
435 return fmt.Sprintf("%.2fMB", float32(n)/1000/1000)
436 }
437 if n >= 10*1000 {
438 return fmt.Sprintf("%.2fkB", float32(n)/1000)
439 }
440 return fmt.Sprintf("%dB", n)
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900441}
442
443func showSerializedNodesStats(nodes []*SerializableDepNode) {
444 outputSize := 0
445 cmdSize := 0
446 depsSize := 0
447 actualInputSize := 0
448 tsvSize := 0
449 filenameSize := 0
450 linenoSize := 0
451 for _, n := range nodes {
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900452 outputSize += 4
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900453 for _, c := range n.Cmds {
454 cmdSize += len(c)
455 }
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900456 for _ = range n.Deps {
457 depsSize += 4
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900458 }
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900459 for _ = range n.ActualInputs {
460 actualInputSize += 4
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900461 }
462 for _ = range n.TargetSpecificVars {
463 tsvSize += 4
464 }
465 filenameSize += len(n.Filename)
466 linenoSize += 4
467 }
468 size := outputSize + cmdSize + depsSize + actualInputSize + tsvSize + filenameSize + linenoSize
469 LogStats("%d nodes %s", len(nodes), human(size))
470 LogStats(" output %s", human(outputSize))
471 LogStats(" command %s", human(cmdSize))
472 LogStats(" deps %s", human(depsSize))
473 LogStats(" inputs %s", human(actualInputSize))
474 LogStats(" tsv %s", human(tsvSize))
475 LogStats(" filename %s", human(filenameSize))
476 LogStats(" lineno %s", human(linenoSize))
477}
478
479func (v SerializableVar) size() int {
480 size := 0
481 size += len(v.Type)
482 size += len(v.V)
483 size += len(v.Origin)
484 for _, c := range v.Children {
485 size += c.size()
486 }
487 return size
488}
489
490func showSerializedVarsStats(vars map[string]SerializableVar) {
491 nameSize := 0
492 valueSize := 0
493 for k, v := range vars {
494 nameSize += len(k)
495 valueSize += v.size()
496 }
497 size := nameSize + valueSize
498 LogStats("%d vars %s", len(vars), human(size))
499 LogStats(" name %s", human(nameSize))
500 LogStats(" value %s", human(valueSize))
501}
502
503func showSerializedTsvsStats(vars []SerializableTargetSpecificVar) {
504 nameSize := 0
505 valueSize := 0
506 for _, v := range vars {
507 nameSize += len(v.Name)
508 valueSize += v.Value.size()
509 }
510 size := nameSize + valueSize
511 LogStats("%d tsvs %s", len(vars), human(size))
512 LogStats(" name %s", human(nameSize))
513 LogStats(" value %s", human(valueSize))
514}
515
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900516func showSerializedTargetsStats(targets []string) {
517 size := 0
518 for _, t := range targets {
519 size += len(t)
520 }
521 LogStats("%d targets %s", len(targets), human(size))
522}
523
Shinichiro Hamaji006adbf2015-05-25 18:42:12 +0900524func showSerializedReadMksStats(readMks []*ReadMakefile) {
525 size := 0
526 for _, rm := range readMks {
Shinichiro Hamaji4220be32015-05-26 13:30:18 +0900527 size += len(rm.Filename) + len(rm.Hash) + 4
Shinichiro Hamaji006adbf2015-05-25 18:42:12 +0900528 }
529 LogStats("%d makefiles %s", len(readMks), human(size))
530}
531
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900532func showSerializedGraphStats(g SerializableGraph) {
533 showSerializedNodesStats(g.Nodes)
534 showSerializedVarsStats(g.Vars)
535 showSerializedTsvsStats(g.Tsvs)
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900536 showSerializedTargetsStats(g.Targets)
Shinichiro Hamaji006adbf2015-05-25 18:42:12 +0900537 showSerializedReadMksStats(g.ReadMks)
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900538}
539
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900540func DeserializeGraph(g SerializableGraph) *DepGraph {
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900541 if katiLogFlag || katiStatsFlag {
542 showSerializedGraphStats(g)
543 }
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900544 nodes := DeserializeNodes(g)
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900545 vars := DeserializeVars(g.Vars)
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900546 return &DepGraph{
Shinichiro Hamajif3ea5d02015-05-20 17:13:00 +0900547 nodes: nodes,
548 vars: vars,
549 readMks: g.ReadMks,
Shinichiro Hamaji98500372015-05-29 17:05:43 +0900550 exports: g.Exports,
Shinichiro Hamaji750ae2e2015-05-20 12:59:15 +0900551 }
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900552}
553
Fumitoshi Ukai936de102015-06-08 11:21:16 +0900554func LoadDepGraphFromJSON(filename string) *DepGraph {
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900555 f, err := os.Open(filename)
556 if err != nil {
557 panic(err)
558 }
Fumitoshi Ukaied9a6152015-06-02 15:28:55 +0900559 defer f.Close()
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900560
561 d := json.NewDecoder(f)
Shinichiro Hamaji3d6d0aa2015-04-28 16:18:44 +0900562 g := SerializableGraph{Vars: make(map[string]SerializableVar)}
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900563 err = d.Decode(&g)
564 if err != nil {
565 panic(err)
566 }
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900567 return DeserializeGraph(g)
Shinichiro Hamaji1833c282015-04-28 05:02:27 +0900568}
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900569
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900570func LoadDepGraph(filename string) *DepGraph {
Shinichiro Hamaji1833c282015-04-28 05:02:27 +0900571 f, err := os.Open(filename)
572 if err != nil {
573 panic(err)
574 }
Fumitoshi Ukaied9a6152015-06-02 15:28:55 +0900575 defer f.Close()
Shinichiro Hamaji1833c282015-04-28 05:02:27 +0900576
577 d := gob.NewDecoder(f)
Shinichiro Hamaji3d6d0aa2015-04-28 16:18:44 +0900578 g := SerializableGraph{Vars: make(map[string]SerializableVar)}
Shinichiro Hamaji1833c282015-04-28 05:02:27 +0900579 err = d.Decode(&g)
580 if err != nil {
581 panic(err)
582 }
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900583 return DeserializeGraph(g)
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900584}
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900585
Shinichiro Hamajif3ea5d02015-05-20 17:13:00 +0900586func LoadDepGraphCache(makefile string, roots []string) *DepGraph {
Shinichiro Hamaji82ecff92015-05-25 18:36:04 +0900587 startTime := time.Now()
588 defer func() {
589 LogStats("Cache lookup time: %q", time.Now().Sub(startTime))
590 }()
591
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900592 filename := GetCacheFilename(makefile, roots)
Shinichiro Hamaji39e62402015-05-20 19:34:58 +0900593 if !exists(filename) {
594 LogAlways("Cache not found")
595 return nil
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900596 }
Shinichiro Hamaji39e62402015-05-20 19:34:58 +0900597
598 g := LoadDepGraph(filename)
599 for _, mk := range g.readMks {
Fumitoshi Ukai936de102015-06-08 11:21:16 +0900600 if mk.State != FileExists && mk.State != FileNotExists {
Shinichiro Hamaji45cde1d2015-05-25 18:21:23 +0900601 panic(fmt.Sprintf("Internal error: broken state: %d", mk.State))
Shinichiro Hamaji0ba75a92015-05-20 19:42:43 +0900602 }
Fumitoshi Ukai936de102015-06-08 11:21:16 +0900603 if mk.State == FileNotExists {
Shinichiro Hamaji45cde1d2015-05-25 18:21:23 +0900604 if exists(mk.Filename) {
605 LogAlways("Cache expired: %s", mk.Filename)
606 return nil
607 }
608 } else {
Fumitoshi Ukaibc40a462015-06-02 15:51:16 +0900609 c, err := ioutil.ReadFile(mk.Filename)
Shinichiro Hamaji4220be32015-05-26 13:30:18 +0900610 if err != nil {
611 LogAlways("Cache expired: %s", mk.Filename)
612 return nil
613 }
614 h := sha1.Sum(c)
615 if !bytes.Equal(h[:], mk.Hash[:]) {
Shinichiro Hamaji45cde1d2015-05-25 18:21:23 +0900616 LogAlways("Cache expired: %s", mk.Filename)
617 return nil
618 }
Shinichiro Hamaji39e62402015-05-20 19:34:58 +0900619 }
620 }
621 g.isCached = true
622 LogAlways("Cache found!")
623 return g
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900624}