blob: f244a2b9b3c711bd61f43abbd64e5aaa721662b3 [file] [log] [blame]
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +09001package main
2
3import (
Shinichiro Hamaji530136b2015-04-28 17:12:48 +09004 "bytes"
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +09005 "encoding/binary"
Shinichiro Hamaji1833c282015-04-28 05:02:27 +09006 "encoding/gob"
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +09007 "encoding/json"
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +09008 "fmt"
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +09009 "io"
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +090010 "net/url"
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +090011 "os"
Shinichiro Hamaji530136b2015-04-28 17:12:48 +090012 "sort"
Shinichiro Hamajie666ac82015-04-28 04:18:13 +090013 "strconv"
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +090014 "time"
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +090015)
16
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +090017const (
18 VALUE_TYPE_RECURSIVE = 'R'
19 VALUE_TYPE_SIMPLE = 'S'
20 VALUE_TYPE_TSV = 'T'
21 VALUE_TYPE_UNDEFINED = 'U'
22 VALUE_TYPE_ASSIGN = 'a'
23 VALUE_TYPE_EXPR = 'e'
24 VALUE_TYPE_FUNC = 'f'
25 VALUE_TYPE_LITERAL = 'l'
26 VALUE_TYPE_NOP = 'n'
27 VALUE_TYPE_PARAMREF = 'p'
28 VALUE_TYPE_VARREF = 'r'
29 VALUE_TYPE_VARSUBST = 's'
30 VALUE_TYPE_TMPVAL = 't'
31)
32
33func dumpData(w io.Writer, data []byte) {
34 for len(data) != 0 {
35 written, err := w.Write(data)
36 if err == io.EOF {
37 return
38 }
39 if err != nil {
40 panic(err)
41 }
42 data = data[written:]
43 }
44}
45
46func dumpInt(w io.Writer, i int) {
47 v := int32(i)
48 binary.Write(w, binary.LittleEndian, &v)
49}
50
51func dumpString(w io.Writer, s string) {
52 dumpInt(w, len(s))
53 dumpData(w, []byte(s))
54}
55
56func dumpBytes(w io.Writer, b []byte) {
57 dumpInt(w, len(b))
58 dumpData(w, b)
59}
60
61func dumpByte(w io.Writer, b byte) {
62 w.Write([]byte{b})
63}
64
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +090065type SerializableVar struct {
66 Type string
67 V string
68 Origin string
69 Children []SerializableVar
70}
71
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +090072type SerializableDepNode struct {
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +090073 Output int
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +090074 Cmds []string
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +090075 Deps []int
Shinichiro Hamaji744b1392015-05-14 23:29:14 +090076 Parents []int
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +090077 HasRule bool
78 IsOrderOnly bool
79 IsPhony bool
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +090080 ActualInputs []int
Shinichiro Hamaji530136b2015-04-28 17:12:48 +090081 TargetSpecificVars []int
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +090082 Filename string
83 Lineno int
84}
85
Shinichiro Hamaji530136b2015-04-28 17:12:48 +090086type SerializableTargetSpecificVar struct {
87 Name string
88 Value SerializableVar
89}
90
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +090091type SerializableGraph struct {
Shinichiro Hamajif3ea5d02015-05-20 17:13:00 +090092 Nodes []*SerializableDepNode
93 Vars map[string]SerializableVar
94 Tsvs []SerializableTargetSpecificVar
95 Targets []string
96 Roots []string
Shinichiro Hamaji45cde1d2015-05-25 18:21:23 +090097 ReadMks []*ReadMakefile
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +090098}
99
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900100func encGob(v interface{}) string {
101 var buf bytes.Buffer
102 e := gob.NewEncoder(&buf)
103 err := e.Encode(v)
104 if err != nil {
105 panic(err)
106 }
107 return buf.String()
108}
109
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +0900110func encVar(k string, v Var) string {
111 var buf bytes.Buffer
112 dumpString(&buf, k)
113 v.Dump(&buf)
114 return buf.String()
115}
116
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900117type DepNodesSerializer struct {
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900118 nodes []*SerializableDepNode
119 tsvs []SerializableTargetSpecificVar
120 tsvMap map[string]int
121 targets []string
122 targetMap map[string]int
123 done map[string]bool
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900124}
125
126func NewDepNodesSerializer() *DepNodesSerializer {
127 return &DepNodesSerializer{
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900128 tsvMap: make(map[string]int),
129 targetMap: make(map[string]int),
130 done: make(map[string]bool),
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900131 }
132}
133
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900134func (ns *DepNodesSerializer) SerializeTarget(t string) int {
135 id, present := ns.targetMap[t]
136 if present {
137 return id
138 }
139 id = len(ns.targets)
140 ns.targetMap[t] = id
141 ns.targets = append(ns.targets, t)
142 return id
143}
144
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900145func (ns *DepNodesSerializer) SerializeDepNodes(nodes []*DepNode) {
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900146 for _, n := range nodes {
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900147 if ns.done[n.Output] {
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900148 continue
149 }
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900150 ns.done[n.Output] = true
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900151
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900152 var deps []int
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900153 for _, d := range n.Deps {
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900154 deps = append(deps, ns.SerializeTarget(d.Output))
155 }
Shinichiro Hamaji744b1392015-05-14 23:29:14 +0900156 var parents []int
157 for _, d := range n.Parents {
158 parents = append(parents, ns.SerializeTarget(d.Output))
159 }
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900160 var actualInputs []int
161 for _, i := range n.ActualInputs {
162 actualInputs = append(actualInputs, ns.SerializeTarget(i))
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900163 }
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900164
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900165 // Sort keys for consistent serialization.
166 var tsvKeys []string
167 for k := range n.TargetSpecificVars {
168 tsvKeys = append(tsvKeys, k)
169 }
170 sort.Strings(tsvKeys)
171
172 var vars []int
173 for _, k := range tsvKeys {
174 v := n.TargetSpecificVars[k]
175 sv := SerializableTargetSpecificVar{Name: k, Value: v.Serialize()}
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +0900176 //gob := encGob(sv)
177 gob := encVar(k, v)
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900178 id, present := ns.tsvMap[gob]
179 if !present {
180 id = len(ns.tsvs)
181 ns.tsvMap[gob] = id
182 ns.tsvs = append(ns.tsvs, sv)
183 }
184 vars = append(vars, id)
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900185 }
186
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900187 ns.nodes = append(ns.nodes, &SerializableDepNode{
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900188 Output: ns.SerializeTarget(n.Output),
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900189 Cmds: n.Cmds,
190 Deps: deps,
Shinichiro Hamaji744b1392015-05-14 23:29:14 +0900191 Parents: parents,
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900192 HasRule: n.HasRule,
193 IsOrderOnly: n.IsOrderOnly,
194 IsPhony: n.IsPhony,
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900195 ActualInputs: actualInputs,
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900196 TargetSpecificVars: vars,
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900197 Filename: n.Filename,
198 Lineno: n.Lineno,
199 })
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900200 ns.SerializeDepNodes(n.Deps)
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900201 }
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900202}
203
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900204func MakeSerializableVars(vars Vars) (r map[string]SerializableVar) {
205 r = make(map[string]SerializableVar)
206 for k, v := range vars {
207 r[k] = v.Serialize()
208 }
209 return r
210}
211
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900212func MakeSerializableGraph(g *DepGraph, roots []string) SerializableGraph {
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900213 ns := NewDepNodesSerializer()
Shinichiro Hamaji750ae2e2015-05-20 12:59:15 +0900214 ns.SerializeDepNodes(g.nodes)
215 v := MakeSerializableVars(g.vars)
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900216 return SerializableGraph{
Shinichiro Hamajif3ea5d02015-05-20 17:13:00 +0900217 Nodes: ns.nodes,
218 Vars: v,
219 Tsvs: ns.tsvs,
220 Targets: ns.targets,
221 Roots: roots,
222 ReadMks: g.readMks,
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900223 }
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900224}
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900225
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900226func DumpDepGraphAsJson(g *DepGraph, filename string, roots []string) {
Shinichiro Hamaji750ae2e2015-05-20 12:59:15 +0900227 sg := MakeSerializableGraph(g, roots)
228 o, err := json.MarshalIndent(sg, " ", " ")
Shinichiro Hamaji0df24ec2015-04-27 21:29:53 +0900229 if err != nil {
230 panic(err)
231 }
232 f, err2 := os.Create(filename)
233 if err2 != nil {
234 panic(err2)
235 }
236 f.Write(o)
237}
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900238
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900239func DumpDepGraph(g *DepGraph, filename string, roots []string) {
Shinichiro Hamaji1833c282015-04-28 05:02:27 +0900240 f, err := os.Create(filename)
241 if err != nil {
242 panic(err)
243 }
244 e := gob.NewEncoder(f)
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +0900245 startTime := time.Now()
Shinichiro Hamaji750ae2e2015-05-20 12:59:15 +0900246 sg := MakeSerializableGraph(g, roots)
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +0900247 LogStats("serialize prepare time: %q", time.Now().Sub(startTime))
248 startTime = time.Now()
Shinichiro Hamaji750ae2e2015-05-20 12:59:15 +0900249 e.Encode(sg)
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +0900250 LogStats("serialize output time: %q", time.Now().Sub(startTime))
Shinichiro Hamaji1833c282015-04-28 05:02:27 +0900251}
252
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900253func GetCacheFilename(mk string, roots []string) string {
254 filename := ".kati_cache." + mk
255 for _, r := range roots {
256 filename += "." + r
257 }
258 return url.QueryEscape(filename)
259}
260
261func DumpDepGraphCache(g *DepGraph, roots []string) {
262 if len(g.readMks) == 0 {
263 panic("No Makefile is read")
264 }
Shinichiro Hamajif3ea5d02015-05-20 17:13:00 +0900265 cacheFile := GetCacheFilename(g.readMks[0].Filename, roots)
266 for _, mk := range g.readMks {
267 // Inconsistent, do not dump this result.
Shinichiro Hamaji45cde1d2015-05-25 18:21:23 +0900268 if mk.State == 2 {
Shinichiro Hamajif3ea5d02015-05-20 17:13:00 +0900269 if exists(cacheFile) {
270 os.Remove(cacheFile)
271 }
272 return
273 }
274 }
275 DumpDepGraph(g, cacheFile, roots)
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900276}
277
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900278func DeserializeSingleChild(sv SerializableVar) Value {
279 if len(sv.Children) != 1 {
280 panic(fmt.Sprintf("unexpected number of children: %q", sv))
281 }
282 return DeserializeVar(sv.Children[0])
283}
284
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900285func DeserializeVar(sv SerializableVar) (r Value) {
286 switch sv.Type {
287 case "literal":
288 return literal(sv.V)
Shinichiro Hamajic8dea2a2015-04-28 17:15:30 +0900289 case "tmpval":
290 return tmpval([]byte(sv.V))
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900291 case "expr":
292 var e Expr
293 for _, v := range sv.Children {
294 e = append(e, DeserializeVar(v))
295 }
296 return e
297 case "varref":
Shinichiro Hamaji3d6d0aa2015-04-28 16:18:44 +0900298 return varref{varname: DeserializeSingleChild(sv)}
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900299 case "paramref":
300 v, err := strconv.Atoi(sv.V)
301 if err != nil {
302 panic(err)
303 }
304 return paramref(v)
Shinichiro Hamajic8dea2a2015-04-28 17:15:30 +0900305 case "varsubst":
306 return varsubst{
307 varname: DeserializeVar(sv.Children[0]),
308 pat: DeserializeVar(sv.Children[1]),
309 subst: DeserializeVar(sv.Children[2]),
310 }
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900311
312 case "func":
313 name := DeserializeVar(sv.Children[0]).(literal)
314 f := funcMap[string(name[1:])]()
315 f.AddArg(name)
316 for _, a := range sv.Children[1:] {
317 f.AddArg(DeserializeVar(a))
318 }
319 return f
320 case "funcEvalAssign":
321 return &funcEvalAssign{
322 lhs: sv.Children[0].V,
Shinichiro Hamaji3d6d0aa2015-04-28 16:18:44 +0900323 op: sv.Children[1].V,
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900324 rhs: DeserializeVar(sv.Children[2]),
325 }
326 case "funcNop":
Shinichiro Hamaji3d6d0aa2015-04-28 16:18:44 +0900327 return &funcNop{expr: sv.V}
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900328
329 case "simple":
330 return SimpleVar{
Shinichiro Hamaji3d6d0aa2015-04-28 16:18:44 +0900331 value: []byte(sv.V),
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900332 origin: sv.Origin,
333 }
334 case "recursive":
335 return RecursiveVar{
Shinichiro Hamaji3d6d0aa2015-04-28 16:18:44 +0900336 expr: DeserializeSingleChild(sv),
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900337 origin: sv.Origin,
338 }
Shinichiro Hamajif8f075c2015-04-28 04:25:37 +0900339
340 case ":=", "=", "+=", "?=":
341 return TargetSpecificVar{
Shinichiro Hamaji3d6d0aa2015-04-28 16:18:44 +0900342 v: DeserializeSingleChild(sv).(Var),
Shinichiro Hamajif8f075c2015-04-28 04:25:37 +0900343 op: sv.Type,
344 }
345
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900346 default:
347 panic(fmt.Sprintf("unknown serialized variable type: %q", sv))
348 }
349 return UndefinedVar{}
350}
351
Shinichiro Hamaji3d6d0aa2015-04-28 16:18:44 +0900352func DeserializeVars(vars map[string]SerializableVar) Vars {
Shinichiro Hamaji79a56932015-04-28 03:53:57 +0900353 r := make(Vars)
354 for k, v := range vars {
355 r[k] = DeserializeVar(v).(Var)
356 }
357 return r
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900358}
359
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900360func DeserializeNodes(g SerializableGraph) (r []*DepNode) {
361 nodes := g.Nodes
362 tsvs := g.Tsvs
363 targets := g.Targets
Shinichiro Hamaji7a65e682015-04-28 18:00:12 +0900364 // Deserialize all TSVs first so that multiple rules can share memory.
365 var tsvValues []Var
366 for _, sv := range tsvs {
367 tsvValues = append(tsvValues, DeserializeVar(sv.Value).(Var))
368 }
369
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900370 nodeMap := make(map[string]*DepNode)
371 for _, n := range nodes {
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900372 var actualInputs []string
373 for _, i := range n.ActualInputs {
374 actualInputs = append(actualInputs, targets[i])
375 }
376
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900377 d := &DepNode{
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900378 Output: targets[n.Output],
Shinichiro Hamaji3d6d0aa2015-04-28 16:18:44 +0900379 Cmds: n.Cmds,
380 HasRule: n.HasRule,
381 IsOrderOnly: n.IsOrderOnly,
382 IsPhony: n.IsPhony,
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900383 ActualInputs: actualInputs,
Shinichiro Hamaji3d6d0aa2015-04-28 16:18:44 +0900384 Filename: n.Filename,
385 Lineno: n.Lineno,
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900386 TargetSpecificVars: make(Vars),
387 }
388
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900389 for _, id := range n.TargetSpecificVars {
390 sv := tsvs[id]
Shinichiro Hamaji7a65e682015-04-28 18:00:12 +0900391 d.TargetSpecificVars[sv.Name] = tsvValues[id]
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900392 }
393
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900394 nodeMap[targets[n.Output]] = d
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900395 r = append(r, d)
396 }
397
398 for _, n := range nodes {
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900399 d := nodeMap[targets[n.Output]]
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900400 for _, o := range n.Deps {
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900401 c, present := nodeMap[targets[o]]
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900402 if !present {
403 panic(fmt.Sprintf("unknown target: %s", o))
404 }
405 d.Deps = append(d.Deps, c)
406 }
Shinichiro Hamaji744b1392015-05-14 23:29:14 +0900407 for _, o := range n.Parents {
408 c, present := nodeMap[targets[o]]
409 if !present {
410 panic(fmt.Sprintf("unknown target: %s", o))
411 }
412 d.Parents = append(d.Parents, c)
413 }
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900414 }
415
416 return r
417}
418
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900419func human(n int) string {
Shinichiro Hamaji744b1392015-05-14 23:29:14 +0900420 if n >= 10*1000*1000*1000 {
421 return fmt.Sprintf("%.2fGB", float32(n)/1000/1000/1000)
422 } else if n >= 10*1000*1000 {
423 return fmt.Sprintf("%.2fMB", float32(n)/1000/1000)
424 } else if n >= 10*1000 {
425 return fmt.Sprintf("%.2fkB", float32(n)/1000)
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900426 } else {
427 return fmt.Sprintf("%dB", n)
428 }
429}
430
431func showSerializedNodesStats(nodes []*SerializableDepNode) {
432 outputSize := 0
433 cmdSize := 0
434 depsSize := 0
435 actualInputSize := 0
436 tsvSize := 0
437 filenameSize := 0
438 linenoSize := 0
439 for _, n := range nodes {
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900440 outputSize += 4
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900441 for _, c := range n.Cmds {
442 cmdSize += len(c)
443 }
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900444 for _ = range n.Deps {
445 depsSize += 4
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900446 }
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900447 for _ = range n.ActualInputs {
448 actualInputSize += 4
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900449 }
450 for _ = range n.TargetSpecificVars {
451 tsvSize += 4
452 }
453 filenameSize += len(n.Filename)
454 linenoSize += 4
455 }
456 size := outputSize + cmdSize + depsSize + actualInputSize + tsvSize + filenameSize + linenoSize
457 LogStats("%d nodes %s", len(nodes), human(size))
458 LogStats(" output %s", human(outputSize))
459 LogStats(" command %s", human(cmdSize))
460 LogStats(" deps %s", human(depsSize))
461 LogStats(" inputs %s", human(actualInputSize))
462 LogStats(" tsv %s", human(tsvSize))
463 LogStats(" filename %s", human(filenameSize))
464 LogStats(" lineno %s", human(linenoSize))
465}
466
467func (v SerializableVar) size() int {
468 size := 0
469 size += len(v.Type)
470 size += len(v.V)
471 size += len(v.Origin)
472 for _, c := range v.Children {
473 size += c.size()
474 }
475 return size
476}
477
478func showSerializedVarsStats(vars map[string]SerializableVar) {
479 nameSize := 0
480 valueSize := 0
481 for k, v := range vars {
482 nameSize += len(k)
483 valueSize += v.size()
484 }
485 size := nameSize + valueSize
486 LogStats("%d vars %s", len(vars), human(size))
487 LogStats(" name %s", human(nameSize))
488 LogStats(" value %s", human(valueSize))
489}
490
491func showSerializedTsvsStats(vars []SerializableTargetSpecificVar) {
492 nameSize := 0
493 valueSize := 0
494 for _, v := range vars {
495 nameSize += len(v.Name)
496 valueSize += v.Value.size()
497 }
498 size := nameSize + valueSize
499 LogStats("%d tsvs %s", len(vars), human(size))
500 LogStats(" name %s", human(nameSize))
501 LogStats(" value %s", human(valueSize))
502}
503
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900504func showSerializedTargetsStats(targets []string) {
505 size := 0
506 for _, t := range targets {
507 size += len(t)
508 }
509 LogStats("%d targets %s", len(targets), human(size))
510}
511
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900512func showSerializedGraphStats(g SerializableGraph) {
513 showSerializedNodesStats(g.Nodes)
514 showSerializedVarsStats(g.Vars)
515 showSerializedTsvsStats(g.Tsvs)
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900516 showSerializedTargetsStats(g.Targets)
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900517}
518
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900519func DeserializeGraph(g SerializableGraph) *DepGraph {
Shinichiro Hamaji0962e862015-04-28 23:58:57 +0900520 if katiLogFlag || katiStatsFlag {
521 showSerializedGraphStats(g)
522 }
Shinichiro Hamajif013e4b2015-04-29 00:21:54 +0900523 nodes := DeserializeNodes(g)
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900524 vars := DeserializeVars(g.Vars)
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900525 return &DepGraph{
Shinichiro Hamajif3ea5d02015-05-20 17:13:00 +0900526 nodes: nodes,
527 vars: vars,
528 readMks: g.ReadMks,
Shinichiro Hamaji750ae2e2015-05-20 12:59:15 +0900529 }
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900530}
531
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900532func LoadDepGraphFromJson(filename string) *DepGraph {
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900533 f, err := os.Open(filename)
534 if err != nil {
535 panic(err)
536 }
537
538 d := json.NewDecoder(f)
Shinichiro Hamaji3d6d0aa2015-04-28 16:18:44 +0900539 g := SerializableGraph{Vars: make(map[string]SerializableVar)}
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900540 err = d.Decode(&g)
541 if err != nil {
542 panic(err)
543 }
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900544 return DeserializeGraph(g)
Shinichiro Hamaji1833c282015-04-28 05:02:27 +0900545}
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900546
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900547func LoadDepGraph(filename string) *DepGraph {
Shinichiro Hamaji1833c282015-04-28 05:02:27 +0900548 f, err := os.Open(filename)
549 if err != nil {
550 panic(err)
551 }
552
553 d := gob.NewDecoder(f)
Shinichiro Hamaji3d6d0aa2015-04-28 16:18:44 +0900554 g := SerializableGraph{Vars: make(map[string]SerializableVar)}
Shinichiro Hamaji1833c282015-04-28 05:02:27 +0900555 err = d.Decode(&g)
556 if err != nil {
557 panic(err)
558 }
Shinichiro Hamaji530136b2015-04-28 17:12:48 +0900559 return DeserializeGraph(g)
Shinichiro Hamaji8c9d0e32015-04-28 03:30:19 +0900560}
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900561
Shinichiro Hamajif3ea5d02015-05-20 17:13:00 +0900562func LoadDepGraphCache(makefile string, roots []string) *DepGraph {
Shinichiro Hamaji82ecff92015-05-25 18:36:04 +0900563 startTime := time.Now()
564 defer func() {
565 LogStats("Cache lookup time: %q", time.Now().Sub(startTime))
566 }()
567
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900568 filename := GetCacheFilename(makefile, roots)
Shinichiro Hamaji39e62402015-05-20 19:34:58 +0900569 if !exists(filename) {
570 LogAlways("Cache not found")
571 return nil
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900572 }
Shinichiro Hamaji39e62402015-05-20 19:34:58 +0900573
574 g := LoadDepGraph(filename)
575 for _, mk := range g.readMks {
Shinichiro Hamaji45cde1d2015-05-25 18:21:23 +0900576 if mk.State != FILE_EXISTS && mk.State != FILE_NOT_EXISTS {
577 panic(fmt.Sprintf("Internal error: broken state: %d", mk.State))
Shinichiro Hamaji0ba75a92015-05-20 19:42:43 +0900578 }
Shinichiro Hamaji45cde1d2015-05-25 18:21:23 +0900579 if mk.State == FILE_NOT_EXISTS {
580 if exists(mk.Filename) {
581 LogAlways("Cache expired: %s", mk.Filename)
582 return nil
583 }
584 } else {
585 c, err := readFile(mk.Filename)
586 if err != nil || !bytes.Equal(c, mk.Content) {
587 LogAlways("Cache expired: %s", mk.Filename)
588 return nil
589 }
Shinichiro Hamaji39e62402015-05-20 19:34:58 +0900590 }
591 }
592 g.isCached = true
593 LogAlways("Cache found!")
594 return g
Shinichiro Hamajib0d2e2f2015-05-20 16:42:59 +0900595}