| OLD | NEW |
| 1 // Copyright 2014 The Chromium OS Authors. All rights reserved. | 1 // Copyright 2014 The Chromium OS Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "volume_reader_javascript_stream.h" | 5 #include "volume_reader_javascript_stream.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 | 9 |
| 10 #include "third_party/zlib/contrib/minizip/unzip.h" | 10 #include "third_party/zlib/contrib/minizip/unzip.h" |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 // true then the second read ahead data is the same as the first read ahead | 64 // true then the second read ahead data is the same as the first read ahead |
| 65 // data so we can just ignore it. | 65 // data so we can just ignore it. |
| 66 | 66 |
| 67 // TODO(mtomasz): We don't need to discard everything. Sometimes part of the | 67 // TODO(mtomasz): We don't need to discard everything. Sometimes part of the |
| 68 // buffer can still be used. In such case we should use it. That can greatly | 68 // buffer can still be used. In such case we should use it. That can greatly |
| 69 // improve traversing headers for archives with small files! | 69 // improve traversing headers for archives with small files! |
| 70 | 70 |
| 71 pthread_mutex_lock(&shared_state_lock_); | 71 pthread_mutex_lock(&shared_state_lock_); |
| 72 if (read_offset == offset_ && !available_data_ && !read_error_) { | 72 if (read_offset == offset_ && !available_data_ && !read_error_) { |
| 73 // Signal VolumeReaderJavaScriptStream::Read to continue execution. Copies | 73 // Signal VolumeReaderJavaScriptStream::Read to continue execution. Copies |
| 74 // buffer locally so libarchive has the buffer in memory when working with | 74 // buffer locally so minizip has the buffer in memory when working with |
| 75 // it. Though we acquire a lock here this call is blocking only for a few | 75 // it. Though we acquire a lock here this call is blocking only for a few |
| 76 // moments as VolumeReaderJavaScriptStream::Read will release the lock with | 76 // moments as VolumeReaderJavaScriptStream::Read will release the lock with |
| 77 // pthread_cond_wait. So we cannot arrive at a deadlock that will block the | 77 // pthread_cond_wait. So we cannot arrive at a deadlock that will block the |
| 78 // main thread. | 78 // main thread. |
| 79 | 79 |
| 80 *read_ahead_array_buffer_ptr_ = array_buffer; // Copy operation. | 80 *read_ahead_array_buffer_ptr_ = array_buffer; // Copy operation. |
| 81 available_data_ = true; | 81 available_data_ = true; |
| 82 | 82 |
| 83 pthread_cond_signal(&available_data_cond_); | 83 pthread_cond_signal(&available_data_cond_); |
| 84 } | 84 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 134 } | 134 } |
| 135 pthread_cond_wait(&available_data_cond_, &shared_state_lock_); | 135 pthread_cond_wait(&available_data_cond_, &shared_state_lock_); |
| 136 } | 136 } |
| 137 } | 137 } |
| 138 | 138 |
| 139 if (read_error_) { // Read ahead failed. | 139 if (read_error_) { // Read ahead failed. |
| 140 pthread_mutex_unlock(&shared_state_lock_); | 140 pthread_mutex_unlock(&shared_state_lock_); |
| 141 return -1; | 141 return -1; |
| 142 } | 142 } |
| 143 | 143 |
| 144 // Make data available for libarchive custom read. No need to lock this part. | 144 // Make data available for minizip custom read. No need to lock this part. |
| 145 // The reason is that VolumeReaderJavaScriptStream::RequestChunk is the only | 145 // The reason is that VolumeReaderJavaScriptStream::RequestChunk is the only |
| 146 // function that can set available_data_ back to false and let | 146 // function that can set available_data_ back to false and let |
| 147 // VolumeReaderJavaScriptStream::SetBufferAndSignal overwrite the buffer. But | 147 // VolumeReaderJavaScriptStream::SetBufferAndSignal overwrite the buffer. But |
| 148 // reading ahead is done only at the end of this function after the buffers | 148 // reading ahead is done only at the end of this function after the buffers |
| 149 // are switched. | 149 // are switched. |
| 150 *destination_buffer = read_ahead_array_buffer_ptr_->Map(); | 150 *destination_buffer = read_ahead_array_buffer_ptr_->Map(); |
| 151 int64_t bytes_read = | 151 int64_t bytes_read = |
| 152 std::min(static_cast<int64_t>(read_ahead_array_buffer_ptr_->ByteLength()), | 152 std::min(static_cast<int64_t>(read_ahead_array_buffer_ptr_->ByteLength()), |
| 153 bytes_to_read); | 153 bytes_to_read); |
| 154 | 154 |
| 155 offset_ += bytes_read; | 155 offset_ += bytes_read; |
| 156 last_read_chunk_offset_ = offset_; | 156 last_read_chunk_offset_ = offset_; |
| 157 | 157 |
| 158 // Ask for more data from JavaScript in the other buffer. This is the only | 158 // Ask for more data from JavaScript in the other buffer. This is the only |
| 159 // time when we switch buffers. The reason is that libarchive must | 159 // time when we switch buffers. The reason is that minizip must |
| 160 // always work on valid data and that data must be available until next | 160 // always work on valid data and that data must be available until next |
| 161 // VolumeReaderJavaScriptStream::Read call, and as the data can be received | 161 // VolumeReaderJavaScriptStream::Read call, and as the data can be received |
| 162 // at any time from JavaScript, we need a buffer to store it in case of | 162 // at any time from JavaScript, we need a buffer to store it in case of |
| 163 // reading ahead. | 163 // reading ahead. |
| 164 read_ahead_array_buffer_ptr_ = | 164 read_ahead_array_buffer_ptr_ = |
| 165 read_ahead_array_buffer_ptr_ != &first_array_buffer_ | 165 read_ahead_array_buffer_ptr_ != &first_array_buffer_ |
| 166 ? &first_array_buffer_ | 166 ? &first_array_buffer_ |
| 167 : &second_array_buffer_; | 167 : &second_array_buffer_; |
| 168 | 168 |
| 169 // Unmap old buffer. Only Read and constructor can Map the buffers so Read and | 169 // Unmap old buffer. Only Read and constructor can Map the buffers so Read and |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 248 // Read next chunk only if not at the end of archive. | 248 // Read next chunk only if not at the end of archive. |
| 249 if (archive_size_ <= offset_) | 249 if (archive_size_ <= offset_) |
| 250 return; | 250 return; |
| 251 | 251 |
| 252 int64_t bytes_to_read = | 252 int64_t bytes_to_read = |
| 253 std::min(length, archive_size_ - offset_ /* Positive check above. */); | 253 std::min(length, archive_size_ - offset_ /* Positive check above. */); |
| 254 available_data_ = false; | 254 available_data_ = false; |
| 255 | 255 |
| 256 requestor_->RequestFileChunk(request_id_, offset_, bytes_to_read); | 256 requestor_->RequestFileChunk(request_id_, offset_, bytes_to_read); |
| 257 } | 257 } |
| OLD | NEW |