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

Side by Side Diff: pkg/analyzer/lib/src/dart/analysis/file_byte_store.dart

Issue 2676363003: Add EvictingFileByteStore and make FileByteStore non-evicting. (Closed)
Patch Set: Created 3 years, 10 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 | « pkg/analysis_server/lib/src/analysis_server.dart ('k') | no next file » | 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) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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:async'; 5 import 'dart:async';
6 import 'dart:io'; 6 import 'dart:io';
7 import 'dart:isolate'; 7 import 'dart:isolate';
8 8
9 import 'package:analyzer/src/dart/analysis/byte_store.dart'; 9 import 'package:analyzer/src/dart/analysis/byte_store.dart';
10 import 'package:path/path.dart'; 10 import 'package:path/path.dart';
11 11
12 /** 12 /**
13 * The request that is sent from the main isolate to the clean-up isolate. 13 * [ByteStore] that stores values as files and performs cache eviction.
14 *
15 * Only the process that manages the cache, e.g. Analysis Server, should use
16 * this class. Other processes, e.g. Analysis Server plugins, should use
17 * [FileByteStore] instead and let the main process to perform eviction.
14 */ 18 */
15 class CacheCleanUpRequest { 19 class EvictingFileByteStore implements ByteStore {
16 final String cachePath;
17 final int maxSizeBytes;
18 final SendPort replyTo;
19
20 CacheCleanUpRequest(this.cachePath, this.maxSizeBytes, this.replyTo);
21 }
22
23 /**
24 * [ByteStore] that stores values as files.
25 */
26 class FileByteStore implements ByteStore {
27 static bool _cleanUpSendPortShouldBePrepared = true; 20 static bool _cleanUpSendPortShouldBePrepared = true;
28 static SendPort _cleanUpSendPort; 21 static SendPort _cleanUpSendPort;
29 22
30 final String _cachePath; 23 final String _cachePath;
31 final String _tempName = 'temp_$pid';
32 final int _maxSizeBytes; 24 final int _maxSizeBytes;
25 final FileByteStore _fileByteStore;
33 26
34 int _bytesWrittenSinceCleanup = 0; 27 int _bytesWrittenSinceCleanup = 0;
35 bool _evictionIsolateIsRunning = false; 28 bool _evictionIsolateIsRunning = false;
36 29
37 FileByteStore(this._cachePath, this._maxSizeBytes) { 30 EvictingFileByteStore(this._cachePath, this._maxSizeBytes)
31 : _fileByteStore = new FileByteStore(_cachePath) {
38 _requestCacheCleanUp(); 32 _requestCacheCleanUp();
39 } 33 }
40 34
41 @override 35 @override
42 List<int> get(String key) { 36 List<int> get(String key) {
43 try { 37 return _fileByteStore.get(key);
44 return _getFileForKey(key).readAsBytesSync();
45 } catch (_) {
46 return null;
47 }
48 } 38 }
49 39
50 @override 40 @override
51 void put(String key, List<int> bytes) { 41 void put(String key, List<int> bytes) {
52 try { 42 _fileByteStore.put(key, bytes);
53 File tempFile = _getFileForKey(_tempName); 43 // Update the current size.
54 tempFile.writeAsBytesSync(bytes); 44 _bytesWrittenSinceCleanup += bytes.length;
55 File file = _getFileForKey(key); 45 if (_bytesWrittenSinceCleanup > _maxSizeBytes ~/ 8) {
56 tempFile.renameSync(file.path); 46 _requestCacheCleanUp();
57 // Update the current size. 47 }
58 _bytesWrittenSinceCleanup += bytes.length;
59 if (_bytesWrittenSinceCleanup > _maxSizeBytes ~/ 8) {
60 _requestCacheCleanUp();
61 }
62 } catch (_) {}
63 }
64
65 File _getFileForKey(String key) {
66 return new File(join(_cachePath, key));
67 } 48 }
68 49
69 /** 50 /**
70 * If the cache clean up process has not been requested yet, request it. 51 * If the cache clean up process has not been requested yet, request it.
71 */ 52 */
72 Future<Null> _requestCacheCleanUp() async { 53 Future<Null> _requestCacheCleanUp() async {
73 if (_cleanUpSendPortShouldBePrepared) { 54 if (_cleanUpSendPortShouldBePrepared) {
74 _cleanUpSendPortShouldBePrepared = false; 55 _cleanUpSendPortShouldBePrepared = false;
75 ReceivePort response = new ReceivePort(); 56 ReceivePort response = new ReceivePort();
76 await Isolate.spawn(_cacheCleanUpFunction, response.sendPort); 57 await Isolate.spawn(_cacheCleanUpFunction, response.sendPort);
77 _cleanUpSendPort = await response.first as SendPort; 58 _cleanUpSendPort = await response.first as SendPort;
78 } else { 59 } else {
79 while (_cleanUpSendPort == null) { 60 while (_cleanUpSendPort == null) {
80 await new Future.delayed(new Duration(milliseconds: 100), () {}); 61 await new Future.delayed(new Duration(milliseconds: 100), () {});
81 } 62 }
82 } 63 }
83 64
84 if (!_evictionIsolateIsRunning) { 65 if (!_evictionIsolateIsRunning) {
85 _evictionIsolateIsRunning = true; 66 _evictionIsolateIsRunning = true;
86 try { 67 try {
87 ReceivePort response = new ReceivePort(); 68 ReceivePort response = new ReceivePort();
88 _cleanUpSendPort.send(new CacheCleanUpRequest( 69 _cleanUpSendPort.send(new _CacheCleanUpRequest(
89 _cachePath, _maxSizeBytes, response.sendPort)); 70 _cachePath, _maxSizeBytes, response.sendPort));
90 await response.first; 71 await response.first;
91 } finally { 72 } finally {
92 _evictionIsolateIsRunning = false; 73 _evictionIsolateIsRunning = false;
93 _bytesWrittenSinceCleanup = 0; 74 _bytesWrittenSinceCleanup = 0;
94 } 75 }
95 } 76 }
96 } 77 }
97 78
98 /** 79 /**
99 * This function is started in a new isolate, receives cache folder clean up 80 * This function is started in a new isolate, receives cache folder clean up
100 * requests and evicts older files from the folder. 81 * requests and evicts older files from the folder.
101 */ 82 */
102 static void _cacheCleanUpFunction(SendPort initialReplyTo) { 83 static void _cacheCleanUpFunction(SendPort initialReplyTo) {
103 ReceivePort port = new ReceivePort(); 84 ReceivePort port = new ReceivePort();
104 initialReplyTo.send(port.sendPort); 85 initialReplyTo.send(port.sendPort);
105 port.listen((request) async { 86 port.listen((request) async {
106 if (request is CacheCleanUpRequest) { 87 if (request is _CacheCleanUpRequest) {
107 await _cleanUpFolder(request.cachePath, request.maxSizeBytes); 88 await _cleanUpFolder(request.cachePath, request.maxSizeBytes);
108 // Let the client know that we're done. 89 // Let the client know that we're done.
109 request.replyTo.send(true); 90 request.replyTo.send(true);
110 } 91 }
111 }); 92 });
112 } 93 }
113 94
114 static Future<Null> _cleanUpFolder(String cachePath, int maxSizeBytes) async { 95 static Future<Null> _cleanUpFolder(String cachePath, int maxSizeBytes) async {
115 // Prepare the list of files and their statistics. 96 // Prepare the list of files and their statistics.
116 List<File> files = <File>[]; 97 List<File> files = <File>[];
(...skipping 20 matching lines...) Expand all
137 if (currentSizeBytes < maxSizeBytes) { 118 if (currentSizeBytes < maxSizeBytes) {
138 break; 119 break;
139 } 120 }
140 try { 121 try {
141 await file.delete(); 122 await file.delete();
142 } catch (_) {} 123 } catch (_) {}
143 currentSizeBytes -= fileStatMap[file].size; 124 currentSizeBytes -= fileStatMap[file].size;
144 } 125 }
145 } 126 }
146 } 127 }
128
129 /**
130 * [ByteStore] that stores values as files.
131 */
132 class FileByteStore implements ByteStore {
133 final String _cachePath;
134 final String _tempName = 'temp_$pid';
135
136 FileByteStore(this._cachePath);
137
138 @override
139 List<int> get(String key) {
140 try {
141 return _getFileForKey(key).readAsBytesSync();
142 } catch (_) {
143 return null;
144 }
145 }
146
147 @override
148 void put(String key, List<int> bytes) {
149 try {
150 File tempFile = _getFileForKey(_tempName);
151 tempFile.writeAsBytesSync(bytes);
152 File file = _getFileForKey(key);
153 tempFile.renameSync(file.path);
154 } catch (_) {}
155 }
156
157 File _getFileForKey(String key) {
158 return new File(join(_cachePath, key));
159 }
160 }
161
162 /**
163 * The request that is sent from the main isolate to the clean-up isolate.
164 */
165 class _CacheCleanUpRequest {
166 final String cachePath;
167 final int maxSizeBytes;
168 final SendPort replyTo;
169
170 _CacheCleanUpRequest(this.cachePath, this.maxSizeBytes, this.replyTo);
171 }
OLDNEW
« no previous file with comments | « pkg/analysis_server/lib/src/analysis_server.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698