Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(214)

Side by Side Diff: client/cmd/isolate/tarring_archiver.go

Issue 2991083002: isolate: Move partitioning code out of exparchive main. (Closed)
Patch Set: refer to isolate rather than isolated path when logging Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « client/cmd/isolate/exp_archive.go ('k') | client/cmd/isolate/upload_tracker.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2017 The LUCI Authors.
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
15 package main
16
17 import (
18 "fmt"
19 "log"
20 "os"
21 "path/filepath"
22
23 humanize "github.com/dustin/go-humanize"
24 "github.com/luci/luci-go/client/internal/common"
25 "github.com/luci/luci-go/client/isolate"
26 "github.com/luci/luci-go/common/isolated"
27 )
28
29 // TarringArchiver archives the files specified by an isolate file to the server ,
30 // Small files are combining into tar archives before uploading.
31 type TarringArchiver struct {
32 checker Checker
33 uploader Uploader
34 }
35
36 // NewTarringArchiver constructs a TarringArchiver.
37 func NewTarringArchiver(checker Checker, uploader Uploader) *TarringArchiver {
38 return &TarringArchiver{checker: checker, uploader: uploader}
39 }
40
41 // Archive uploads a single isolate.
42 func (ta *TarringArchiver) Archive(archiveOpts *isolate.ArchiveOptions) (Isolate dSummary, error) {
43 // Parse the incoming isolate file.
44 deps, rootDir, isol, err := isolate.ProcessIsolate(archiveOpts)
45 if err != nil {
46 return IsolatedSummary{}, fmt.Errorf("failed to process isolate: %v", err)
47 }
48 log.Printf("Isolate %s referenced %d deps", archiveOpts.Isolate, len(dep s))
49
50 parts, err := partitionDeps(deps, rootDir, archiveOpts.Blacklist)
51 if err != nil {
52 return IsolatedSummary{}, fmt.Errorf("partitioning deps: %v", er r)
53 }
54
55 log.Printf("Isolate %s expanded to the following items to be isolated:\n %s", archiveOpts.Isolate, parts)
56
57 tracker := NewUploadTracker(ta.checker, ta.uploader, isol)
58 if err := tracker.UploadDeps(parts); err != nil {
59 return IsolatedSummary{}, err
60 }
61 return tracker.Finalize(archiveOpts.Isolated)
62 }
63
64 // Item represents a file or symlink referenced by an isolate file.
65 type Item struct {
66 Path string
67 RelPath string
68 Size int64
69 Mode os.FileMode
70
71 Digest isolated.HexDigest
72 }
73
74 // itemGroup is a list of Items, plus a count of the aggregate size.
75 type itemGroup struct {
76 items []*Item
77 totalSize int64
78 }
79
80 func (ig *itemGroup) AddItem(item *Item) {
81 ig.items = append(ig.items, item)
82 ig.totalSize += item.Size
83 }
84
85 // partitioningWalker contains the state necessary to partition isolate deps by handling multiple os.WalkFunc invocations.
86 type partitioningWalker struct {
87 // fsView must be initialized before walkFn is called.
88 fsView common.FilesystemView
89
90 parts partitionedDeps
91 }
92
93 // partitionedDeps contains a list of items to be archived, partitioned into sym links and files categorized by size.
94 type partitionedDeps struct {
95 links itemGroup
96 filesToArchive itemGroup
97 indivFiles itemGroup
98 }
99
100 func (parts partitionedDeps) String() string {
101 str := fmt.Sprintf(" %d symlinks\n", len(parts.links.items))
102 str += fmt.Sprintf(" %d individual files (total size: %s)\n", len(parts .indivFiles.items), humanize.Bytes(uint64(parts.indivFiles.totalSize)))
103 str += fmt.Sprintf(" %d files in archives (total size %s)", len(parts.f ilesToArchive.items), humanize.Bytes(uint64(parts.filesToArchive.totalSize)))
104 return str
105 }
106
107 // walkFn implements filepath.WalkFunc, for use traversing a directory hierarchy to be isolated.
108 // It accumulates files in pw.parts, partitioned into symlinks and files categor ized by size.
109 func (pw *partitioningWalker) walkFn(path string, info os.FileInfo, err error) e rror {
110 if err != nil {
111 return err
112 }
113
114 relPath, err := pw.fsView.RelativePath(path)
115 if err != nil {
116 return err
117 }
118
119 if relPath == "" { // empty string indicates skip.
120 return common.WalkFuncSkipFile(info)
121 }
122
123 if info.IsDir() {
124 return nil
125 }
126
127 item := &Item{
128 Path: path,
129 RelPath: relPath,
130 Mode: info.Mode(),
131 Size: info.Size(),
132 }
133
134 switch {
135 case item.Mode&os.ModeSymlink == os.ModeSymlink:
136 pw.parts.links.AddItem(item)
137 case item.Size < archiveThreshold:
138 pw.parts.filesToArchive.AddItem(item)
139 default:
140 pw.parts.indivFiles.AddItem(item)
141 }
142 return nil
143 }
144
145 // partitionDeps walks each of the deps, partioning the results into symlinks an d files categorized by size.
146 func partitionDeps(deps []string, rootDir string, blacklist []string) (partition edDeps, error) {
147 fsView, err := common.NewFilesystemView(rootDir, blacklist)
148 if err != nil {
149 return partitionedDeps{}, err
150 }
151
152 walker := partitioningWalker{fsView: fsView}
153 for _, dep := range deps {
154 // Try to walk dep. If dep is a file (or symlink), the inner fun ction is called exactly once.
155 if err := filepath.Walk(filepath.Clean(dep), walker.walkFn); err != nil {
156 return partitionedDeps{}, err
157 }
158 }
159 return walker.parts, nil
160 }
OLDNEW
« no previous file with comments | « client/cmd/isolate/exp_archive.go ('k') | client/cmd/isolate/upload_tracker.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698