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

Side by Side Diff: pkg/front_end/lib/src/incremental/file_byte_store.dart

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

Powered by Google App Engine
This is Rietveld 408576698