Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 part of dart.io; | 5 part of dart.io; |
| 6 | 6 |
| 7 // Read the file in blocks of size 64k. | 7 // Read the file in blocks of size 64k. |
| 8 const int _BLOCK_SIZE = 64 * 1024; | 8 const int _BLOCK_SIZE = 64 * 1024; |
| 9 | 9 |
| 10 | 10 |
| (...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 557 | 557 |
| 558 String toString() => "File: '$path'"; | 558 String toString() => "File: '$path'"; |
| 559 | 559 |
| 560 static throwIfError(Object result, String msg, String path) { | 560 static throwIfError(Object result, String msg, String path) { |
| 561 if (result is OSError) { | 561 if (result is OSError) { |
| 562 throw new FileSystemException(msg, path, result); | 562 throw new FileSystemException(msg, path, result); |
| 563 } | 563 } |
| 564 } | 564 } |
| 565 } | 565 } |
| 566 | 566 |
| 567 abstract class _RandomAccessFileOps { | |
| 568 external factory _RandomAccessFileOps(int pointer); | |
|
Ivan Posva
2016/04/20 05:31:06
Needs a patch in sdk/lib/_internal/js_runtime/lib/
zra
2016/04/20 17:07:52
Done.
| |
| 567 | 569 |
| 568 class _RandomAccessFile | 570 int getPointer(); |
| 569 implements RandomAccessFile { | 571 int close(); |
| 572 readByte(); | |
| 573 read(int bytes); | |
| 574 readInto(List<int> buffer, int start, int end); | |
| 575 writeByte(int value); | |
| 576 writeFrom(List<int> buffer, int start, int end); | |
| 577 position(); | |
| 578 setPosition(int position); | |
| 579 truncate(int length); | |
| 580 length(); | |
| 581 flush(); | |
| 582 lock(int lock, int start, int end); | |
| 583 } | |
| 584 | |
| 585 class _RandomAccessFile implements RandomAccessFile { | |
| 570 static bool _connectedResourceHandler = false; | 586 static bool _connectedResourceHandler = false; |
| 571 | 587 |
| 572 final String path; | 588 final String path; |
| 573 int _id; | 589 |
| 590 // Calling this function will increase the reference count on the native | |
| 591 // object that implements the file operations. It should only be called to | |
| 592 // pass the pointer to the IO Service, which will decrement the reference | |
| 593 // count when it is finished with it. | |
| 594 int _pointer() => _ops.getPointer(); | |
| 595 | |
| 574 bool _asyncDispatched = false; | 596 bool _asyncDispatched = false; |
| 575 SendPort _fileService; | 597 SendPort _fileService; |
| 576 | 598 |
| 577 _FileResourceInfo _resourceInfo; | 599 _FileResourceInfo _resourceInfo; |
| 600 _RandomAccessFileOps _ops; | |
| 578 | 601 |
| 579 _RandomAccessFile(this._id, this.path) { | 602 _RandomAccessFile(int pointer, this.path) { |
| 603 _ops = new _RandomAccessFileOps(pointer); | |
| 580 _resourceInfo = new _FileResourceInfo(this); | 604 _resourceInfo = new _FileResourceInfo(this); |
| 581 _maybeConnectHandler(); | 605 _maybeConnectHandler(); |
| 582 } | 606 } |
| 583 | 607 |
| 584 void _maybePerformCleanup() { | 608 void _maybePerformCleanup() { |
| 585 if (closed) { | 609 if (closed) { |
| 586 _FileResourceInfo.FileClosed(_resourceInfo); | 610 _FileResourceInfo.FileClosed(_resourceInfo); |
| 587 } | 611 } |
| 588 } | 612 } |
| 589 | 613 |
| 590 external static int _getFD(int id); | |
| 591 | |
| 592 _maybeConnectHandler() { | 614 _maybeConnectHandler() { |
| 593 if (!_connectedResourceHandler) { | 615 if (!_connectedResourceHandler) { |
| 594 // TODO(ricow): we probably need set these in some initialization code. | 616 // TODO(ricow): We probably need to set these in some initialization code. |
| 595 // We need to make sure that these are always awailable from the | 617 // We need to make sure that these are always available from the |
| 596 // observatory even if no files (or sockets for the socket ones) are | 618 // observatory even if no files (or sockets for the socket ones) are |
| 597 // open. | 619 // open. |
| 598 registerExtension('ext.dart.io.getOpenFiles', | 620 registerExtension('ext.dart.io.getOpenFiles', |
| 599 _FileResourceInfo.getOpenFiles); | 621 _FileResourceInfo.getOpenFiles); |
| 600 registerExtension('ext.dart.io.getFileByID', | 622 registerExtension('ext.dart.io.getFileByID', |
| 601 _FileResourceInfo.getFileInfoMapByID); | 623 _FileResourceInfo.getFileInfoMapByID); |
| 602 _connectedResourceHandler = true; | 624 _connectedResourceHandler = true; |
| 603 } | 625 } |
| 604 } | 626 } |
| 605 | 627 |
| 606 Future<RandomAccessFile> close() { | 628 Future<RandomAccessFile> close() { |
| 607 return _dispatch(_FILE_CLOSE, [_id], markClosed: true).then((result) { | 629 return _dispatch(_FILE_CLOSE, [_pointer()], markClosed: true).then((result) { |
| 608 if (result != -1) { | 630 if (result != -1) { |
| 609 _id = result; | 631 closed = closed || (result == 0); |
| 610 _maybePerformCleanup(); | 632 _maybePerformCleanup(); |
| 611 return this; | 633 return this; |
| 612 } else { | 634 } else { |
| 613 throw new FileSystemException("Cannot close file", path); | 635 throw new FileSystemException("Cannot close file", path); |
| 614 } | 636 } |
| 615 }); | 637 }); |
| 616 } | 638 } |
| 617 | 639 |
| 618 external static int _close(int id); | |
| 619 | |
| 620 void closeSync() { | 640 void closeSync() { |
| 621 _checkAvailable(); | 641 _checkAvailable(); |
| 622 var id = _close(_id); | 642 var id = _ops.close(); |
| 623 if (id == -1) { | 643 if (id == -1) { |
| 624 throw new FileSystemException("Cannot close file", path); | 644 throw new FileSystemException("Cannot close file", path); |
| 625 } | 645 } |
| 626 _id = id; | 646 closed = closed || (id == 0); |
| 627 _maybePerformCleanup(); | 647 _maybePerformCleanup(); |
| 628 } | 648 } |
| 629 | 649 |
| 630 Future<int> readByte() { | 650 Future<int> readByte() { |
| 631 return _dispatch(_FILE_READ_BYTE, [_id]).then((response) { | 651 return _dispatch(_FILE_READ_BYTE, [_pointer()]).then((response) { |
| 632 if (_isErrorResponse(response)) { | 652 if (_isErrorResponse(response)) { |
| 633 throw _exceptionFromResponse(response, "readByte failed", path); | 653 throw _exceptionFromResponse(response, "readByte failed", path); |
| 634 } | 654 } |
| 635 _resourceInfo.addRead(1); | 655 _resourceInfo.addRead(1); |
| 636 return response; | 656 return response; |
| 637 }); | 657 }); |
| 638 } | 658 } |
| 639 | 659 |
| 640 external static _readByte(int id); | |
| 641 | |
| 642 int readByteSync() { | 660 int readByteSync() { |
| 643 _checkAvailable(); | 661 _checkAvailable(); |
| 644 var result = _readByte(_id); | 662 var result = _ops.readByte(); |
| 645 if (result is OSError) { | 663 if (result is OSError) { |
| 646 throw new FileSystemException("readByte failed", path, result); | 664 throw new FileSystemException("readByte failed", path, result); |
| 647 } | 665 } |
| 648 _resourceInfo.addRead(1); | 666 _resourceInfo.addRead(1); |
| 649 return result; | 667 return result; |
| 650 } | 668 } |
| 651 | 669 |
| 652 Future<List<int>> read(int bytes) { | 670 Future<List<int>> read(int bytes) { |
| 653 if (bytes is !int) { | 671 if (bytes is !int) { |
| 654 throw new ArgumentError(bytes); | 672 throw new ArgumentError(bytes); |
| 655 } | 673 } |
| 656 return _dispatch(_FILE_READ, [_id, bytes]).then((response) { | 674 return _dispatch(_FILE_READ, [_pointer(), bytes]).then((response) { |
| 657 if (_isErrorResponse(response)) { | 675 if (_isErrorResponse(response)) { |
| 658 throw _exceptionFromResponse(response, "read failed", path); | 676 throw _exceptionFromResponse(response, "read failed", path); |
| 659 } | 677 } |
| 660 _resourceInfo.addRead(response[1].length); | 678 _resourceInfo.addRead(response[1].length); |
| 661 return response[1]; | 679 return response[1]; |
| 662 }); | 680 }); |
| 663 } | 681 } |
| 664 | 682 |
| 665 external static _read(int id, int bytes); | |
| 666 | |
| 667 List<int> readSync(int bytes) { | 683 List<int> readSync(int bytes) { |
| 668 _checkAvailable(); | 684 _checkAvailable(); |
| 669 if (bytes is !int) { | 685 if (bytes is !int) { |
| 670 throw new ArgumentError(bytes); | 686 throw new ArgumentError(bytes); |
| 671 } | 687 } |
| 672 var result = _read(_id, bytes); | 688 var result = _ops.read(bytes); |
| 673 if (result is OSError) { | 689 if (result is OSError) { |
| 674 throw new FileSystemException("readSync failed", path, result); | 690 throw new FileSystemException("readSync failed", path, result); |
| 675 } | 691 } |
| 676 _resourceInfo.addRead(result.length); | 692 _resourceInfo.addRead(result.length); |
| 677 return result; | 693 return result; |
| 678 } | 694 } |
| 679 | 695 |
| 680 Future<int> readInto(List<int> buffer, [int start = 0, int end]) { | 696 Future<int> readInto(List<int> buffer, [int start = 0, int end]) { |
| 681 if (buffer is !List || | 697 if ((buffer is !List) || |
| 682 (start != null && start is !int) || | 698 ((start != null) && (start is !int)) || |
| 683 (end != null && end is !int)) { | 699 ((end != null) && (end is !int))) { |
| 684 throw new ArgumentError(); | 700 throw new ArgumentError(); |
| 685 } | 701 } |
| 686 end = RangeError.checkValidRange(start, end, buffer.length); | 702 end = RangeError.checkValidRange(start, end, buffer.length); |
| 687 if (end == start) return new Future.value(0); | 703 if (end == start) { |
| 704 return new Future.value(0); | |
| 705 } | |
| 688 int length = end - start; | 706 int length = end - start; |
| 689 return _dispatch(_FILE_READ_INTO, [_id, length]).then((response) { | 707 return _dispatch(_FILE_READ_INTO, [_pointer(), length]).then((response) { |
| 690 if (_isErrorResponse(response)) { | 708 if (_isErrorResponse(response)) { |
| 691 throw _exceptionFromResponse(response, "readInto failed", path); | 709 throw _exceptionFromResponse(response, "readInto failed", path); |
| 692 } | 710 } |
| 693 var read = response[1]; | 711 var read = response[1]; |
| 694 var data = response[2]; | 712 var data = response[2]; |
| 695 buffer.setRange(start, start + read, data); | 713 buffer.setRange(start, start + read, data); |
| 696 _resourceInfo.addRead(read); | 714 _resourceInfo.addRead(read); |
| 697 return read; | 715 return read; |
| 698 }); | 716 }); |
| 699 } | 717 } |
| 700 | 718 |
| 701 external static _readInto(int id, List<int> buffer, int start, int end); | |
| 702 | |
| 703 int readIntoSync(List<int> buffer, [int start = 0, int end]) { | 719 int readIntoSync(List<int> buffer, [int start = 0, int end]) { |
| 704 _checkAvailable(); | 720 _checkAvailable(); |
| 705 if (buffer is !List || | 721 if ((buffer is !List) || |
| 706 (start != null && start is !int) || | 722 ((start != null) && (start is !int)) || |
| 707 (end != null && end is !int)) { | 723 ((end != null) && (end is !int))) { |
| 708 throw new ArgumentError(); | 724 throw new ArgumentError(); |
| 709 } | 725 } |
| 710 end = RangeError.checkValidRange(start, end, buffer.length); | 726 end = RangeError.checkValidRange(start, end, buffer.length); |
| 711 if (end == start) return 0; | 727 if (end == start) { |
| 712 var result = _readInto(_id, buffer, start, end); | 728 return 0; |
| 729 } | |
| 730 var result = _ops.readInto(buffer, start, end); | |
| 713 if (result is OSError) { | 731 if (result is OSError) { |
| 714 throw new FileSystemException("readInto failed", path, result); | 732 throw new FileSystemException("readInto failed", path, result); |
| 715 } | 733 } |
| 716 _resourceInfo.addRead(result); | 734 _resourceInfo.addRead(result); |
| 717 return result; | 735 return result; |
| 718 } | 736 } |
| 719 | 737 |
| 720 Future<RandomAccessFile> writeByte(int value) { | 738 Future<RandomAccessFile> writeByte(int value) { |
| 721 if (value is !int) { | 739 if (value is !int) { |
| 722 throw new ArgumentError(value); | 740 throw new ArgumentError(value); |
| 723 } | 741 } |
| 724 return _dispatch(_FILE_WRITE_BYTE, [_id, value]).then((response) { | 742 return _dispatch(_FILE_WRITE_BYTE, [_pointer(), value]).then((response) { |
| 725 if (_isErrorResponse(response)) { | 743 if (_isErrorResponse(response)) { |
| 726 throw _exceptionFromResponse(response, "writeByte failed", path); | 744 throw _exceptionFromResponse(response, "writeByte failed", path); |
| 727 } | 745 } |
| 728 _resourceInfo.addWrite(1); | 746 _resourceInfo.addWrite(1); |
| 729 return this; | 747 return this; |
| 730 }); | 748 }); |
| 731 } | 749 } |
| 732 | 750 |
| 733 external static _writeByte(int id, int value); | |
| 734 | |
| 735 int writeByteSync(int value) { | 751 int writeByteSync(int value) { |
| 736 _checkAvailable(); | 752 _checkAvailable(); |
| 737 if (value is !int) { | 753 if (value is !int) { |
| 738 throw new ArgumentError(value); | 754 throw new ArgumentError(value); |
| 739 } | 755 } |
| 740 var result = _writeByte(_id, value); | 756 var result = _ops.writeByte(value); |
| 741 if (result is OSError) { | 757 if (result is OSError) { |
| 742 throw new FileSystemException("writeByte failed", path, result); | 758 throw new FileSystemException("writeByte failed", path, result); |
| 743 } | 759 } |
| 744 _resourceInfo.addWrite(1); | 760 _resourceInfo.addWrite(1); |
| 745 return result; | 761 return result; |
| 746 } | 762 } |
| 747 | 763 |
| 748 Future<RandomAccessFile> writeFrom( | 764 Future<RandomAccessFile> writeFrom( |
| 749 List<int> buffer, [int start = 0, int end]) { | 765 List<int> buffer, [int start = 0, int end]) { |
| 750 if ((buffer is !List) || | 766 if ((buffer is !List) || |
| 751 (start != null && start is !int) || | 767 ((start != null) && (start is !int)) || |
| 752 (end != null && end is !int)) { | 768 ((end != null) && (end is !int))) { |
| 753 throw new ArgumentError("Invalid arguments to writeFrom"); | 769 throw new ArgumentError("Invalid arguments to writeFrom"); |
| 754 } | 770 } |
| 755 end = RangeError.checkValidRange(start, end, buffer.length); | 771 end = RangeError.checkValidRange(start, end, buffer.length); |
| 756 if (end == start) return new Future.value(this); | 772 if (end == start) { |
| 773 return new Future.value(this); | |
| 774 } | |
| 757 _BufferAndStart result; | 775 _BufferAndStart result; |
| 758 try { | 776 try { |
| 759 result = _ensureFastAndSerializableByteData(buffer, start, end); | 777 result = _ensureFastAndSerializableByteData(buffer, start, end); |
| 760 } catch (e) { | 778 } catch (e) { |
| 761 return new Future.error(e); | 779 return new Future.error(e); |
| 762 } | 780 } |
| 763 | 781 |
| 764 List request = new List(4); | 782 List request = new List(4); |
| 765 request[0] = _id; | 783 request[0] = _pointer(); |
| 766 request[1] = result.buffer; | 784 request[1] = result.buffer; |
| 767 request[2] = result.start; | 785 request[2] = result.start; |
| 768 request[3] = end - (start - result.start); | 786 request[3] = end - (start - result.start); |
| 769 return _dispatch(_FILE_WRITE_FROM, request).then((response) { | 787 return _dispatch(_FILE_WRITE_FROM, request).then((response) { |
| 770 if (_isErrorResponse(response)) { | 788 if (_isErrorResponse(response)) { |
| 771 throw _exceptionFromResponse(response, "writeFrom failed", path); | 789 throw _exceptionFromResponse(response, "writeFrom failed", path); |
| 772 } | 790 } |
| 773 _resourceInfo.addWrite(end - (start - result.start)); | 791 _resourceInfo.addWrite(end - (start - result.start)); |
| 774 return this; | 792 return this; |
| 775 }); | 793 }); |
| 776 } | 794 } |
| 777 | 795 |
| 778 external static _writeFrom(int id, List<int> buffer, int start, int end); | |
| 779 | |
| 780 void writeFromSync(List<int> buffer, [int start = 0, int end]) { | 796 void writeFromSync(List<int> buffer, [int start = 0, int end]) { |
| 781 _checkAvailable(); | 797 _checkAvailable(); |
| 782 if (buffer is !List || | 798 if ((buffer is !List) || |
| 783 (start != null && start is !int) || | 799 ((start != null) && (start is !int)) || |
| 784 (end != null && end is !int)) { | 800 ((end != null) && (end is !int))) { |
| 785 throw new ArgumentError("Invalid arguments to writeFromSync"); | 801 throw new ArgumentError("Invalid arguments to writeFromSync"); |
| 786 } | 802 } |
| 787 end = RangeError.checkValidRange(start, end, buffer.length); | 803 end = RangeError.checkValidRange(start, end, buffer.length); |
| 788 if (end == start) return; | 804 if (end == start) { |
| 805 return; | |
| 806 } | |
| 789 _BufferAndStart bufferAndStart = | 807 _BufferAndStart bufferAndStart = |
| 790 _ensureFastAndSerializableByteData(buffer, start, end); | 808 _ensureFastAndSerializableByteData(buffer, start, end); |
| 791 var result = _writeFrom(_id, | 809 var result = _ops.writeFrom(bufferAndStart.buffer, |
| 792 bufferAndStart.buffer, | 810 bufferAndStart.start, |
| 793 bufferAndStart.start, | 811 end - (start - bufferAndStart.start)); |
| 794 end - (start - bufferAndStart.start)); | |
| 795 if (result is OSError) { | 812 if (result is OSError) { |
| 796 throw new FileSystemException("writeFrom failed", path, result); | 813 throw new FileSystemException("writeFrom failed", path, result); |
| 797 } | 814 } |
| 798 _resourceInfo.addWrite(end - (start - bufferAndStart.start)); | 815 _resourceInfo.addWrite(end - (start - bufferAndStart.start)); |
| 799 } | 816 } |
| 800 | 817 |
| 801 Future<RandomAccessFile> writeString(String string, | 818 Future<RandomAccessFile> writeString(String string, |
| 802 {Encoding encoding: UTF8}) { | 819 {Encoding encoding: UTF8}) { |
| 803 if (encoding is! Encoding) { | 820 if (encoding is! Encoding) { |
| 804 throw new ArgumentError(encoding); | 821 throw new ArgumentError(encoding); |
| 805 } | 822 } |
| 806 var data = encoding.encode(string); | 823 var data = encoding.encode(string); |
| 807 return writeFrom(data, 0, data.length); | 824 return writeFrom(data, 0, data.length); |
| 808 } | 825 } |
| 809 | 826 |
| 810 void writeStringSync(String string, {Encoding encoding: UTF8}) { | 827 void writeStringSync(String string, {Encoding encoding: UTF8}) { |
| 811 if (encoding is! Encoding) { | 828 if (encoding is! Encoding) { |
| 812 throw new ArgumentError(encoding); | 829 throw new ArgumentError(encoding); |
| 813 } | 830 } |
| 814 var data = encoding.encode(string); | 831 var data = encoding.encode(string); |
| 815 writeFromSync(data, 0, data.length); | 832 writeFromSync(data, 0, data.length); |
| 816 } | 833 } |
| 817 | 834 |
| 818 Future<int> position() { | 835 Future<int> position() { |
| 819 return _dispatch(_FILE_POSITION, [_id]).then((response) { | 836 return _dispatch(_FILE_POSITION, [_pointer()]).then((response) { |
| 820 if (_isErrorResponse(response)) { | 837 if (_isErrorResponse(response)) { |
| 821 throw _exceptionFromResponse(response, "position failed", path); | 838 throw _exceptionFromResponse(response, "position failed", path); |
| 822 } | 839 } |
| 823 return response; | 840 return response; |
| 824 }); | 841 }); |
| 825 } | 842 } |
| 826 | 843 |
| 827 external static _position(int id); | |
| 828 | |
| 829 int positionSync() { | 844 int positionSync() { |
| 830 _checkAvailable(); | 845 _checkAvailable(); |
| 831 var result = _position(_id); | 846 var result = _ops.position(); |
| 832 if (result is OSError) { | 847 if (result is OSError) { |
| 833 throw new FileSystemException("position failed", path, result); | 848 throw new FileSystemException("position failed", path, result); |
| 834 } | 849 } |
| 835 return result; | 850 return result; |
| 836 } | 851 } |
| 837 | 852 |
| 838 Future<RandomAccessFile> setPosition(int position) { | 853 Future<RandomAccessFile> setPosition(int position) { |
| 839 return _dispatch(_FILE_SET_POSITION, [_id, position]) | 854 return _dispatch(_FILE_SET_POSITION, [_pointer(), position]) |
| 840 .then((response) { | 855 .then((response) { |
| 841 if (_isErrorResponse(response)) { | 856 if (_isErrorResponse(response)) { |
| 842 throw _exceptionFromResponse(response, "setPosition failed", path); | 857 throw _exceptionFromResponse(response, "setPosition failed", path); |
| 843 } | 858 } |
| 844 return this; | 859 return this; |
| 845 }); | 860 }); |
| 846 } | 861 } |
| 847 | 862 |
| 848 external static _setPosition(int id, int position); | |
| 849 | |
| 850 void setPositionSync(int position) { | 863 void setPositionSync(int position) { |
| 851 _checkAvailable(); | 864 _checkAvailable(); |
| 852 var result = _setPosition(_id, position); | 865 var result = _ops.setPosition(position); |
| 853 if (result is OSError) { | 866 if (result is OSError) { |
| 854 throw new FileSystemException("setPosition failed", path, result); | 867 throw new FileSystemException("setPosition failed", path, result); |
| 855 } | 868 } |
| 856 } | 869 } |
| 857 | 870 |
| 858 Future<RandomAccessFile> truncate(int length) { | 871 Future<RandomAccessFile> truncate(int length) { |
| 859 return _dispatch(_FILE_TRUNCATE, [_id, length]).then((response) { | 872 return _dispatch(_FILE_TRUNCATE, [_pointer(), length]).then((response) { |
| 860 if (_isErrorResponse(response)) { | 873 if (_isErrorResponse(response)) { |
| 861 throw _exceptionFromResponse(response, "truncate failed", path); | 874 throw _exceptionFromResponse(response, "truncate failed", path); |
| 862 } | 875 } |
| 863 return this; | 876 return this; |
| 864 }); | 877 }); |
| 865 } | 878 } |
| 866 | 879 |
| 867 external static _truncate(int id, int length); | |
| 868 | |
| 869 void truncateSync(int length) { | 880 void truncateSync(int length) { |
| 870 _checkAvailable(); | 881 _checkAvailable(); |
| 871 var result = _truncate(_id, length); | 882 var result = _ops.truncate(length); |
| 872 if (result is OSError) { | 883 if (result is OSError) { |
| 873 throw new FileSystemException("truncate failed", path, result); | 884 throw new FileSystemException("truncate failed", path, result); |
| 874 } | 885 } |
| 875 } | 886 } |
| 876 | 887 |
| 877 Future<int> length() { | 888 Future<int> length() { |
| 878 return _dispatch(_FILE_LENGTH, [_id]).then((response) { | 889 return _dispatch(_FILE_LENGTH, [_pointer()]).then((response) { |
| 879 if (_isErrorResponse(response)) { | 890 if (_isErrorResponse(response)) { |
| 880 throw _exceptionFromResponse(response, "length failed", path); | 891 throw _exceptionFromResponse(response, "length failed", path); |
| 881 } | 892 } |
| 882 return response; | 893 return response; |
| 883 }); | 894 }); |
| 884 } | 895 } |
| 885 | 896 |
| 886 external static _length(int id); | |
| 887 | |
| 888 int lengthSync() { | 897 int lengthSync() { |
| 889 _checkAvailable(); | 898 _checkAvailable(); |
| 890 var result = _length(_id); | 899 var result = _ops.length(); |
| 891 if (result is OSError) { | 900 if (result is OSError) { |
| 892 throw new FileSystemException("length failed", path, result); | 901 throw new FileSystemException("length failed", path, result); |
| 893 } | 902 } |
| 894 return result; | 903 return result; |
| 895 } | 904 } |
| 896 | 905 |
| 897 Future<RandomAccessFile> flush() { | 906 Future<RandomAccessFile> flush() { |
| 898 return _dispatch(_FILE_FLUSH, [_id]).then((response) { | 907 return _dispatch(_FILE_FLUSH, [_pointer()]).then((response) { |
| 899 if (_isErrorResponse(response)) { | 908 if (_isErrorResponse(response)) { |
| 900 throw _exceptionFromResponse(response, | 909 throw _exceptionFromResponse(response, |
| 901 "flush failed", | 910 "flush failed", |
| 902 path); | 911 path); |
| 903 } | 912 } |
| 904 return this; | 913 return this; |
| 905 }); | 914 }); |
| 906 } | 915 } |
| 907 | 916 |
| 908 external static _flush(int id); | |
| 909 | |
| 910 void flushSync() { | 917 void flushSync() { |
| 911 _checkAvailable(); | 918 _checkAvailable(); |
| 912 var result = _flush(_id); | 919 var result = _ops.flush(); |
| 913 if (result is OSError) { | 920 if (result is OSError) { |
| 914 throw new FileSystemException("flush failed", path, result); | 921 throw new FileSystemException("flush failed", path, result); |
| 915 } | 922 } |
| 916 } | 923 } |
| 917 | 924 |
| 918 static final int LOCK_UNLOCK = 0; | 925 static final int LOCK_UNLOCK = 0; |
| 919 static final int LOCK_SHARED = 1; | 926 static final int LOCK_SHARED = 1; |
| 920 static final int LOCK_EXCLUSIVE = 2; | 927 static final int LOCK_EXCLUSIVE = 2; |
| 921 | 928 |
| 922 Future<RandomAccessFile> lock( | 929 Future<RandomAccessFile> lock( |
| 923 [FileLock mode = FileLock.EXCLUSIVE, int start = 0, int end]) { | 930 [FileLock mode = FileLock.EXCLUSIVE, int start = 0, int end]) { |
| 924 if ((start != null && start is !int) || | 931 if (((start != null) && (start is !int)) || |
| 925 (end != null && end is !int) || | 932 ((end != null) && (end is !int)) || |
| 926 mode is !FileLock) { | 933 (mode is !FileLock)) { |
| 927 throw new ArgumentError(); | 934 throw new ArgumentError(); |
| 928 } | 935 } |
| 929 if (start == null) start = 0; | 936 if (start == null) { |
| 930 if (end == null) end = -1; | 937 start = 0; |
| 931 if (start < 0 || end < -1 || (end != -1 && start >= end)) { | 938 } |
| 939 if (end == null) { | |
| 940 end = -1; | |
| 941 } | |
| 942 if ((start < 0) || (end < -1) || ((end != -1) && (start >= end))) { | |
| 932 throw new ArgumentError(); | 943 throw new ArgumentError(); |
| 933 } | 944 } |
| 934 int lock = mode == FileLock.EXCLUSIVE ? LOCK_EXCLUSIVE : LOCK_SHARED; | 945 int lock = (mode == FileLock.EXCLUSIVE) ? LOCK_EXCLUSIVE : LOCK_SHARED; |
| 935 return _dispatch(_FILE_LOCK, [_id, lock, start, end]) | 946 return _dispatch(_FILE_LOCK, [_pointer(), lock, start, end]) |
| 936 .then((response) { | 947 .then((response) { |
| 937 if (_isErrorResponse(response)) { | 948 if (_isErrorResponse(response)) { |
| 938 throw _exceptionFromResponse(response, 'lock failed', path); | 949 throw _exceptionFromResponse(response, 'lock failed', path); |
| 939 } | 950 } |
| 940 return this; | 951 return this; |
| 941 }); | 952 }); |
| 942 } | 953 } |
| 943 | 954 |
| 944 Future<RandomAccessFile> unlock([int start = 0, int end]) { | 955 Future<RandomAccessFile> unlock([int start = 0, int end]) { |
| 945 if ((start != null && start is !int) || | 956 if (((start != null) && (start is !int)) || |
| 946 (end != null && end is !int)) { | 957 ((end != null) && (end is !int))) { |
| 947 throw new ArgumentError(); | 958 throw new ArgumentError(); |
| 948 } | 959 } |
| 949 if (start == null) start = 0; | 960 if (start == null) { |
| 950 if (end == null) end = -1; | 961 start = 0; |
| 951 if (start == end) throw new ArgumentError(); | 962 } |
| 952 return _dispatch(_FILE_LOCK, [_id, LOCK_UNLOCK, start, end]) | 963 if (end == null) { |
| 964 end = -1; | |
| 965 } | |
| 966 if (start == end) { | |
| 967 throw new ArgumentError(); | |
| 968 } | |
| 969 return _dispatch(_FILE_LOCK, [_pointer(), LOCK_UNLOCK, start, end]) | |
| 953 .then((response) { | 970 .then((response) { |
| 954 if (_isErrorResponse(response)) { | 971 if (_isErrorResponse(response)) { |
| 955 throw _exceptionFromResponse(response, 'unlock failed', path); | 972 throw _exceptionFromResponse(response, 'unlock failed', path); |
| 956 } | 973 } |
| 957 return this; | 974 return this; |
| 958 }); | 975 }); |
| 959 } | 976 } |
| 960 | 977 |
| 961 external static _lock(int id, int lock, int start, int end); | |
| 962 | |
| 963 void lockSync([FileLock mode = FileLock.EXCLUSIVE, int start = 0, int end]) { | 978 void lockSync([FileLock mode = FileLock.EXCLUSIVE, int start = 0, int end]) { |
| 964 _checkAvailable(); | 979 _checkAvailable(); |
| 965 if ((start != null && start is !int) || | 980 if (((start != null) && (start is !int)) || |
| 966 (end != null && end is !int) || | 981 ((end != null) && (end is !int)) || |
| 967 mode is !FileLock) { | 982 (mode is !FileLock)) { |
| 968 throw new ArgumentError(); | 983 throw new ArgumentError(); |
| 969 } | 984 } |
| 970 if (start == null) start = 0; | 985 if (start == null) { |
|
Ivan Posva
2016/04/20 05:31:06
This test is a bit confusing to say the least. It
zra
2016/04/20 17:07:52
Done.
| |
| 971 if (end == null) end = -1; | 986 start = 0; |
| 972 if (start < 0 || end < -1 || (end != -1 && start >= end)) { | 987 } |
| 988 if (end == null) { | |
| 989 end = -1; | |
| 990 } | |
| 991 if ((start < 0) || (end < -1) || ((end != -1) && (start >= end))) { | |
| 973 throw new ArgumentError(); | 992 throw new ArgumentError(); |
| 974 } | 993 } |
| 975 int lock = mode == FileLock.EXCLUSIVE ? LOCK_EXCLUSIVE : LOCK_SHARED; | 994 int lock = (mode == FileLock.EXCLUSIVE) ? LOCK_EXCLUSIVE : LOCK_SHARED; |
| 976 var result = _lock(_id, lock, start, end); | 995 var result = _ops.lock(lock, start, end); |
| 977 if (result is OSError) { | 996 if (result is OSError) { |
| 978 throw new FileSystemException('lock failed', path, result); | 997 throw new FileSystemException('lock failed', path, result); |
| 979 } | 998 } |
| 980 } | 999 } |
| 981 | 1000 |
| 982 void unlockSync([int start = 0, int end]) { | 1001 void unlockSync([int start = 0, int end]) { |
| 983 _checkAvailable(); | 1002 _checkAvailable(); |
| 984 if ((start != null && start is !int) || | 1003 if (((start != null) && (start is !int)) || |
| 985 (end != null && end is !int)) { | 1004 ((end != null) && (end is !int))) { |
| 986 throw new ArgumentError(); | 1005 throw new ArgumentError(); |
| 987 } | 1006 } |
| 988 if (start == null) start = 0; | 1007 if (start == null) { |
|
Ivan Posva
2016/04/20 05:31:06
ditto
zra
2016/04/20 17:07:52
Done.
| |
| 989 if (end == null) end = -1; | 1008 start = 0; |
| 990 if (start == end) throw new ArgumentError(); | 1009 } |
| 991 var result = _lock(_id, LOCK_UNLOCK, start, end); | 1010 if (end == null) { |
| 1011 end = -1; | |
| 1012 } | |
| 1013 if (start == end) { | |
| 1014 throw new ArgumentError(); | |
| 1015 } | |
| 1016 var result = _ops.lock(LOCK_UNLOCK, start, end); | |
| 992 if (result is OSError) { | 1017 if (result is OSError) { |
| 993 throw new FileSystemException('unlock failed', path, result); | 1018 throw new FileSystemException('unlock failed', path, result); |
| 994 } | 1019 } |
| 995 } | 1020 } |
| 996 | 1021 |
| 997 bool get closed => _id == 0; | 1022 bool closed = false; |
| 998 | 1023 |
| 999 Future _dispatch(int request, List data, { bool markClosed: false }) { | 1024 Future _dispatch(int request, List data, { bool markClosed: false }) { |
| 1000 if (closed) { | 1025 if (closed) { |
| 1001 return new Future.error(new FileSystemException("File closed", path)); | 1026 return new Future.error(new FileSystemException("File closed", path)); |
| 1002 } | 1027 } |
| 1003 if (_asyncDispatched) { | 1028 if (_asyncDispatched) { |
| 1004 var msg = "An async operation is currently pending"; | 1029 var msg = "An async operation is currently pending"; |
| 1005 return new Future.error(new FileSystemException(msg, path)); | 1030 return new Future.error(new FileSystemException(msg, path)); |
| 1006 } | 1031 } |
| 1007 if (markClosed) { | 1032 if (markClosed) { |
| 1008 // Set the id_ to 0 (NULL) to ensure the no more async requests | 1033 // Set closed to true to ensure that no more async requests can be issued |
| 1009 // can be issued for this file. | 1034 // for this file. |
| 1010 _id = 0; | 1035 closed = true; |
| 1011 } | 1036 } |
| 1012 _asyncDispatched = true; | 1037 _asyncDispatched = true; |
| 1013 return _IOService._dispatch(request, data) | 1038 return _IOService._dispatch(request, data) |
| 1014 .whenComplete(() { | 1039 .whenComplete(() { |
| 1015 _asyncDispatched = false; | 1040 _asyncDispatched = false; |
| 1016 }); | 1041 }); |
| 1017 } | 1042 } |
| 1018 | 1043 |
| 1019 void _checkAvailable() { | 1044 void _checkAvailable() { |
| 1020 if (_asyncDispatched) { | 1045 if (_asyncDispatched) { |
| 1021 throw new FileSystemException("An async operation is currently pending", | 1046 throw new FileSystemException("An async operation is currently pending", |
| 1022 path); | 1047 path); |
| 1023 } | 1048 } |
| 1024 if (closed) { | 1049 if (closed) { |
| 1025 throw new FileSystemException("File closed", path); | 1050 throw new FileSystemException("File closed", path); |
| 1026 } | 1051 } |
| 1027 } | 1052 } |
| 1028 } | 1053 } |
| OLD | NEW |