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

Side by Side Diff: pkg/analyzer/lib/src/summary/incremental_cache.dart

Issue 1816693002: Extract CacheStorage and renames. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 9 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 | « no previous file | pkg/analyzer/test/src/summary/incremental_cache_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 import 'dart:convert' show UTF8; 5 import 'dart:convert' show UTF8;
6 import 'dart:core' hide Resource; 6 import 'dart:core' hide Resource;
7 7
8 import 'package:analyzer/dart/element/element.dart'; 8 import 'package:analyzer/dart/element/element.dart';
9 import 'package:analyzer/file_system/file_system.dart'; 9 import 'package:analyzer/file_system/file_system.dart';
10 import 'package:analyzer/src/generated/engine.dart'; 10 import 'package:analyzer/src/generated/engine.dart';
11 import 'package:analyzer/src/generated/source.dart'; 11 import 'package:analyzer/src/generated/source.dart';
12 import 'package:analyzer/src/summary/format.dart'; 12 import 'package:analyzer/src/summary/format.dart';
13 import 'package:analyzer/src/summary/idl.dart'; 13 import 'package:analyzer/src/summary/idl.dart';
14 import 'package:analyzer/src/summary/summarize_elements.dart'; 14 import 'package:analyzer/src/summary/summarize_elements.dart';
15 import 'package:crypto/crypto.dart'; 15 import 'package:crypto/crypto.dart';
16 16
17 /** 17 /**
18 * The cache of per-library [PackageBundle]s. 18 * Storage for cache data.
19 *
20 * Note that currently this class is not intended for interactive use.
21 */ 19 */
22 class LibraryBundleCache { 20 abstract class CacheStorage {
21 /**
22 * Return bytes for the given [key], `null` if [key] is not in the storage.
23 */
24 List<int> get(String key);
25
26 /**
27 * Associate the [key] with the given [bytes].
28 *
29 * If the [key] was already in the storage, its associated value is changed.
30 * Otherwise the key-value pair is added to the storage.
31 *
32 * This method does not guarantee that data will always be accessible using
33 * [get], in some implementations association may silently fail or become
34 * inaccessible after some time.
35 */
36 void put(String key, List<int> bytes);
37 }
38
39 /**
40 * A [Folder] based implementation of [CacheStorage].
41 */
42 class FolderCacheStorage implements CacheStorage {
43 /**
44 * The folder to read and write files.
45 */
46 final Folder folder;
47
23 /** 48 /**
24 * To ensure that operations of writing files are atomic we create a temporary 49 * To ensure that operations of writing files are atomic we create a temporary
25 * file with this name in the [cacheFolder] and then rename it once we are 50 * file with this name in the [folder] and then rename it once we are
26 * done writing. 51 * done writing.
27 */ 52 */
28 final String tempFileName; 53 final String tempFileName;
29 54
55 FolderCacheStorage(this.folder, this.tempFileName);
56
57 @override
58 List<int> get(String key) {
59 Resource file = folder.getChild(key);
60 if (file is File) {
61 try {
62 return file.readAsBytesSync();
63 } on FileSystemException {}
64 }
65 return null;
66 }
67
68 @override
69 void put(String key, List<int> bytes) {
70 try {
Paul Berry 2016/03/18 20:22:42 The try/catch should only surround the call to ren
71 String absPath = folder.getChild(key).path;
72 File tempFile = folder.getChild(tempFileName);
73 tempFile.writeAsBytesSync(bytes);
74 tempFile.renameSync(absPath);
75 } catch (e) {}
76 }
77 }
78
79 /**
80 * Cache of information to support incremental analysis.
81 *
82 * Note that currently this class is not intended for interactive use.
83 */
84 class IncrementalCache {
30 /** 85 /**
31 * The folder to read and write files. 86 * The storage for the cache data.
32 */ 87 */
33 final Folder cacheFolder; 88 final CacheStorage storage;
34 89
35 /** 90 /**
36 * The context in which this cache is used. 91 * The context in which this cache is used.
37 */ 92 */
38 final AnalysisContext context; 93 final AnalysisContext context;
39 94
40 /** 95 /**
41 * Opaque data that reflects the current configuration, such as the [context] 96 * Opaque data that reflects the current configuration, such as the [context]
42 * options, and is mixed into the hashes. 97 * options, and is mixed into the hashes.
43 */ 98 */
44 final List<int> configSalt; 99 final List<int> configSalt;
45 100
46 final Map<Source, CacheSourceContent> _sourceContentMap = 101 final Map<Source, CacheSourceContent> _sourceContentMap =
47 <Source, CacheSourceContent>{}; 102 <Source, CacheSourceContent>{};
48 final Map<Source, List<Source>> _libraryClosureMap = <Source, List<Source>>{}; 103 final Map<Source, List<Source>> _libraryClosureMap = <Source, List<Source>>{};
49 final Map<Source, List<int>> _sourceContentHashMap = <Source, List<int>>{}; 104 final Map<Source, List<int>> _sourceContentHashMap = <Source, List<int>>{};
50 105
51 LibraryBundleCache( 106 IncrementalCache(this.storage, this.context, this.configSalt);
52 this.tempFileName, this.cacheFolder, this.context, this.configSalt);
53 107
54 /** 108 /**
55 * Clear internal caches so that we read from file system again. 109 * Clear internal caches so that we read from file system again.
56 */ 110 */
57 void clearInternalCaches() { 111 void clearInternalCaches() {
58 _sourceContentMap.clear(); 112 _sourceContentMap.clear();
59 _libraryClosureMap.clear(); 113 _libraryClosureMap.clear();
60 _sourceContentHashMap.clear(); 114 _sourceContentHashMap.clear();
61 } 115 }
62 116
(...skipping 19 matching lines...) Expand all
82 * Write information about the [library] into the cache. 136 * Write information about the [library] into the cache.
83 */ 137 */
84 void putLibrary(LibraryElement library) { 138 void putLibrary(LibraryElement library) {
85 try { 139 try {
86 _writeCacheSourceContents(library); 140 _writeCacheSourceContents(library);
87 List<int> hash = _getLibraryClosureHash(library.source); 141 List<int> hash = _getLibraryClosureHash(library.source);
88 String hashStr = CryptoUtils.bytesToHex(hash); 142 String hashStr = CryptoUtils.bytesToHex(hash);
89 PackageBundleAssembler assembler = new PackageBundleAssembler(); 143 PackageBundleAssembler assembler = new PackageBundleAssembler();
90 assembler.serializeLibraryElement(library); 144 assembler.serializeLibraryElement(library);
91 List<int> bytes = assembler.assemble().toBuffer(); 145 List<int> bytes = assembler.assemble().toBuffer();
92 _safeWriteBytes('$hashStr.sum', bytes); 146 storage.put('$hashStr.sum', bytes);
93 } catch (e) {} 147 } catch (e) {}
94 } 148 }
95 149
96 /** 150 /**
97 * Read the [PackageBundle] for the library with the given [source] from 151 * Read the [PackageBundle] for the library with the given [source] from
98 * the cache. The returned bundle will correspond to the state when the set 152 * the cache. The returned bundle will correspond to the state when the set
99 * of direct and indirect dependencies is resolved in the [context]. Return 153 * of direct and indirect dependencies is resolved in the [context]. Return
100 * `null` if such bundle does not exist. 154 * `null` if such bundle does not exist.
101 */ 155 */
102 PackageBundle readBundle(Source source) { 156 PackageBundle readBundle(Source source) {
103 try { 157 try {
104 List<int> hash = _getLibraryClosureHash(source); 158 List<int> hash = _getLibraryClosureHash(source);
105 String hashStr = CryptoUtils.bytesToHex(hash); 159 String hashStr = CryptoUtils.bytesToHex(hash);
106 List<int> bytes = _safeReadBytes('$hashStr.sum'); 160 List<int> bytes = storage.get('$hashStr.sum');
107 if (bytes == null) { 161 if (bytes == null) {
108 return null; 162 return null;
109 } 163 }
110 return new PackageBundle.fromBuffer(bytes); 164 return new PackageBundle.fromBuffer(bytes);
111 } catch (e) { 165 } catch (e) {
112 return null; 166 return null;
113 } 167 }
114 } 168 }
115 169
116 /** 170 /**
(...skipping 30 matching lines...) Expand all
147 } 201 }
148 } 202 }
149 203
150 /** 204 /**
151 * Get the content based information about the given [source], maybe `null` 205 * Get the content based information about the given [source], maybe `null`
152 * if the information is not in the cache. 206 * if the information is not in the cache.
153 */ 207 */
154 CacheSourceContent _getCacheSourceContent(Source source) { 208 CacheSourceContent _getCacheSourceContent(Source source) {
155 CacheSourceContent content = _sourceContentMap[source]; 209 CacheSourceContent content = _sourceContentMap[source];
156 if (content == null) { 210 if (content == null) {
157 String fileName = _getCacheSourceContentFileName(source); 211 String key = _getCacheSourceContentKey(source);
158 List<int> bytes = _safeReadBytes(fileName); 212 List<int> bytes = storage.get(key);
159 if (bytes == null) { 213 if (bytes == null) {
160 return null; 214 return null;
161 } 215 }
162 content = new CacheSourceContent.fromBuffer(bytes); 216 content = new CacheSourceContent.fromBuffer(bytes);
163 _sourceContentMap[source] = content; 217 _sourceContentMap[source] = content;
164 } 218 }
165 return content; 219 return content;
166 } 220 }
167 221
168 /** 222 /**
169 * Return the name of the file with the content based [source] information. 223 * Return the key of the content based [source] information.
170 */ 224 */
171 String _getCacheSourceContentFileName(Source source) { 225 String _getCacheSourceContentKey(Source source) {
172 List<int> hash = _getSourceContentHash(source); 226 List<int> hash = _getSourceContentHash(source);
173 String hashStr = CryptoUtils.bytesToHex(hash); 227 String hashStr = CryptoUtils.bytesToHex(hash);
174 return '$hashStr.content'; 228 return '$hashStr.content';
175 } 229 }
176 230
177 /** 231 /**
178 * Return the whole source closure of the library with the given 232 * Return the whole source closure of the library with the given
179 * [librarySource]. It includes defining units and parts of the library and 233 * [librarySource]. It includes defining units and parts of the library and
180 * of all its directly or indirectly imported or exported libraries. 234 * of all its directly or indirectly imported or exported libraries.
181 */ 235 */
(...skipping 25 matching lines...) Expand all
207 */ 261 */
208 List<int> _getSourceContentHash(Source source) { 262 List<int> _getSourceContentHash(Source source) {
209 return _sourceContentHashMap.putIfAbsent(source, () { 263 return _sourceContentHashMap.putIfAbsent(source, () {
210 String sourceText = source.contents.data; 264 String sourceText = source.contents.data;
211 List<int> sourceBytes = UTF8.encode(sourceText); 265 List<int> sourceBytes = UTF8.encode(sourceText);
212 return (new MD5()..add(sourceBytes)).close(); 266 return (new MD5()..add(sourceBytes)).close();
213 }); 267 });
214 } 268 }
215 269
216 /** 270 /**
217 * Return bytes of the file with the given [relPath] in the cache, or `null`
218 * if the file does not exist.
219 */
220 List<int> _safeReadBytes(String relPath) {
221 Resource file = cacheFolder.getChild(relPath);
222 if (file is File) {
223 try {
224 return file.readAsBytesSync();
225 } on FileSystemException {}
226 }
227 return null;
228 }
229
230 /**
231 * Atomically write the given [bytes] into the file with the given [relPath].
232 * Silently ignores any errors.
233 */
234 void _safeWriteBytes(String relPath, List<int> bytes) {
235 try {
236 String absPath = cacheFolder.getChild(relPath).path;
237 File tempFile = cacheFolder.getChild(tempFileName);
238 tempFile.writeAsBytesSync(bytes);
239 tempFile.renameSync(absPath);
240 } catch (e) {}
241 }
242
243 /**
244 * Write the content based information about the given [source]. 271 * Write the content based information about the given [source].
245 */ 272 */
246 void _writeCacheSourceContent(Source source, CacheSourceContentBuilder b) { 273 void _writeCacheSourceContent(Source source, CacheSourceContentBuilder b) {
247 String fileName = _getCacheSourceContentFileName(source); 274 String key = _getCacheSourceContentKey(source);
248 List<int> bytes = b.toBuffer(); 275 List<int> bytes = b.toBuffer();
249 _safeWriteBytes(fileName, bytes); 276 storage.put(key, bytes);
250 // Put into the cache to avoid reading it later. 277 // Put into the cache to avoid reading it later.
251 _sourceContentMap[source] = new CacheSourceContent.fromBuffer(bytes); 278 _sourceContentMap[source] = new CacheSourceContent.fromBuffer(bytes);
252 } 279 }
253 280
254 /** 281 /**
255 * Write [CacheSourceContent] for every unit of the given [library] and its 282 * Write [CacheSourceContent] for every unit of the given [library] and its
256 * direct and indirect imports/exports. 283 * direct and indirect imports/exports.
257 */ 284 */
258 void _writeCacheSourceContents(LibraryElement library, 285 void _writeCacheSourceContents(LibraryElement library,
259 [Set<LibraryElement> writtenLibraries]) { 286 [Set<LibraryElement> writtenLibraries]) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 // Write the library. 325 // Write the library.
299 _writeCacheSourceContent( 326 _writeCacheSourceContent(
300 librarySource, 327 librarySource,
301 new CacheSourceContentBuilder( 328 new CacheSourceContentBuilder(
302 kind: CacheSourceKind.library, 329 kind: CacheSourceKind.library,
303 importedUris: importUris, 330 importedUris: importUris,
304 exportedUris: exportUris, 331 exportedUris: exportUris,
305 partUris: partUris)); 332 partUris: partUris));
306 } 333 }
307 } 334 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/test/src/summary/incremental_cache_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698