| Index: mojo/public/dart/third_party/barback/lib/src/utils/file_pool.dart
|
| diff --git a/mojo/public/dart/third_party/barback/lib/src/utils/file_pool.dart b/mojo/public/dart/third_party/barback/lib/src/utils/file_pool.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..6a233379daa786e96ee4ad2deba3c4704516b030
|
| --- /dev/null
|
| +++ b/mojo/public/dart/third_party/barback/lib/src/utils/file_pool.dart
|
| @@ -0,0 +1,66 @@
|
| +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
| +// for details. All rights reserved. Use of this source code is governed by a
|
| +// BSD-style license that can be found in the LICENSE file.
|
| +
|
| +library barback.utils.file_pool;
|
| +
|
| +import 'dart:async';
|
| +import 'dart:convert';
|
| +import 'dart:io';
|
| +
|
| +import 'package:pool/pool.dart';
|
| +import 'package:stack_trace/stack_trace.dart';
|
| +
|
| +import '../utils.dart';
|
| +
|
| +/// Manages a pool of files that are opened for reading to cope with maximum
|
| +/// file descriptor limits.
|
| +///
|
| +/// If a file cannot be opened because too many files are already open, this
|
| +/// will defer the open until a previously opened file is closed and then try
|
| +/// again. If this doesn't succeed after a certain amount of time, the open
|
| +/// will fail and the original "too many files" exception will be thrown.
|
| +class FilePool {
|
| + /// The underlying pool.
|
| + ///
|
| + /// The maximum number of allocated descriptors is based on empirical tests
|
| + /// that indicate that beyond 32, additional file reads don't provide
|
| + /// substantial additional throughput.
|
| + final Pool _pool = new Pool(32, timeout: new Duration(seconds: 60));
|
| +
|
| + /// Opens the file at [path] for reading.
|
| + ///
|
| + /// When the returned stream is listened to, if there are too many files
|
| + /// open, this will wait for a previously opened file to be closed and then
|
| + /// try again.
|
| + Stream<List<int>> openRead(String path) {
|
| + return futureStream(_pool.request().then((resource) {
|
| + return Chain.track(new File(path).openRead()).transform(
|
| + new StreamTransformer.fromHandlers(handleDone: (sink) {
|
| + sink.close();
|
| + resource.release();
|
| + }));
|
| + }));
|
| + }
|
| +
|
| + /// Reads [path] as a string using [encoding].
|
| + ///
|
| + /// If there are too many files open and the read fails, this will wait for
|
| + /// a previously opened file to be closed and then try again.
|
| + Future<String> readAsString(String path, Encoding encoding) {
|
| + return _readAsBytes(path).then(encoding.decode);
|
| + }
|
| +
|
| + /// Reads [path] as a list of bytes, using [openRead] to retry if there are
|
| + /// failures.
|
| + Future<List<int>> _readAsBytes(String path) {
|
| + var completer = new Completer<List<int>>();
|
| + var builder = new BytesBuilder();
|
| +
|
| + openRead(path).listen(builder.add, onDone: () {
|
| + completer.complete(builder.takeBytes());
|
| + }, onError: completer.completeError, cancelOnError: true);
|
| +
|
| + return completer.future;
|
| + }
|
| +}
|
|
|