OLD | NEW |
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:collection'; |
5 import 'dart:convert'; | 6 import 'dart:convert'; |
6 import 'dart:core' hide Resource; | 7 import 'dart:core' hide Resource; |
7 | 8 |
8 import 'package:analyzer/dart/element/element.dart'; | 9 import 'package:analyzer/dart/element/element.dart'; |
9 import 'package:analyzer/file_system/file_system.dart'; | 10 import 'package:analyzer/file_system/file_system.dart'; |
10 import 'package:analyzer/src/generated/engine.dart'; | 11 import 'package:analyzer/src/generated/engine.dart'; |
11 import 'package:analyzer/src/generated/error.dart'; | 12 import 'package:analyzer/src/generated/error.dart'; |
12 import 'package:analyzer/src/generated/source.dart'; | 13 import 'package:analyzer/src/generated/source.dart'; |
13 import 'package:analyzer/src/summary/format.dart'; | 14 import 'package:analyzer/src/summary/format.dart'; |
14 import 'package:analyzer/src/summary/idl.dart'; | 15 import 'package:analyzer/src/summary/idl.dart'; |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
51 return 1; | 52 return 1; |
52 } | 53 } |
53 return 0; | 54 return 0; |
54 } | 55 } |
55 | 56 |
56 /** | 57 /** |
57 * Storage for cache data. | 58 * Storage for cache data. |
58 */ | 59 */ |
59 abstract class CacheStorage { | 60 abstract class CacheStorage { |
60 /** | 61 /** |
| 62 * Compact the storage, e.g. remove unused entries. |
| 63 */ |
| 64 void compact(); |
| 65 |
| 66 /** |
61 * Return bytes for the given [key], `null` if [key] is not in the storage. | 67 * Return bytes for the given [key], `null` if [key] is not in the storage. |
62 */ | 68 */ |
63 List<int> get(String key); | 69 List<int> get(String key); |
64 | 70 |
65 /** | 71 /** |
66 * Associate the [key] with the given [bytes]. | 72 * Associate the [key] with the given [bytes]. |
67 * | 73 * |
68 * If the [key] was already in the storage, its associated value is changed. | 74 * If the [key] was already in the storage, its associated value is changed. |
69 * Otherwise the key-value pair is added to the storage. | 75 * Otherwise the key-value pair is added to the storage. |
70 * | 76 * |
71 * It is not guaranteed that data will always be accessible using [get], in | 77 * It is not guaranteed that data will always be accessible using [get], in |
72 * some implementations association may silently fail or become inaccessible | 78 * some implementations association may silently fail or become inaccessible |
73 * after some time. | 79 * after some time. |
74 */ | 80 */ |
75 void put(String key, List<int> bytes); | 81 void put(String key, List<int> bytes); |
76 } | 82 } |
77 | 83 |
78 /** | 84 /** |
79 * A [Folder] based implementation of [CacheStorage]. | 85 * A [Folder] based implementation of [CacheStorage]. |
80 */ | 86 */ |
81 class FolderCacheStorage implements CacheStorage { | 87 class FolderCacheStorage implements CacheStorage { |
82 /** | 88 /** |
| 89 * The maximum number of entries to keep in the cache. |
| 90 */ |
| 91 static const MAX_ENTRIES = 20000; |
| 92 |
| 93 /** |
83 * The folder to read and write files. | 94 * The folder to read and write files. |
84 */ | 95 */ |
85 final Folder folder; | 96 final Folder folder; |
86 | 97 |
87 /** | 98 /** |
88 * To ensure that operations of writing files are atomic we create a temporary | 99 * To ensure that operations of writing files are atomic we create a temporary |
89 * file with this name in the [folder] and then rename it once we are | 100 * file with this name in the [folder] and then rename it once we are |
90 * done writing. | 101 * done writing. |
91 */ | 102 */ |
92 final String tempFileName; | 103 final String tempFileName; |
93 | 104 |
94 FolderCacheStorage(this.folder, this.tempFileName); | 105 /** |
| 106 * The set of recently used entries, with the most recently used entries |
| 107 * on the bottom. |
| 108 */ |
| 109 final LinkedHashSet<String> _recentEntries = new LinkedHashSet<String>(); |
| 110 |
| 111 FolderCacheStorage(this.folder, this.tempFileName) { |
| 112 try { |
| 113 File file = folder.getChildAssumingFile('.entries'); |
| 114 if (file.exists) { |
| 115 String entriesString = file.readAsStringSync(); |
| 116 List<String> entriesLists = entriesString.split('\n'); |
| 117 _recentEntries.addAll(entriesLists); |
| 118 } |
| 119 } catch (_) {} |
| 120 } |
| 121 |
| 122 @override |
| 123 void compact() { |
| 124 while (_recentEntries.length > MAX_ENTRIES) { |
| 125 String key = _recentEntries.first; |
| 126 _recentEntries.remove(key); |
| 127 try { |
| 128 folder.getChildAssumingFile(key).delete(); |
| 129 } catch (_) {} |
| 130 } |
| 131 try { |
| 132 List<int> bytes = UTF8.encode(_recentEntries.join('\n')); |
| 133 folder.getChildAssumingFile('.entries').writeAsBytesSync(bytes); |
| 134 } catch (_) {} |
| 135 } |
95 | 136 |
96 @override | 137 @override |
97 List<int> get(String key) { | 138 List<int> get(String key) { |
98 Resource file = folder.getChild(key); | 139 Resource file = folder.getChild(key); |
99 if (file is File) { | 140 if (file is File) { |
100 try { | 141 try { |
101 return file.readAsBytesSync(); | 142 List<int> bytes = file.readAsBytesSync(); |
| 143 _accessedKey(key); |
| 144 return bytes; |
102 } on FileSystemException {} | 145 } on FileSystemException {} |
103 } | 146 } |
104 return null; | 147 return null; |
105 } | 148 } |
106 | 149 |
107 @override | 150 @override |
108 void put(String key, List<int> bytes) { | 151 void put(String key, List<int> bytes) { |
109 String absPath = folder.getChild(key).path; | 152 String absPath = folder.getChild(key).path; |
110 File tempFile = folder.getChild(tempFileName); | 153 File tempFile = folder.getChild(tempFileName); |
111 tempFile.writeAsBytesSync(bytes); | 154 tempFile.writeAsBytesSync(bytes); |
112 try { | 155 try { |
113 tempFile.renameSync(absPath); | 156 tempFile.renameSync(absPath); |
| 157 _accessedKey(key); |
114 } catch (e) {} | 158 } catch (e) {} |
115 } | 159 } |
| 160 |
| 161 /** |
| 162 * The given [key] was accessed, update recently used entries. |
| 163 */ |
| 164 void _accessedKey(String key) { |
| 165 _recentEntries.remove(key); |
| 166 _recentEntries.add(key); |
| 167 } |
116 } | 168 } |
117 | 169 |
118 /** | 170 /** |
119 * Cache of information to support incremental analysis. | 171 * Cache of information to support incremental analysis. |
120 * | 172 * |
121 * Note that currently this class is not intended for interactive use. | 173 * Note that currently this class is not intended for interactive use. |
122 */ | 174 */ |
123 class IncrementalCache { | 175 class IncrementalCache { |
124 /** | 176 /** |
125 * The storage for the cache data. | 177 * The storage for the cache data. |
(...skipping 468 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
594 */ | 646 */ |
595 final String id; | 647 final String id; |
596 | 648 |
597 /** | 649 /** |
598 * The payload bundle. | 650 * The payload bundle. |
599 */ | 651 */ |
600 final PackageBundle bundle; | 652 final PackageBundle bundle; |
601 | 653 |
602 LibraryBundleWithId(this.source, this.id, this.bundle); | 654 LibraryBundleWithId(this.source, this.id, this.bundle); |
603 } | 655 } |
OLD | NEW |