Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 class _FileInputStream extends _BaseDataInputStream implements InputStream { | 5 class _FileInputStream extends _BaseDataInputStream implements InputStream { |
| 6 _FileInputStream(RandomAccessFile this._file, int this._length) { | 6 _FileInputStream(RandomAccessFile this._file, int this._length) { |
| 7 _streamMarkedClosed = true; | 7 _streamMarkedClosed = true; |
| 8 _checkScheduleCallbacks(); | 8 _checkScheduleCallbacks(); |
| 9 } | 9 } |
| 10 | 10 |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 149 // the stream is fully closed. | 149 // the stream is fully closed. |
| 150 bool _closeCallbackCalled = false; | 150 bool _closeCallbackCalled = false; |
| 151 | 151 |
| 152 Timer _scheduledNoPendingWriteCallback; | 152 Timer _scheduledNoPendingWriteCallback; |
| 153 Timer _scheduledCloseCallback; | 153 Timer _scheduledCloseCallback; |
| 154 Function _noPendingWriteHandler; | 154 Function _noPendingWriteHandler; |
| 155 Function _closeHandler; | 155 Function _closeHandler; |
| 156 } | 156 } |
| 157 | 157 |
| 158 | 158 |
| 159 class _FileOperation { | |
| 160 abstract void execute(ReceivePort port); | |
| 161 | |
| 162 void set replyPort(SendPort port) { | |
| 163 _replyPort = port; | |
| 164 } | |
| 165 | |
| 166 bool isWrite() => false; | |
| 167 | |
| 168 SendPort _replyPort; | |
| 169 } | |
| 170 | |
| 171 | |
| 172 class _ExistsOperation extends _FileOperation { | |
| 173 _ExistsOperation(String this._name); | |
| 174 | |
| 175 void execute(ReceivePort port) { | |
| 176 _replyPort.send(_FileUtils.exists(_name), port.toSendPort()); | |
| 177 } | |
| 178 | |
| 179 String _name; | |
| 180 } | |
| 181 | |
| 182 | |
| 183 class _OpenOperation extends _FileOperation { | |
| 184 _OpenOperation(String this._name, int this._mode); | |
| 185 | |
| 186 void execute(ReceivePort port) { | |
| 187 _replyPort.send(_FileUtils.checkedOpen(_name, _mode), | |
| 188 port.toSendPort()); | |
| 189 } | |
| 190 | |
| 191 String _name; | |
| 192 int _mode; | |
| 193 } | |
| 194 | |
| 195 | |
| 196 class _CloseOperation extends _FileOperation { | |
| 197 _CloseOperation(int this._id); | |
| 198 | |
| 199 void execute(ReceivePort port) { | |
| 200 _replyPort.send(_FileUtils.close(_id), port.toSendPort()); | |
| 201 } | |
| 202 | |
| 203 int _id; | |
| 204 } | |
| 205 | |
| 206 | |
| 207 class _ReadByteOperation extends _FileOperation { | |
| 208 _ReadByteOperation(int this._id); | |
| 209 | |
| 210 void execute(ReceivePort port) { | |
| 211 _replyPort.send(_FileUtils.readByte(_id), port.toSendPort()); | |
| 212 } | |
| 213 | |
| 214 int _id; | |
| 215 } | |
| 216 | |
| 217 | |
| 218 class _ReadListResult { | |
| 219 _ReadListResult(this.read, this.buffer); | |
| 220 int read; | |
| 221 List buffer; | |
| 222 } | |
| 223 | |
| 224 | |
| 225 class _ReadListOperation extends _FileOperation { | |
| 226 _ReadListOperation(int this._id, | |
| 227 int this._length, | |
| 228 int this._offset, | |
| 229 int this._bytes); | |
| 230 | |
| 231 void execute(ReceivePort port) { | |
| 232 if (_bytes == 0) { | |
| 233 _replyPort.send(0, port.toSendPort()); | |
| 234 return; | |
| 235 } | |
| 236 int index = | |
| 237 _FileUtils.checkReadWriteListArguments(_length, _offset, _bytes); | |
| 238 if (index != 0) { | |
| 239 _replyPort.send("index out of range in readList: $index", | |
| 240 port.toSendPort()); | |
| 241 return; | |
| 242 } | |
| 243 ByteArray buffer = new ByteArray(_bytes); | |
| 244 var result = | |
| 245 new _ReadListResult(_FileUtils.readList(_id, buffer, 0, _bytes), | |
| 246 buffer); | |
| 247 _replyPort.send(result, port.toSendPort()); | |
| 248 } | |
| 249 | |
| 250 int _id; | |
| 251 int _length; | |
| 252 int _offset; | |
| 253 int _bytes; | |
| 254 } | |
| 255 | |
| 256 | |
| 257 class _WriteByteOperation extends _FileOperation { | |
| 258 _WriteByteOperation(int this._id, int this._value); | |
| 259 | |
| 260 void execute(ReceivePort port) { | |
| 261 _replyPort.send(_FileUtils.writeByte(_id, _value), port.toSendPort()); | |
| 262 } | |
| 263 | |
| 264 bool isWrite() => true; | |
| 265 | |
| 266 int _id; | |
| 267 int _value; | |
| 268 } | |
| 269 | |
| 270 | |
| 271 class _WriteListOperation extends _FileOperation { | |
| 272 _WriteListOperation(int this._id, | |
| 273 List this._buffer, | |
| 274 int this._offset, | |
| 275 int this._bytes); | |
| 276 | |
| 277 void execute(ReceivePort port) { | |
| 278 if (_bytes == 0) { | |
| 279 _replyPort.send(0, port.toSendPort()); | |
| 280 return; | |
| 281 } | |
| 282 int index = | |
| 283 _FileUtils.checkReadWriteListArguments(_buffer.length, _offset, _bytes); | |
| 284 if (index != 0) { | |
| 285 _replyPort.send("index out of range in writeList: $index", | |
| 286 port.toSendPort()); | |
| 287 return; | |
| 288 } | |
| 289 var result = _FileUtils.writeList(_id, _buffer, _offset, _bytes); | |
| 290 _replyPort.send(result, port.toSendPort()); | |
| 291 } | |
| 292 | |
| 293 bool isWrite() => true; | |
| 294 | |
| 295 int _id; | |
| 296 List _buffer; | |
| 297 int _offset; | |
| 298 int _bytes; | |
| 299 } | |
| 300 | |
| 301 | |
| 302 class _WriteStringOperation extends _FileOperation { | |
| 303 _WriteStringOperation(int this._id, String this._string); | |
| 304 | |
| 305 void execute(ReceivePort port) { | |
| 306 _replyPort.send(_FileUtils.checkedWriteString(_id, _string), | |
| 307 port.toSendPort()); | |
| 308 } | |
| 309 | |
| 310 bool isWrite() => true; | |
| 311 | |
| 312 int _id; | |
| 313 String _string; | |
| 314 } | |
| 315 | |
| 316 | |
| 317 class _PositionOperation extends _FileOperation { | |
| 318 _PositionOperation(int this._id); | |
| 319 | |
| 320 void execute(ReceivePort port) { | |
| 321 _replyPort.send(_FileUtils.position(_id), port.toSendPort()); | |
| 322 } | |
| 323 | |
| 324 int _id; | |
| 325 } | |
| 326 | |
| 327 | |
| 328 class _SetPositionOperation extends _FileOperation { | |
| 329 _SetPositionOperation(int this._id, int this._position); | |
| 330 | |
| 331 void execute(ReceivePort port) { | |
| 332 _replyPort.send(_FileUtils.setPosition(_id, _position), port.toSendPort()); | |
| 333 } | |
| 334 | |
| 335 int _id; | |
| 336 int _position; | |
| 337 } | |
| 338 | |
| 339 | |
| 340 class _TruncateOperation extends _FileOperation { | |
| 341 _TruncateOperation(int this._id, int this._length); | |
| 342 | |
| 343 void execute(ReceivePort port) { | |
| 344 _replyPort.send(_FileUtils.truncate(_id, _length), port.toSendPort()); | |
| 345 } | |
| 346 | |
| 347 int _id; | |
| 348 int _length; | |
| 349 } | |
| 350 | |
| 351 | |
| 352 class _LengthOperation extends _FileOperation { | |
| 353 _LengthOperation(int this._id); | |
| 354 | |
| 355 void execute(ReceivePort port) { | |
| 356 _replyPort.send(_FileUtils.length(_id), port.toSendPort()); | |
| 357 } | |
| 358 | |
| 359 int _id; | |
| 360 } | |
| 361 | |
| 362 | |
| 363 class _FlushOperation extends _FileOperation { | |
| 364 _FlushOperation(int this._id); | |
| 365 | |
| 366 void execute(ReceivePort port) { | |
| 367 _replyPort.send(_FileUtils.flush(_id), port.toSendPort()); | |
| 368 } | |
| 369 | |
| 370 int _id; | |
| 371 } | |
| 372 | |
| 373 | |
| 374 class _FullPathOperation extends _FileOperation { | |
| 375 _FullPathOperation(String this._name); | |
| 376 | |
| 377 void execute(ReceivePort port) { | |
| 378 _replyPort.send(_FileUtils.checkedFullPath(_name), port.toSendPort()); | |
| 379 } | |
| 380 | |
| 381 String _name; | |
| 382 } | |
| 383 | |
| 384 | |
| 385 class _CreateOperation extends _FileOperation { | |
| 386 _CreateOperation(String this._name); | |
| 387 | |
| 388 void execute(ReceivePort port) { | |
| 389 _replyPort.send(_FileUtils.checkedCreate(_name), port.toSendPort()); | |
| 390 } | |
| 391 | |
| 392 String _name; | |
| 393 } | |
| 394 | |
| 395 | |
| 396 class _DeleteOperation extends _FileOperation { | |
| 397 _DeleteOperation(String this._name); | |
| 398 | |
| 399 void execute(ReceivePort port) { | |
| 400 _replyPort.send(_FileUtils.checkedDelete(_name), port.toSendPort()); | |
| 401 } | |
| 402 | |
| 403 String _name; | |
| 404 } | |
| 405 | |
| 406 | |
| 407 class _ExitOperation extends _FileOperation { | |
| 408 void execute(ReceivePort port) { | |
| 409 port.close(); | |
| 410 } | |
| 411 } | |
| 412 | |
| 413 | |
| 414 class _FileOperationIsolate extends Isolate { | |
| 415 _FileOperationIsolate() : super.heavy(); | |
| 416 | |
| 417 void handleOperation(_FileOperation message, SendPort ignored) { | |
| 418 message.execute(port); | |
| 419 port.receive(handleOperation); | |
| 420 } | |
| 421 | |
| 422 void main() { | |
| 423 port.receive(handleOperation); | |
| 424 } | |
| 425 } | |
| 426 | |
| 427 | |
| 428 class _FileOperationScheduler { | |
| 429 _FileOperationScheduler() : _queue = new Queue(); | |
| 430 | |
| 431 void schedule(SendPort port) { | |
| 432 assert(_isolate != null); | |
| 433 if (_queue.isEmpty()) { | |
| 434 port.send(new _ExitOperation()); | |
| 435 _isolate = null; | |
| 436 } else { | |
| 437 port.send(_queue.removeFirst()); | |
| 438 } | |
| 439 } | |
| 440 | |
| 441 void scheduleWrap(void callback(result, ignored)) { | |
| 442 return (result, replyTo) { | |
| 443 callback(result, replyTo); | |
| 444 schedule(replyTo); | |
| 445 }; | |
| 446 } | |
| 447 | |
| 448 void enqueue(_FileOperation operation, void callback(result, ignored)) { | |
| 449 ReceivePort replyPort = new ReceivePort.singleShot(); | |
| 450 replyPort.receive(scheduleWrap(callback)); | |
| 451 operation.replyPort = replyPort.toSendPort(); | |
| 452 _queue.addLast(operation); | |
| 453 if (_isolate == null) { | |
| 454 _isolate = new _FileOperationIsolate(); | |
| 455 _isolate.spawn().then((port) { | |
| 456 schedule(port); | |
| 457 }); | |
| 458 } | |
| 459 } | |
| 460 | |
| 461 bool noPendingWrite() { | |
| 462 int queuedWrites = 0; | |
| 463 _queue.forEach((operation) { | |
| 464 if (operation.isWrite()) { | |
| 465 queuedWrites++; | |
| 466 } | |
| 467 }); | |
| 468 return queuedWrites == 0; | |
| 469 } | |
| 470 | |
| 471 Queue<_FileOperation> _queue; | |
| 472 _FileOperationIsolate _isolate; | |
| 473 } | |
| 474 | |
| 475 | |
| 476 // Helper class containing static file helper methods. | 159 // Helper class containing static file helper methods. |
| 477 class _FileUtils { | 160 class _FileUtils { |
| 478 static bool exists(String name) native "File_Exists"; | 161 static final kExistsRequest = 0; |
| 479 static int open(String name, int mode) native "File_Open"; | 162 static final kCreateRequest = 1; |
| 480 static bool create(String name) native "File_Create"; | 163 static final kDeleteRequest = 2; |
| 481 static bool delete(String name) native "File_Delete"; | 164 static final kOpenRequest = 3; |
| 482 static String fullPath(String name) native "File_FullPath"; | 165 static final kFullPathRequest = 4; |
| 483 static int close(int id) native "File_Close"; | 166 static final kCloseRequest = 5; |
| 484 static int readByte(int id) native "File_ReadByte"; | 167 static final kPositionRequest = 6; |
| 485 static int readList(int id, List<int> buffer, int offset, int bytes) | 168 static final kSetPositionRequest = 7; |
| 486 native "File_ReadList"; | 169 static final kTruncateRequest = 8; |
| 487 static int writeByte(int id, int value) native "File_WriteByte"; | 170 static final kLengthRequest = 9; |
| 488 static int writeList(int id, List<int> buffer, int offset, int bytes) { | 171 static final kFlushRequest = 10; |
| 172 static final kReadByteRequest = 11; | |
| 173 static final kWriteByteRequest = 12; | |
| 174 static final kReadListRequest = 13; | |
| 175 static final kWriteListRequest = 14; | |
| 176 static final kWriteStringRequest = 15; | |
| 177 | |
| 178 static List ensureFastAndSerializabelBuffer( | |
|
Mads Ager (google)
2012/02/23 08:57:44
Serializable
Søren Gjesse
2012/02/23 10:26:42
Done.
| |
| 179 List buffer, int offset, int bytes) { | |
| 489 // When using the Dart C API to access raw data, using a ByteArray is | 180 // When using the Dart C API to access raw data, using a ByteArray is |
| 490 // currently much faster. This function will make a copy of the | 181 // currently much faster. This function will make a copy of the |
| 491 // supplied List to a ByteArray if it isn't already. | 182 // supplied List to a ByteArray if it isn't already. |
| 492 List outBuffer; | 183 List outBuffer; |
| 493 int outOffset = offset; | 184 int outOffset = offset; |
| 494 if (buffer is ByteArray || buffer is ObjectArray) { | 185 if (buffer is ByteArray || buffer is ObjectArray) { |
| 495 outBuffer = buffer; | 186 outBuffer = buffer; |
| 496 } else { | 187 } else { |
| 497 outBuffer = new ByteArray(bytes); | 188 outBuffer = new ByteArray(bytes); |
| 498 outOffset = 0; | 189 outOffset = 0; |
| 499 int j = offset; | 190 int j = offset; |
| 500 for (int i = 0; i < bytes; i++) { | 191 for (int i = 0; i < bytes; i++) { |
| 501 int value = buffer[j]; | 192 int value = buffer[j]; |
| 502 if (value is! int) { | 193 if (value is! int) { |
| 503 throw new FileIOException( | 194 throw new FileIOException( |
| 504 "List element is not an integer at index $j"); | 195 "List element is not an integer at index $j"); |
| 505 } | 196 } |
| 506 outBuffer[i] = value; | 197 outBuffer[i] = value; |
| 507 j++; | 198 j++; |
| 508 } | 199 } |
| 509 } | 200 } |
| 201 return [outBuffer, outOffset]; | |
| 202 } | |
| 203 | |
| 204 static bool exists(String name) native "File_Exists"; | |
| 205 static int open(String name, int mode) native "File_Open"; | |
| 206 static bool create(String name) native "File_Create"; | |
| 207 static bool delete(String name) native "File_Delete"; | |
| 208 static String fullPath(String name) native "File_FullPath"; | |
| 209 static int close(int id) native "File_Close"; | |
| 210 static int readByte(int id) native "File_ReadByte"; | |
| 211 static int readList(int id, List<int> buffer, int offset, int bytes) | |
| 212 native "File_ReadList"; | |
| 213 static int writeByte(int id, int value) native "File_WriteByte"; | |
| 214 static int writeList(int id, List<int> buffer, int offset, int bytes) { | |
| 215 List result = | |
| 216 _FileUtils.ensureFastAndSerializabelBuffer(buffer, offset, bytes); | |
| 217 List outBuffer = result[0]; | |
| 218 int outOffset = result[1]; | |
| 510 return writeListNative(id, outBuffer, outOffset, bytes); | 219 return writeListNative(id, outBuffer, outOffset, bytes); |
| 511 } | 220 } |
| 512 static int writeListNative(int id, List<int> buffer, int offset, int bytes) | 221 static int writeListNative(int id, List<int> buffer, int offset, int bytes) |
| 513 native "File_WriteList"; | 222 native "File_WriteList"; |
| 514 static int writeString(int id, String string) native "File_WriteString"; | 223 static int writeString(int id, String string) native "File_WriteString"; |
| 515 static int position(int id) native "File_Position"; | 224 static int position(int id) native "File_Position"; |
| 516 static bool setPosition(int id, int position) native "File_SetPosition"; | 225 static bool setPosition(int id, int position) native "File_SetPosition"; |
| 517 static bool truncate(int id, int length) native "File_Truncate"; | 226 static bool truncate(int id, int length) native "File_Truncate"; |
| 518 static int length(int id) native "File_Length"; | 227 static int length(int id) native "File_Length"; |
| 519 static int flush(int id) native "File_Flush"; | 228 static int flush(int id) native "File_Flush"; |
| 520 static int openStdio(int fd) native "File_OpenStdio"; | 229 static int openStdio(int fd) native "File_OpenStdio"; |
| 230 static SendPort newServicePort() native "File_NewServicePort"; | |
| 521 | 231 |
| 522 static int checkedOpen(String name, int mode) { | 232 static int checkedOpen(String name, int mode) { |
| 523 if (name is !String || mode is !int) return 0; | 233 if (name is !String || mode is !int) return 0; |
| 524 return open(name, mode); | 234 return open(name, mode); |
| 525 } | 235 } |
| 526 | 236 |
| 527 static bool checkedCreate(String name) { | 237 static bool checkedCreate(String name) { |
| 528 if (name is !String) return false; | 238 if (name is !String) return false; |
| 529 return create(name); | 239 return create(name); |
| 530 } | 240 } |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 549 static int checkedWriteString(int id, String string) { | 259 static int checkedWriteString(int id, String string) { |
| 550 if (string is !String) return -1; | 260 if (string is !String) return -1; |
| 551 return writeString(id, string); | 261 return writeString(id, string); |
| 552 } | 262 } |
| 553 } | 263 } |
| 554 | 264 |
| 555 | 265 |
| 556 // Class for encapsulating the native implementation of files. | 266 // Class for encapsulating the native implementation of files. |
| 557 class _File implements File { | 267 class _File implements File { |
| 558 // Constructor for file. | 268 // Constructor for file. |
| 559 _File(String this._name) | 269 _File(String this._name) : _asyncUsed = false; |
| 560 : _scheduler = new _FileOperationScheduler(), | |
| 561 _asyncUsed = false; | |
| 562 | 270 |
| 563 void exists() { | 271 void exists() { |
| 272 _ensureFileService(); | |
| 564 _asyncUsed = true; | 273 _asyncUsed = true; |
| 565 if (_name is !String) { | 274 if (_name is !String) { |
| 566 if (_errorHandler != null) { | 275 if (_errorHandler != null) { |
| 567 _errorHandler('File name is not a string: $_name'); | 276 _errorHandler('File name is not a string: $_name'); |
| 568 } | 277 } |
| 569 return; | 278 return; |
| 570 } | 279 } |
| 571 var operation = new _ExistsOperation(_name); | 280 List request = new List(2); |
| 572 _scheduler.enqueue(operation, (result, ignored) { | 281 request[0] = _FileUtils.kExistsRequest; |
| 573 var handler = | 282 request[1] = _name; |
| 574 (_existsHandler != null) ? _existsHandler : (result) => null; | 283 _fileService.call(request).receive((exists, replyTo) { |
| 575 handler(result); | 284 if (_existsHandler != null) _existsHandler(exists); |
| 576 }); | 285 }); |
| 577 } | 286 } |
| 578 | 287 |
| 579 bool existsSync() { | 288 bool existsSync() { |
| 580 if (_asyncUsed) { | 289 if (_asyncUsed) { |
| 581 throw new FileIOException( | 290 throw new FileIOException( |
| 582 "Mixed use of synchronous and asynchronous API"); | 291 "Mixed use of synchronous and asynchronous API"); |
| 583 } | 292 } |
| 584 if (_name is !String) { | 293 if (_name is !String) { |
| 585 throw new FileIOException('File name is not a string: $_name'); | 294 throw new FileIOException('File name is not a string: $_name'); |
| 586 } | 295 } |
| 587 return _FileUtils.exists(_name); | 296 return _FileUtils.exists(_name); |
| 588 } | 297 } |
| 589 | 298 |
| 590 void create() { | 299 void create() { |
| 300 _ensureFileService(); | |
| 591 _asyncUsed = true; | 301 _asyncUsed = true; |
| 592 var handleCreateResult = (created, ignored) { | 302 List request = new List(2); |
| 593 var handler = (_createHandler != null) ? _createHandler : () => null; | 303 request[0] = _FileUtils.kCreateRequest; |
| 304 request[1] = _name; | |
| 305 _fileService.call(request).receive((created, replyTo) { | |
| 594 if (created) { | 306 if (created) { |
| 595 handler(); | 307 if (_createHandler != null) _createHandler(); |
| 596 } else if (_errorHandler != null) { | 308 } else if (_errorHandler != null) { |
| 597 _errorHandler("Cannot create file: $_name"); | 309 _errorHandler("Cannot create file: $_name"); |
| 598 } | 310 } |
| 599 }; | 311 }); |
| 600 var operation = new _CreateOperation(_name); | |
| 601 _scheduler.enqueue(operation, handleCreateResult); | |
| 602 } | 312 } |
| 603 | 313 |
| 604 void createSync() { | 314 void createSync() { |
| 605 if (_asyncUsed) { | 315 if (_asyncUsed) { |
| 606 throw new FileIOException( | 316 throw new FileIOException( |
| 607 "Mixed use of synchronous and asynchronous API"); | 317 "Mixed use of synchronous and asynchronous API"); |
| 608 } | 318 } |
| 609 bool created = _FileUtils.checkedCreate(_name); | 319 bool created = _FileUtils.checkedCreate(_name); |
| 610 if (!created) { | 320 if (!created) { |
| 611 throw new FileIOException("Cannot create file: $_name"); | 321 throw new FileIOException("Cannot create file: $_name"); |
| 612 } | 322 } |
| 613 } | 323 } |
| 614 | 324 |
| 615 void delete() { | 325 void delete() { |
| 326 _ensureFileService(); | |
| 616 _asyncUsed = true; | 327 _asyncUsed = true; |
| 617 var handleDeleteResult = (created, ignored) { | 328 List request = new List(2); |
| 618 var handler = (_deleteHandler != null) ? _deleteHandler : () => null; | 329 request[0] = _FileUtils.kDeleteRequest; |
| 619 if (created) { | 330 request[1] = _name; |
| 620 handler(); | 331 _fileService.call(request).receive((deleted, replyTo) { |
| 332 if (deleted) { | |
| 333 if (_deleteHandler != null) _deleteHandler(); | |
| 621 } else if (_errorHandler != null) { | 334 } else if (_errorHandler != null) { |
| 622 _errorHandler("Cannot delete file: $_name"); | 335 _errorHandler("Cannot delete file: $_name"); |
| 623 } | 336 } |
| 624 }; | 337 }); |
| 625 var operation = new _DeleteOperation(_name); | |
| 626 _scheduler.enqueue(operation, handleDeleteResult); | |
| 627 } | 338 } |
| 628 | 339 |
| 629 void deleteSync() { | 340 void deleteSync() { |
| 630 if (_asyncUsed) { | 341 if (_asyncUsed) { |
| 631 throw new FileIOException( | 342 throw new FileIOException( |
| 632 "Mixed use of synchronous and asynchronous API"); | 343 "Mixed use of synchronous and asynchronous API"); |
| 633 } | 344 } |
| 634 bool deleted = _FileUtils.checkedDelete(_name); | 345 bool deleted = _FileUtils.checkedDelete(_name); |
| 635 if (!deleted) { | 346 if (!deleted) { |
| 636 throw new FileIOException("Cannot delete file: $_name"); | 347 throw new FileIOException("Cannot delete file: $_name"); |
| 637 } | 348 } |
| 638 } | 349 } |
| 639 | 350 |
| 640 void open([FileMode mode = FileMode.READ]) { | 351 void open([FileMode mode = FileMode.READ]) { |
| 352 _ensureFileService(); | |
| 641 _asyncUsed = true; | 353 _asyncUsed = true; |
| 642 if (mode != FileMode.READ && | 354 if (mode != FileMode.READ && |
| 643 mode != FileMode.WRITE && | 355 mode != FileMode.WRITE && |
| 644 mode != FileMode.APPEND) { | 356 mode != FileMode.APPEND) { |
| 645 if (_errorHandler != null) { | 357 if (_errorHandler != null) { |
| 646 _errorHandler("Unknown file mode. Use FileMode.READ, FileMode.WRITE " + | 358 _errorHandler("Unknown file mode. Use FileMode.READ, FileMode.WRITE " + |
| 647 "or FileMode.APPEND."); | 359 "or FileMode.APPEND."); |
| 648 return; | 360 return; |
| 649 } | 361 } |
| 650 } | 362 } |
| 651 var handleOpenResult = (id, ignored) { | 363 List request = new List(3); |
| 652 // If no open handler is present, close the file immediately to | 364 request[0] = _FileUtils.kOpenRequest; |
| 653 // avoid leaking an open file descriptor. | 365 request[1] = _name; |
| 366 request[2] = mode._mode; // Direct int value for serialization. | |
| 367 _fileService.call(request).receive((id, replyTo) { | |
| 654 var handler = _openHandler; | 368 var handler = _openHandler; |
| 655 if (handler === null) { | 369 if (handler === null) { |
| 370 // If no open handler is present, close the file immediately to | |
| 371 // avoid leaking an open file descriptor. | |
| 656 handler = (file) => file.close(); | 372 handler = (file) => file.close(); |
| 657 } | 373 } |
| 658 if (id != 0) { | 374 if (id != 0) { |
| 659 var randomAccessFile = new _RandomAccessFile(id, _name); | 375 var randomAccessFile = new _RandomAccessFile(id, _name); |
| 660 handler(randomAccessFile); | 376 handler(randomAccessFile); |
| 661 } else if (_errorHandler != null) { | 377 } else if (_errorHandler != null) { |
| 662 _errorHandler("Cannot open file: $_name"); | 378 _errorHandler("Cannot open file: $_name"); |
| 663 } | 379 } |
| 664 }; | 380 }); |
| 665 var operation = new _OpenOperation(_name, mode._mode); | |
| 666 _scheduler.enqueue(operation, handleOpenResult); | |
| 667 } | 381 } |
| 668 | 382 |
| 669 RandomAccessFile openSync([FileMode mode = FileMode.READ]) { | 383 RandomAccessFile openSync([FileMode mode = FileMode.READ]) { |
| 670 if (_asyncUsed) { | 384 if (_asyncUsed) { |
| 671 throw new FileIOException( | 385 throw new FileIOException( |
| 672 "Mixed use of synchronous and asynchronous API"); | 386 "Mixed use of synchronous and asynchronous API"); |
| 673 } | 387 } |
| 674 if (mode != FileMode.READ && | 388 if (mode != FileMode.READ && |
| 675 mode != FileMode.WRITE && | 389 mode != FileMode.WRITE && |
| 676 mode != FileMode.APPEND) { | 390 mode != FileMode.APPEND) { |
| 677 throw new FileIOException("Unknown file mode. Use FileMode.READ, " + | 391 throw new FileIOException("Unknown file mode. Use FileMode.READ, " + |
| 678 "FileMode.WRITE or FileMode.APPEND."); | 392 "FileMode.WRITE or FileMode.APPEND."); |
| 679 } | 393 } |
| 680 var id = _FileUtils.checkedOpen(_name, mode._mode); | 394 var id = _FileUtils.checkedOpen(_name, mode._mode); |
| 681 if (id == 0) { | 395 if (id == 0) { |
| 682 throw new FileIOException("Cannot open file: $_name"); | 396 throw new FileIOException("Cannot open file: $_name"); |
| 683 } | 397 } |
| 684 return new _RandomAccessFile(id, _name); | 398 return new _RandomAccessFile(id, _name); |
| 685 } | 399 } |
| 686 | 400 |
| 687 static RandomAccessFile _openStdioSync(int fd) { | 401 static RandomAccessFile _openStdioSync(int fd) { |
| 688 var id = _FileUtils.openStdio(fd); | 402 var id = _FileUtils.openStdio(fd); |
| 689 if (id == 0) { | 403 if (id == 0) { |
| 690 throw new FileIOException("Cannot open stdio file for: $fd"); | 404 throw new FileIOException("Cannot open stdio file for: $fd"); |
| 691 } | 405 } |
| 692 return new _RandomAccessFile(id, ""); | 406 return new _RandomAccessFile(id, ""); |
| 693 } | 407 } |
| 694 | 408 |
| 695 void fullPath() { | 409 void fullPath() { |
| 410 _ensureFileService(); | |
| 696 _asyncUsed = true; | 411 _asyncUsed = true; |
| 697 var handleFullPathResult = (result, ignored) { | 412 List request = new List(2); |
| 698 var handler = _fullPathHandler; | 413 request[0] = _FileUtils.kFullPathRequest; |
| 699 if (handler == null) handler = (path) => null; | 414 request[1] = _name; |
| 415 _fileService.call(request).receive((result, replyTo) { | |
| 700 if (result != null) { | 416 if (result != null) { |
| 701 handler(result); | 417 if (_fullPathHandler != null) _fullPathHandler(result); |
| 702 } else if (_errorHandler != null) { | 418 } else if (_errorHandler != null) { |
| 703 _errorHandler("fullPath failed"); | 419 _errorHandler("fullPath failed"); |
| 704 } | 420 } |
| 705 }; | 421 }); |
| 706 var operation = new _FullPathOperation(_name); | |
| 707 _scheduler.enqueue(operation, handleFullPathResult); | |
| 708 } | 422 } |
| 709 | 423 |
| 710 String fullPathSync() { | 424 String fullPathSync() { |
| 711 if (_asyncUsed) { | 425 if (_asyncUsed) { |
| 712 throw new FileIOException( | 426 throw new FileIOException( |
| 713 "Mixed use of synchronous and asynchronous API"); | 427 "Mixed use of synchronous and asynchronous API"); |
| 714 } | 428 } |
| 715 String result = _FileUtils.checkedFullPath(_name); | 429 String result = _FileUtils.checkedFullPath(_name); |
| 716 if (result == null) { | 430 if (result == null) { |
| 717 throw new FileIOException("fullPath failed"); | 431 throw new FileIOException("fullPath failed"); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 809 } | 523 } |
| 810 | 524 |
| 811 void set fullPathHandler(void handler(String)) { | 525 void set fullPathHandler(void handler(String)) { |
| 812 _fullPathHandler = handler; | 526 _fullPathHandler = handler; |
| 813 } | 527 } |
| 814 | 528 |
| 815 void set errorHandler(void handler(String error)) { | 529 void set errorHandler(void handler(String error)) { |
| 816 _errorHandler = handler; | 530 _errorHandler = handler; |
| 817 } | 531 } |
| 818 | 532 |
| 533 void _ensureFileService() { | |
| 534 if (_fileService == null) { | |
| 535 _fileService = _FileUtils.newServicePort(); | |
| 536 } | |
| 537 } | |
| 538 | |
| 819 String _name; | 539 String _name; |
| 820 bool _asyncUsed; | 540 bool _asyncUsed; |
| 821 | 541 |
| 822 _FileOperationScheduler _scheduler; | 542 SendPort _fileService; |
| 823 | 543 |
| 824 Function _existsHandler; | 544 Function _existsHandler; |
| 825 Function _createHandler; | 545 Function _createHandler; |
| 826 Function _deleteHandler; | 546 Function _deleteHandler; |
| 827 Function _openHandler; | 547 Function _openHandler; |
| 828 Function _inputStreamHandler; | 548 Function _inputStreamHandler; |
| 829 Function _outputStreamHandler; | 549 Function _outputStreamHandler; |
| 830 Function _fullPathHandler; | 550 Function _fullPathHandler; |
| 831 Function _errorHandler; | 551 Function _errorHandler; |
| 832 } | 552 } |
| 833 | 553 |
| 834 | 554 |
| 835 class _RandomAccessFile implements RandomAccessFile { | 555 class _RandomAccessFile implements RandomAccessFile { |
| 836 _RandomAccessFile(int this._id, String this._name) | 556 _RandomAccessFile(int this._id, String this._name) : _asyncUsed = false; |
| 837 : _scheduler = new _FileOperationScheduler(), | |
| 838 _asyncUsed = false; | |
| 839 | 557 |
| 840 void close() { | 558 void close() { |
| 559 if (_id == 0) return; | |
| 560 _ensureFileService(); | |
| 841 _asyncUsed = true; | 561 _asyncUsed = true; |
| 842 var handleCloseResult = (result, ignored) { | 562 List request = new List(2); |
| 843 var handler = (_closeHandler != null) ? _closeHandler : () => null; | 563 request[0] = _FileUtils.kCloseRequest; |
| 564 request[1] = _id; | |
| 565 // Set the id_ to 0 (NULL) to ensure the no more async requests | |
| 566 // can be issues for this file. | |
| 567 _id = 0; | |
| 568 _fileService.call(request).receive((result, replyTo) { | |
| 844 if (result != -1) { | 569 if (result != -1) { |
| 845 _id = result; | 570 _id = result; |
| 846 handler(); | 571 if (_closeHandler != null) _closeHandler(); |
| 847 } else if (_errorHandler != null) { | 572 } else if (_errorHandler != null) { |
| 848 _errorHandler("Cannot close file: $_name"); | 573 _errorHandler("Cannot close file: $_name"); |
| 849 } | 574 } |
| 850 }; | 575 }); |
| 851 var operation = new _CloseOperation(_id); | |
| 852 _scheduler.enqueue(operation, handleCloseResult); | |
| 853 } | 576 } |
| 854 | 577 |
| 855 void closeSync() { | 578 void closeSync() { |
| 856 if (_asyncUsed) { | 579 if (_asyncUsed) { |
| 857 throw new FileIOException( | 580 throw new FileIOException( |
| 858 "Mixed use of synchronous and asynchronous API"); | 581 "Mixed use of synchronous and asynchronous API"); |
| 859 } | 582 } |
| 860 var id = _FileUtils.close(_id); | 583 var id = _FileUtils.close(_id); |
| 861 if (id == -1) { | 584 if (id == -1) { |
| 862 throw new FileIOException("Cannot close file: $_name"); | 585 throw new FileIOException("Cannot close file: $_name"); |
| 863 } | 586 } |
| 864 _id = id; | 587 _id = id; |
| 865 } | 588 } |
| 866 | 589 |
| 867 void readByte() { | 590 void readByte() { |
| 591 _ensureFileService(); | |
| 868 _asyncUsed = true; | 592 _asyncUsed = true; |
| 869 var handleReadByteResult = (result, ignored) { | 593 List request = new List(2); |
| 870 var handler = | 594 request[0] = _FileUtils.kReadByteRequest; |
| 871 (_readByteHandler != null) ? _readByteHandler : (byte) => null; | 595 request[1] = _id; |
| 596 _fileService.call(request).receive((result, replyTo) { | |
| 872 if (result != -1) { | 597 if (result != -1) { |
| 873 handler(result); | 598 if (_readByteHandler != null) _readByteHandler(result); |
| 874 } else if (_errorHandler != null) { | 599 } else if (_errorHandler != null) { |
| 875 _errorHandler("readByte failed"); | 600 _errorHandler("readByte failed"); |
| 876 } | 601 } |
| 877 }; | 602 }); |
| 878 var operation = new _ReadByteOperation(_id); | |
| 879 _scheduler.enqueue(operation, handleReadByteResult); | |
| 880 } | 603 } |
| 881 | 604 |
| 882 int readByteSync() { | 605 int readByteSync() { |
| 883 if (_asyncUsed) { | 606 if (_asyncUsed) { |
| 884 throw new FileIOException( | 607 throw new FileIOException( |
| 885 "Mixed use of synchronous and asynchronous API"); | 608 "Mixed use of synchronous and asynchronous API"); |
| 886 } | 609 } |
| 887 int result = _FileUtils.readByte(_id); | 610 int result = _FileUtils.readByte(_id); |
| 888 if (result == -1) { | 611 if (result == -1) { |
| 889 throw new FileIOException("readByte failed"); | 612 throw new FileIOException("readByte failed"); |
| 890 } | 613 } |
| 891 return result; | 614 return result; |
| 892 } | 615 } |
| 893 | 616 |
| 894 void readList(List<int> buffer, int offset, int bytes) { | 617 void readList(List<int> buffer, int offset, int bytes) { |
| 618 _ensureFileService(); | |
| 895 _asyncUsed = true; | 619 _asyncUsed = true; |
| 896 if (buffer is !List || offset is !int || bytes is !int) { | 620 if (buffer is !List || offset is !int || bytes is !int) { |
| 897 if (_errorHandler != null) { | 621 if (_errorHandler != null) { |
| 898 _errorHandler("Invalid arguments to readList"); | 622 _errorHandler("Invalid arguments to readList"); |
| 899 } | 623 } |
| 900 return; | 624 return; |
| 901 }; | 625 }; |
| 902 var handleReadListResult = (result, ignored) { | 626 List request = new List(3); |
| 903 var handler = | 627 request[0] = _FileUtils.kReadListRequest; |
| 904 (_readListHandler != null) ? _readListHandler : (result) => null; | 628 request[1] = _id; |
| 905 if (result is _ReadListResult && result.read != -1) { | 629 request[2] = bytes; |
| 906 var read = result.read; | 630 _fileService.call(request).receive((result, replyTo) { |
| 907 buffer.setRange(offset, read, result.buffer); | 631 if (result is List && result.length == 2 && result[0] != -1) { |
| 908 handler(read); | 632 var read = result[0]; |
| 633 var data = result[1]; | |
| 634 buffer.setRange(offset, read, data); | |
| 635 if (_readListHandler != null) _readListHandler(read); | |
| 909 return; | 636 return; |
| 910 } | 637 } else if (_errorHandler != null) { |
| 911 if (_errorHandler != null) { | |
| 912 _errorHandler(result is String ? result : "readList failed"); | 638 _errorHandler(result is String ? result : "readList failed"); |
| 913 } | 639 } |
| 914 }; | 640 }); |
| 915 var operation = new _ReadListOperation(_id, buffer.length, offset, bytes); | |
| 916 _scheduler.enqueue(operation, handleReadListResult); | |
| 917 } | 641 } |
| 918 | 642 |
| 919 int readListSync(List<int> buffer, int offset, int bytes) { | 643 int readListSync(List<int> buffer, int offset, int bytes) { |
| 920 if (_asyncUsed) { | 644 if (_asyncUsed) { |
| 921 throw new FileIOException( | 645 throw new FileIOException( |
| 922 "Mixed use of synchronous and asynchronous API"); | 646 "Mixed use of synchronous and asynchronous API"); |
| 923 } | 647 } |
| 924 if (buffer is !List || offset is !int || bytes is !int) { | 648 if (buffer is !List || offset is !int || bytes is !int) { |
| 925 throw new FileIOException("Invalid arguments to readList"); | 649 throw new FileIOException("Invalid arguments to readList"); |
| 926 } | 650 } |
| 927 if (bytes == 0) return 0; | 651 if (bytes == 0) return 0; |
| 928 int index = | 652 int index = |
| 929 _FileUtils.checkReadWriteListArguments(buffer.length, offset, bytes); | 653 _FileUtils.checkReadWriteListArguments(buffer.length, offset, bytes); |
| 930 if (index != 0) { | 654 if (index != 0) { |
| 931 throw new IndexOutOfRangeException(index); | 655 throw new IndexOutOfRangeException(index); |
| 932 } | 656 } |
| 933 int result = _FileUtils.readList(_id, buffer, offset, bytes); | 657 int result = _FileUtils.readList(_id, buffer, offset, bytes); |
| 934 if (result == -1) { | 658 if (result == -1) { |
| 935 throw new FileIOException("readList failed"); | 659 throw new FileIOException("readList failed"); |
| 936 } | 660 } |
| 937 return result; | 661 return result; |
| 938 } | 662 } |
| 939 | 663 |
| 940 void _checkPendingWrites() { | |
| 941 if (_scheduler.noPendingWrite() && _noPendingWriteHandler != null) { | |
| 942 _noPendingWriteHandler(); | |
| 943 } | |
| 944 } | |
| 945 | |
| 946 void writeByte(int value) { | 664 void writeByte(int value) { |
| 665 _ensureFileService(); | |
| 947 _asyncUsed = true; | 666 _asyncUsed = true; |
| 948 if (value is !int) { | 667 if (value is !int) { |
| 949 if (_errorHandler != null) { | 668 if (_errorHandler != null) { |
| 950 _errorHandler("Invalid argument to writeByte"); | 669 _errorHandler("Invalid argument to writeByte"); |
| 951 } | 670 } |
| 952 return; | 671 return; |
| 953 } | 672 } |
| 954 var handleReadByteResult = (result, ignored) { | 673 List request = new List(3); |
| 955 if (result == -1 &&_errorHandler != null) { | 674 request[0] = _FileUtils.kWriteByteRequest; |
| 675 request[1] = _id; | |
| 676 request[2] = value; | |
| 677 _writeEnqueued(); | |
| 678 _fileService.call(request).receive((result, replyTo) { | |
| 679 _writesCompleted(); | |
| 680 if (result == -1 && _errorHandler !== null) { | |
| 956 _errorHandler("writeByte failed"); | 681 _errorHandler("writeByte failed"); |
| 957 return; | |
| 958 } | 682 } |
| 959 _checkPendingWrites(); | 683 }); |
| 960 }; | |
| 961 var operation = new _WriteByteOperation(_id, value); | |
| 962 _scheduler.enqueue(operation, handleReadByteResult); | |
| 963 } | 684 } |
| 964 | 685 |
| 965 int writeByteSync(int value) { | 686 int writeByteSync(int value) { |
| 966 if (_asyncUsed) { | 687 if (_asyncUsed) { |
| 967 throw new FileIOException( | 688 throw new FileIOException( |
| 968 "Mixed use of synchronous and asynchronous API"); | 689 "Mixed use of synchronous and asynchronous API"); |
| 969 } | 690 } |
| 970 if (value is !int) { | 691 if (value is !int) { |
| 971 throw new FileIOException("Invalid argument to writeByte"); | 692 throw new FileIOException("Invalid argument to writeByte"); |
| 972 } | 693 } |
| 973 int result = _FileUtils.writeByte(_id, value); | 694 int result = _FileUtils.writeByte(_id, value); |
| 974 if (result == -1) { | 695 if (result == -1) { |
| 975 throw new FileIOException("writeByte failed"); | 696 throw new FileIOException("writeByte failed"); |
| 976 } | 697 } |
| 977 return result; | 698 return result; |
| 978 } | 699 } |
| 979 | 700 |
| 980 void writeList(List<int> buffer, int offset, int bytes) { | 701 void writeList(List<int> buffer, int offset, int bytes) { |
| 702 _ensureFileService(); | |
| 981 _asyncUsed = true; | 703 _asyncUsed = true; |
| 982 if (buffer is !List || offset is !int || bytes is !int) { | 704 if (buffer is !List || offset is !int || bytes is !int) { |
| 983 if (_errorHandler != null) { | 705 if (_errorHandler != null) { |
| 984 _errorHandler("Invalid arguments to writeList"); | 706 _errorHandler("Invalid arguments to writeList"); |
| 985 } | 707 } |
| 986 return; | 708 return; |
| 987 } | 709 } |
| 988 var handleWriteListResult = (result, ignored) { | 710 |
| 989 if (result is !String && result != -1) { | 711 List result = |
| 990 if (result < bytes) { | 712 _FileUtils.ensureFastAndSerializabelBuffer(buffer, offset, bytes); |
| 991 writeList(buffer, offset + result, bytes - result); | 713 List outBuffer = result[0]; |
| 992 } else { | 714 int outOffset = result[1]; |
| 993 _checkPendingWrites(); | 715 |
| 994 } | 716 List request = new List(5); |
| 995 return; | 717 request[0] = _FileUtils.kWriteListRequest; |
| 718 request[1] = _id; | |
| 719 request[2] = outBuffer; | |
| 720 request[3] = outOffset; | |
| 721 request[4] = bytes; | |
| 722 _writeEnqueued(); | |
| 723 _fileService.call(request).receive((result, replyTo) { | |
| 724 _writesCompleted(); | |
| 725 if (result == -1 && _errorHandler !== null) { | |
| 726 _errorHandler("writeList failed"); | |
| 996 } | 727 } |
| 997 if (_errorHandler != null) { | 728 }); |
| 998 _errorHandler(result is String ? result : "writeList failed"); | |
| 999 } | |
| 1000 }; | |
| 1001 var operation = new _WriteListOperation(_id, buffer, offset, bytes); | |
| 1002 _scheduler.enqueue(operation, handleWriteListResult); | |
| 1003 } | 729 } |
| 1004 | 730 |
| 1005 int writeListSync(List<int> buffer, int offset, int bytes) { | 731 int writeListSync(List<int> buffer, int offset, int bytes) { |
| 1006 if (_asyncUsed) { | 732 if (_asyncUsed) { |
| 1007 throw new FileIOException( | 733 throw new FileIOException( |
| 1008 "Mixed use of synchronous and asynchronous API"); | 734 "Mixed use of synchronous and asynchronous API"); |
| 1009 } | 735 } |
| 1010 if (buffer is !List || offset is !int || bytes is !int) { | 736 if (buffer is !List || offset is !int || bytes is !int) { |
| 1011 throw new FileIOException("Invalid arguments to writeList"); | 737 throw new FileIOException("Invalid arguments to writeList"); |
| 1012 } | 738 } |
| 1013 if (bytes == 0) return 0; | 739 if (bytes == 0) return 0; |
| 1014 int index = | 740 int index = |
| 1015 _FileUtils.checkReadWriteListArguments(buffer.length, offset, bytes); | 741 _FileUtils.checkReadWriteListArguments(buffer.length, offset, bytes); |
| 1016 if (index != 0) { | 742 if (index != 0) { |
| 1017 throw new IndexOutOfRangeException(index); | 743 throw new IndexOutOfRangeException(index); |
| 1018 } | 744 } |
| 1019 int result = _FileUtils.writeList(_id, buffer, offset, bytes); | 745 int result = _FileUtils.writeList(_id, buffer, offset, bytes); |
| 1020 if (result == -1) { | 746 if (result == -1) { |
| 1021 throw new FileIOException("writeList failed"); | 747 throw new FileIOException("writeList failed"); |
| 1022 } | 748 } |
| 1023 return result; | 749 return result; |
| 1024 } | 750 } |
| 1025 | 751 |
| 1026 void writeString(String string) { | 752 void writeString(String string) { |
| 753 _ensureFileService(); | |
| 1027 _asyncUsed = true; | 754 _asyncUsed = true; |
| 1028 var handleWriteStringResult = (result, ignored) { | 755 List request = new List(3); |
| 1029 if (result == -1 &&_errorHandler != null) { | 756 request[0] = _FileUtils.kWriteStringRequest; |
| 757 request[1] = _id; | |
| 758 request[2] = string; | |
| 759 _writeEnqueued(); | |
| 760 _fileService.call(request).receive((result, replyTo) { | |
| 761 _writesCompleted(); | |
| 762 if (result == -1 && _errorHandler !== null) { | |
| 1030 _errorHandler("writeString failed"); | 763 _errorHandler("writeString failed"); |
| 1031 return; | |
| 1032 } | 764 } |
| 1033 if (result < string.length) { | 765 }); |
| 1034 writeString(string.substring(result)); | |
| 1035 } else { | |
| 1036 _checkPendingWrites(); | |
| 1037 } | |
| 1038 }; | |
| 1039 var operation = new _WriteStringOperation(_id, string); | |
| 1040 _scheduler.enqueue(operation, handleWriteStringResult); | |
| 1041 } | 766 } |
| 1042 | 767 |
| 1043 int writeStringSync(String string) { | 768 int writeStringSync(String string) { |
| 1044 if (_asyncUsed) { | 769 if (_asyncUsed) { |
| 1045 throw new FileIOException( | 770 throw new FileIOException( |
| 1046 "Mixed use of synchronous and asynchronous API"); | 771 "Mixed use of synchronous and asynchronous API"); |
| 1047 } | 772 } |
| 1048 int result = _FileUtils.checkedWriteString(_id, string); | 773 int result = _FileUtils.checkedWriteString(_id, string); |
| 1049 if (result == -1) { | 774 if (result == -1) { |
| 1050 throw new FileIOException("writeString failed"); | 775 throw new FileIOException("writeString failed"); |
| 1051 } | 776 } |
| 1052 return result; | 777 return result; |
| 1053 } | 778 } |
| 1054 | 779 |
| 1055 void position() { | 780 void position() { |
| 781 _ensureFileService(); | |
| 1056 _asyncUsed = true; | 782 _asyncUsed = true; |
| 1057 var handlePositionResult = (result, ignored) { | 783 List request = new List(2); |
| 1058 var handler = | 784 request[0] = _FileUtils.kPositionRequest; |
| 1059 (_positionHandler != null) ? _positionHandler : (pos) => null; | 785 request[1] = _id; |
| 1060 if (result == -1 && _errorHandler != null) { | 786 _fileService.call(request).receive((result, replyTo) { |
| 787 if (result != -1) { | |
| 788 if (_positionHandler != null) _positionHandler(result); | |
| 789 } else if (_errorHandler != null) { | |
| 1061 _errorHandler("position failed"); | 790 _errorHandler("position failed"); |
| 1062 return; | |
| 1063 } | 791 } |
| 1064 handler(result); | 792 }); |
| 1065 }; | |
| 1066 var operation = new _PositionOperation(_id); | |
| 1067 _scheduler.enqueue(operation, handlePositionResult); | |
| 1068 } | 793 } |
| 1069 | 794 |
| 1070 int positionSync() { | 795 int positionSync() { |
| 1071 if (_asyncUsed) { | 796 if (_asyncUsed) { |
| 1072 throw new FileIOException( | 797 throw new FileIOException( |
| 1073 "Mixed use of synchronous and asynchronous API"); | 798 "Mixed use of synchronous and asynchronous API"); |
| 1074 } | 799 } |
| 1075 int result = _FileUtils.position(_id); | 800 int result = _FileUtils.position(_id); |
| 1076 if (result == -1) { | 801 if (result == -1) { |
| 1077 throw new FileIOException("position failed"); | 802 throw new FileIOException("position failed"); |
| 1078 } | 803 } |
| 1079 return result; | 804 return result; |
| 1080 } | 805 } |
| 1081 | 806 |
| 1082 void setPosition(int position) { | 807 void setPosition(int position) { |
| 808 _ensureFileService(); | |
| 1083 _asyncUsed = true; | 809 _asyncUsed = true; |
| 1084 var handleSetPositionResult = (result, ignored) { | 810 List request = new List(3); |
| 1085 var handler = | 811 request[0] = _FileUtils.kSetPositionRequest; |
| 1086 (_setPositionHandler != null) ? _setPositionHandler : () => null; | 812 request[1] = _id; |
| 1087 if (result == false && _errorHandler != null) { | 813 request[2] = position; |
| 814 _fileService.call(request).receive((result, replyTo) { | |
| 815 if (result) { | |
| 816 if (_setPositionHandler != null) _setPositionHandler(); | |
| 817 } else if (_errorHandler != null) { | |
| 1088 _errorHandler("setPosition failed"); | 818 _errorHandler("setPosition failed"); |
| 1089 return; | |
| 1090 } | 819 } |
| 1091 handler(); | 820 }); |
| 1092 }; | |
| 1093 var operation = new _SetPositionOperation(_id, position); | |
| 1094 _scheduler.enqueue(operation, handleSetPositionResult); | |
| 1095 } | 821 } |
| 1096 | 822 |
| 1097 void setPositionSync(int position) { | 823 void setPositionSync(int position) { |
| 824 _ensureFileService(); | |
| 1098 if (_asyncUsed) { | 825 if (_asyncUsed) { |
| 1099 throw new FileIOException( | 826 throw new FileIOException( |
| 1100 "Mixed use of synchronous and asynchronous API"); | 827 "Mixed use of synchronous and asynchronous API"); |
| 1101 } | 828 } |
| 1102 bool result = _FileUtils.setPosition(_id, position); | 829 bool result = _FileUtils.setPosition(_id, position); |
| 1103 if (result == false) { | 830 if (result == false) { |
| 1104 throw new FileIOException("setPosition failed"); | 831 throw new FileIOException("setPosition failed"); |
| 1105 } | 832 } |
| 1106 } | 833 } |
| 1107 | 834 |
| 1108 void truncate(int length) { | 835 void truncate(int length) { |
| 836 _ensureFileService(); | |
| 1109 _asyncUsed = true; | 837 _asyncUsed = true; |
| 1110 var handleTruncateResult = (result, ignored) { | 838 List request = new List(3); |
| 1111 var handler = (_truncateHandler != null) ? _truncateHandler : () => null; | 839 request[0] = _FileUtils.kTruncateRequest; |
| 1112 if (result == false && _errorHandler != null) { | 840 request[1] = _id; |
| 841 request[2] = length; | |
| 842 _fileService.call(request).receive((result, replyTo) { | |
| 843 if (result) { | |
| 844 if (_truncateHandler != null) _truncateHandler(); | |
| 845 } else if (_errorHandler != null) { | |
| 1113 _errorHandler("truncate failed"); | 846 _errorHandler("truncate failed"); |
| 1114 return; | |
| 1115 } | 847 } |
| 1116 handler(); | 848 }); |
| 1117 }; | |
| 1118 var operation = new _TruncateOperation(_id, length); | |
| 1119 _scheduler.enqueue(operation, handleTruncateResult); | |
| 1120 } | 849 } |
| 1121 | 850 |
| 1122 void truncateSync(int length) { | 851 void truncateSync(int length) { |
| 1123 if (_asyncUsed) { | 852 if (_asyncUsed) { |
| 1124 throw new FileIOException( | 853 throw new FileIOException( |
| 1125 "Mixed use of synchronous and asynchronous API"); | 854 "Mixed use of synchronous and asynchronous API"); |
| 1126 } | 855 } |
| 1127 bool result = _FileUtils.truncate(_id, length); | 856 bool result = _FileUtils.truncate(_id, length); |
| 1128 if (result == false) { | 857 if (result == false) { |
| 1129 throw new FileIOException("truncate failed"); | 858 throw new FileIOException("truncate failed"); |
| 1130 } | 859 } |
| 1131 } | 860 } |
| 1132 | 861 |
| 1133 void length() { | 862 void length() { |
| 863 _ensureFileService(); | |
| 1134 _asyncUsed = true; | 864 _asyncUsed = true; |
| 1135 var handleLengthResult = (result, ignored) { | 865 List request = new List(2); |
| 1136 var handler = (_lengthHandler != null) ? _lengthHandler : (pos) => null; | 866 request[0] = _FileUtils.kLengthRequest; |
| 1137 if (result == -1 && _errorHandler != null) { | 867 request[1] = _id; |
| 868 _fileService.call(request).receive((result, replyTo) { | |
| 869 if (result != -1) { | |
| 870 if (_lengthHandler != null) _lengthHandler(result); | |
| 871 } else if (_errorHandler != null) { | |
| 1138 _errorHandler("length failed"); | 872 _errorHandler("length failed"); |
| 1139 return; | |
| 1140 } | 873 } |
| 1141 handler(result); | 874 }); |
| 1142 }; | |
| 1143 var operation = new _LengthOperation(_id); | |
| 1144 _scheduler.enqueue(operation, handleLengthResult); | |
| 1145 } | 875 } |
| 1146 | 876 |
| 1147 int lengthSync() { | 877 int lengthSync() { |
| 1148 if (_asyncUsed) { | 878 if (_asyncUsed) { |
| 1149 throw new FileIOException( | 879 throw new FileIOException( |
| 1150 "Mixed use of synchronous and asynchronous API"); | 880 "Mixed use of synchronous and asynchronous API"); |
| 1151 } | 881 } |
| 1152 int result = _FileUtils.length(_id); | 882 int result = _FileUtils.length(_id); |
| 1153 if (result == -1) { | 883 if (result == -1) { |
| 1154 throw new FileIOException("length failed"); | 884 throw new FileIOException("length failed"); |
| 1155 } | 885 } |
| 1156 return result; | 886 return result; |
| 1157 } | 887 } |
| 1158 | 888 |
| 1159 void flush() { | 889 void flush() { |
| 890 _ensureFileService(); | |
| 1160 _asyncUsed = true; | 891 _asyncUsed = true; |
| 1161 var handleFlushResult = (result, ignored) { | 892 List request = new List(2); |
| 1162 var handler = (_flushHandler != null) ? _flushHandler : (pos) => null; | 893 request[0] = _FileUtils.kFlushRequest; |
| 1163 if (result == -1 && _errorHandler != null) { | 894 request[1] = _id; |
| 895 _fileService.call(request).receive((result, replyTo) { | |
| 896 if (result != -1) { | |
| 897 if (_flushHandler != null) _flushHandler(); | |
| 898 } else if (_errorHandler != null) { | |
| 1164 _errorHandler("flush failed"); | 899 _errorHandler("flush failed"); |
| 1165 return; | |
| 1166 } | 900 } |
| 1167 handler(); | 901 }); |
| 1168 }; | |
| 1169 var operation = new _FlushOperation(_id); | |
| 1170 _scheduler.enqueue(operation, handleFlushResult); | |
| 1171 } | 902 } |
| 1172 | 903 |
| 1173 void flushSync() { | 904 void flushSync() { |
| 1174 if (_asyncUsed) { | 905 if (_asyncUsed) { |
| 1175 throw new FileIOException( | 906 throw new FileIOException( |
| 1176 "Mixed use of synchronous and asynchronous API"); | 907 "Mixed use of synchronous and asynchronous API"); |
| 1177 } | 908 } |
| 1178 int result = _FileUtils.flush(_id); | 909 int result = _FileUtils.flush(_id); |
| 1179 if (result == -1) { | 910 if (result == -1) { |
| 1180 throw new FileIOException("flush failed"); | 911 throw new FileIOException("flush failed"); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1216 } | 947 } |
| 1217 | 948 |
| 1218 void set lengthHandler(void handler(int length)) { | 949 void set lengthHandler(void handler(int length)) { |
| 1219 _lengthHandler = handler; | 950 _lengthHandler = handler; |
| 1220 } | 951 } |
| 1221 | 952 |
| 1222 void set flushHandler(void handler()) { | 953 void set flushHandler(void handler()) { |
| 1223 _flushHandler = handler; | 954 _flushHandler = handler; |
| 1224 } | 955 } |
| 1225 | 956 |
| 957 void _ensureFileService() { | |
| 958 if (_fileService == null) { | |
| 959 _fileService = _FileUtils.newServicePort(); | |
| 960 } | |
| 961 } | |
| 962 | |
| 963 void _writeEnqueued() => _pendingWrites++; | |
| 964 | |
| 965 void _writesCompleted() { | |
|
Mads Ager (google)
2012/02/23 08:57:44
writes -> write
Søren Gjesse
2012/02/23 10:26:42
Done.
| |
| 966 _pendingWrites--; | |
| 967 if (_pendingWrites == 0 && _noPendingWriteHandler != null) { | |
| 968 _noPendingWriteHandler(); | |
| 969 } | |
| 970 } | |
| 971 | |
| 972 | |
| 1226 String _name; | 973 String _name; |
| 1227 int _id; | 974 int _id; |
| 1228 bool _asyncUsed; | 975 bool _asyncUsed; |
| 976 int _pendingWrites = 0; | |
| 1229 | 977 |
| 1230 _FileOperationScheduler _scheduler; | 978 SendPort _fileService; |
| 1231 | 979 |
| 1232 Function _closeHandler; | 980 Function _closeHandler; |
| 1233 Function _readByteHandler; | 981 Function _readByteHandler; |
| 1234 Function _readListHandler; | 982 Function _readListHandler; |
| 1235 Function _noPendingWriteHandler; | 983 Function _noPendingWriteHandler; |
| 1236 Function _positionHandler; | 984 Function _positionHandler; |
| 1237 Function _setPositionHandler; | 985 Function _setPositionHandler; |
| 1238 Function _truncateHandler; | 986 Function _truncateHandler; |
| 1239 Function _lengthHandler; | 987 Function _lengthHandler; |
| 1240 Function _flushHandler; | 988 Function _flushHandler; |
| 1241 Function _errorHandler; | 989 Function _errorHandler; |
| 1242 } | 990 } |
| OLD | NEW |