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

Side by Side Diff: sdk/lib/io/file_impl.dart

Issue 1892623002: Fixes leak of native File objects. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Address comments Created 4 years, 8 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 | « sdk/lib/io/file.dart ('k') | tests/standalone/io/file_lock_test.dart » ('j') | 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) 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
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);
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 = -1]) {
924 if ((start != null && start is !int) || 931 if ((mode is !FileLock) || (start is !int) || (end is !int)) {
925 (end != null && end is !int) ||
926 mode is !FileLock) {
927 throw new ArgumentError(); 932 throw new ArgumentError();
928 } 933 }
929 if (start == null) start = 0; 934 if ((start < 0) || (end < -1) || ((end != -1) && (start >= end))) {
930 if (end == null) end = -1;
931 if (start < 0 || end < -1 || (end != -1 && start >= end)) {
932 throw new ArgumentError(); 935 throw new ArgumentError();
933 } 936 }
934 int lock = mode == FileLock.EXCLUSIVE ? LOCK_EXCLUSIVE : LOCK_SHARED; 937 int lock = (mode == FileLock.EXCLUSIVE) ? LOCK_EXCLUSIVE : LOCK_SHARED;
935 return _dispatch(_FILE_LOCK, [_id, lock, start, end]) 938 return _dispatch(_FILE_LOCK, [_pointer(), lock, start, end])
936 .then((response) { 939 .then((response) {
937 if (_isErrorResponse(response)) { 940 if (_isErrorResponse(response)) {
938 throw _exceptionFromResponse(response, 'lock failed', path); 941 throw _exceptionFromResponse(response, 'lock failed', path);
939 } 942 }
940 return this; 943 return this;
941 }); 944 });
942 } 945 }
943 946
944 Future<RandomAccessFile> unlock([int start = 0, int end]) { 947 Future<RandomAccessFile> unlock([int start = 0, int end = -1]) {
945 if ((start != null && start is !int) || 948 if ((start is !int) || (end is !int)) {
946 (end != null && end is !int)) {
947 throw new ArgumentError(); 949 throw new ArgumentError();
948 } 950 }
949 if (start == null) start = 0; 951 if (start == end) {
950 if (end == null) end = -1; 952 throw new ArgumentError();
951 if (start == end) throw new ArgumentError(); 953 }
952 return _dispatch(_FILE_LOCK, [_id, LOCK_UNLOCK, start, end]) 954 return _dispatch(_FILE_LOCK, [_pointer(), LOCK_UNLOCK, start, end])
953 .then((response) { 955 .then((response) {
954 if (_isErrorResponse(response)) { 956 if (_isErrorResponse(response)) {
955 throw _exceptionFromResponse(response, 'unlock failed', path); 957 throw _exceptionFromResponse(response, 'unlock failed', path);
956 } 958 }
957 return this; 959 return this;
958 }); 960 });
959 } 961 }
960 962
961 external static _lock(int id, int lock, int start, int end); 963 void lockSync(
962 964 [FileLock mode = FileLock.EXCLUSIVE, int start = 0, int end = -1]) {
963 void lockSync([FileLock mode = FileLock.EXCLUSIVE, int start = 0, int end]) {
964 _checkAvailable(); 965 _checkAvailable();
965 if ((start != null && start is !int) || 966 if ((mode is !FileLock) || (start is !int) || (end is !int)) {
966 (end != null && end is !int) ||
967 mode is !FileLock) {
968 throw new ArgumentError(); 967 throw new ArgumentError();
969 } 968 }
970 if (start == null) start = 0; 969 if ((start < 0) || (end < -1) || ((end != -1) && (start >= end))) {
971 if (end == null) end = -1;
972 if (start < 0 || end < -1 || (end != -1 && start >= end)) {
973 throw new ArgumentError(); 970 throw new ArgumentError();
974 } 971 }
975 int lock = mode == FileLock.EXCLUSIVE ? LOCK_EXCLUSIVE : LOCK_SHARED; 972 int lock = (mode == FileLock.EXCLUSIVE) ? LOCK_EXCLUSIVE : LOCK_SHARED;
976 var result = _lock(_id, lock, start, end); 973 var result = _ops.lock(lock, start, end);
977 if (result is OSError) { 974 if (result is OSError) {
978 throw new FileSystemException('lock failed', path, result); 975 throw new FileSystemException('lock failed', path, result);
979 } 976 }
980 } 977 }
981 978
982 void unlockSync([int start = 0, int end]) { 979 void unlockSync([int start = 0, int end = -1]) {
983 _checkAvailable(); 980 _checkAvailable();
984 if ((start != null && start is !int) || 981 if ((start is !int) || (end is !int)) {
985 (end != null && end is !int)) {
986 throw new ArgumentError(); 982 throw new ArgumentError();
987 } 983 }
988 if (start == null) start = 0; 984 if (start == end) {
989 if (end == null) end = -1; 985 throw new ArgumentError();
990 if (start == end) throw new ArgumentError(); 986 }
991 var result = _lock(_id, LOCK_UNLOCK, start, end); 987 var result = _ops.lock(LOCK_UNLOCK, start, end);
992 if (result is OSError) { 988 if (result is OSError) {
993 throw new FileSystemException('unlock failed', path, result); 989 throw new FileSystemException('unlock failed', path, result);
994 } 990 }
995 } 991 }
996 992
997 bool get closed => _id == 0; 993 bool closed = false;
998 994
999 Future _dispatch(int request, List data, { bool markClosed: false }) { 995 Future _dispatch(int request, List data, { bool markClosed: false }) {
1000 if (closed) { 996 if (closed) {
1001 return new Future.error(new FileSystemException("File closed", path)); 997 return new Future.error(new FileSystemException("File closed", path));
1002 } 998 }
1003 if (_asyncDispatched) { 999 if (_asyncDispatched) {
1004 var msg = "An async operation is currently pending"; 1000 var msg = "An async operation is currently pending";
1005 return new Future.error(new FileSystemException(msg, path)); 1001 return new Future.error(new FileSystemException(msg, path));
1006 } 1002 }
1007 if (markClosed) { 1003 if (markClosed) {
1008 // Set the id_ to 0 (NULL) to ensure the no more async requests 1004 // Set closed to true to ensure that no more async requests can be issued
1009 // can be issued for this file. 1005 // for this file.
1010 _id = 0; 1006 closed = true;
1011 } 1007 }
1012 _asyncDispatched = true; 1008 _asyncDispatched = true;
1013 return _IOService._dispatch(request, data) 1009 return _IOService._dispatch(request, data)
1014 .whenComplete(() { 1010 .whenComplete(() {
1015 _asyncDispatched = false; 1011 _asyncDispatched = false;
1016 }); 1012 });
1017 } 1013 }
1018 1014
1019 void _checkAvailable() { 1015 void _checkAvailable() {
1020 if (_asyncDispatched) { 1016 if (_asyncDispatched) {
1021 throw new FileSystemException("An async operation is currently pending", 1017 throw new FileSystemException("An async operation is currently pending",
1022 path); 1018 path);
1023 } 1019 }
1024 if (closed) { 1020 if (closed) {
1025 throw new FileSystemException("File closed", path); 1021 throw new FileSystemException("File closed", path);
1026 } 1022 }
1027 } 1023 }
1028 } 1024 }
OLDNEW
« no previous file with comments | « sdk/lib/io/file.dart ('k') | tests/standalone/io/file_lock_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698