Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2017 The Chromium OS Authors. All rights reserved. | 1 // Copyright 2017 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 "compressor_io_javascript_stream.h" | 5 #include "compressor_io_javascript_stream.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 #include <thread> | 8 #include <thread> |
| 9 | 9 |
| 10 #include "archive.h" | |
| 11 #include "ppapi/cpp/logging.h" | 10 #include "ppapi/cpp/logging.h" |
| 12 | 11 |
| 13 CompressorIOJavaScriptStream::CompressorIOJavaScriptStream( | 12 CompressorIOJavaScriptStream::CompressorIOJavaScriptStream( |
| 14 JavaScriptCompressorRequestorInterface* requestor) | 13 JavaScriptCompressorRequestorInterface* requestor) |
| 15 : requestor_(requestor) { | 14 : requestor_(requestor), buffer_offset_(-1), buffer_data_length_(0) { |
| 16 pthread_mutex_init(&shared_state_lock_, NULL); | 15 pthread_mutex_init(&shared_state_lock_, nullptr); |
| 17 pthread_cond_init(&available_data_cond_, NULL); | 16 pthread_cond_init(&available_data_cond_, nullptr); |
| 18 pthread_cond_init(&data_written_cond_, NULL); | 17 pthread_cond_init(&data_written_cond_, nullptr); |
| 19 | 18 |
| 20 pthread_mutex_lock(&shared_state_lock_); | 19 pthread_mutex_lock(&shared_state_lock_); |
| 21 available_data_ = false; | 20 available_data_ = false; |
| 21 buffer_ = new char[compressor_stream_constants::kMaximumDataChunkSize]; | |
| 22 pthread_mutex_unlock(&shared_state_lock_); | 22 pthread_mutex_unlock(&shared_state_lock_); |
| 23 } | 23 } |
| 24 | 24 |
| 25 CompressorIOJavaScriptStream::~CompressorIOJavaScriptStream() { | 25 CompressorIOJavaScriptStream::~CompressorIOJavaScriptStream() { |
| 26 pthread_mutex_lock(&shared_state_lock_); | |
| 27 delete buffer_; | |
| 28 pthread_mutex_unlock(&shared_state_lock_); | |
| 26 pthread_cond_destroy(&data_written_cond_); | 29 pthread_cond_destroy(&data_written_cond_); |
| 27 pthread_cond_destroy(&available_data_cond_); | 30 pthread_cond_destroy(&available_data_cond_); |
| 28 pthread_mutex_destroy(&shared_state_lock_); | 31 pthread_mutex_destroy(&shared_state_lock_); |
| 29 }; | 32 }; |
| 30 | 33 |
| 31 int64_t CompressorIOJavaScriptStream::Write(int64_t byte_to_write, | 34 int64_t CompressorIOJavaScriptStream::Flush() { |
| 32 const pp::VarArrayBuffer& buffer) { | |
| 33 pthread_mutex_lock(&shared_state_lock_); | 35 pthread_mutex_lock(&shared_state_lock_); |
| 34 requestor_->WriteChunkRequest(byte_to_write, buffer); | 36 |
| 37 if (buffer_data_length_ == 0) { | |
| 38 pthread_mutex_unlock(&shared_state_lock_); | |
| 39 return 0; | |
| 40 } | |
| 41 | |
| 42 // Copy the data in buffer_ to array_buffer. | |
| 43 pp::VarArrayBuffer array_buffer(buffer_data_length_); | |
| 44 char* array_buffer_data = static_cast<char*>(array_buffer.Map()); | |
| 45 memcpy(array_buffer_data, buffer_, buffer_data_length_); | |
| 46 array_buffer.Unmap(); | |
| 47 | |
| 48 requestor_->WriteChunkRequest(buffer_offset_, | |
| 49 buffer_data_length_, | |
| 50 array_buffer); | |
| 35 | 51 |
| 36 pthread_cond_wait(&data_written_cond_, &shared_state_lock_); | 52 pthread_cond_wait(&data_written_cond_, &shared_state_lock_); |
| 37 | 53 |
| 38 int64_t written_bytes = written_bytes_; | 54 int64_t written_bytes = written_bytes_; |
| 55 if (written_bytes < buffer_data_length_) { | |
| 56 pthread_mutex_unlock(&shared_state_lock_); | |
| 57 return -1 /* Error */; | |
| 58 } | |
| 59 | |
| 60 // Reset the offset and length to the default values. | |
| 61 buffer_offset_ = -1; | |
| 62 buffer_data_length_ = 0; | |
| 63 | |
| 39 pthread_mutex_unlock(&shared_state_lock_); | 64 pthread_mutex_unlock(&shared_state_lock_); |
| 40 | 65 return buffer_data_length_; |
| 41 return written_bytes; | |
| 42 } | 66 } |
| 43 | 67 |
| 44 void CompressorIOJavaScriptStream::WriteChunkDone(int64_t written_bytes) { | 68 int64_t CompressorIOJavaScriptStream::Write(int64_t zip_offset, |
| 69 int64_t zip_length, | |
| 70 const char* zip_buffer) { | |
| 71 pthread_mutex_lock(&shared_state_lock_); | |
| 72 | |
| 73 // The offset from which the data should be written onto the archive. | |
| 74 int64_t current_offset = zip_offset; | |
| 75 int64_t left_length = zip_length; | |
| 76 const char* buffer_pointer = zip_buffer; | |
| 77 | |
| 78 do { | |
| 79 // Flush the buffer if the data in the buffer cannot be reused. | |
| 80 // The following is the brief explanation about the conditions of the | |
| 81 // following if statement. | |
| 82 // 1: The buffer is not in the initial state (empty). | |
| 83 // The buffer should have some data to flush. | |
| 84 // 2: This write operation is not to append the data to the buffer. | |
| 85 // 3: The buffer overflows if we append the data to the buffer. | |
| 86 // If we can append the new data to the current data in the buffer, | |
| 87 // we should not flush the buffer. | |
| 88 // 4: The index to write is outside the buffer. | |
| 89 // If we want to write data outside the range, we first need to flush | |
| 90 // the buffer, and then cache the data in the buffer. | |
| 91 if (buffer_offset_ >= 0 && /* 1 */ | |
| 92 (current_offset != buffer_offset_ + buffer_data_length_ || /* 2 */ | |
| 93 buffer_data_length_ + left_length > | |
| 94 compressor_stream_constants::kMaximumDataChunkSize) && /* 3 */ | |
| 95 (current_offset < buffer_offset_ || | |
| 96 buffer_offset_ + buffer_data_length_ < | |
| 97 current_offset + left_length) /* 4 */ ) { | |
| 98 pthread_mutex_unlock(&shared_state_lock_); | |
| 99 Flush(); | |
|
mtomasz
2017/04/11 06:36:45
Do we need to check for the return value of Flush?
| |
| 100 pthread_mutex_lock(&shared_state_lock_); | |
| 101 } | |
| 102 | |
| 103 // How many bytes we should copy to buffer_ in this iteration. | |
| 104 int64_t copy_length = std::min( | |
| 105 left_length, compressor_stream_constants::kMaximumDataChunkSize); | |
| 106 // Set up the buffer_offset_ if the buffer_ has no data. | |
| 107 if (buffer_offset_ == -1 /* initial state */) | |
| 108 buffer_offset_ = current_offset; | |
| 109 // Calculate the relative offset from left_length. | |
| 110 int64_t offset_in_buffer = current_offset - buffer_offset_; | |
| 111 // Copy data from zip_buffer, which is pointed by buffer_pointer, to buffer_ . | |
| 112 memcpy(buffer_ + offset_in_buffer, buffer_pointer, copy_length); | |
| 113 | |
| 114 // Update variables. | |
|
mtomasz
2017/04/11 06:36:45
nit: This comment has no meaning, let's remove.
| |
| 115 buffer_pointer += copy_length; | |
| 116 buffer_data_length_ = std::max( | |
| 117 buffer_data_length_, offset_in_buffer + copy_length); | |
| 118 current_offset += copy_length; | |
| 119 left_length -= copy_length; | |
| 120 } while (left_length > 0); | |
| 121 | |
| 122 pthread_mutex_unlock(&shared_state_lock_); | |
| 123 return zip_length; | |
| 124 } | |
| 125 | |
| 126 int64_t CompressorIOJavaScriptStream::WriteChunkDone(int64_t written_bytes) { | |
| 45 pthread_mutex_lock(&shared_state_lock_); | 127 pthread_mutex_lock(&shared_state_lock_); |
| 46 written_bytes_ = written_bytes; | 128 written_bytes_ = written_bytes; |
| 47 pthread_cond_signal(&data_written_cond_); | 129 pthread_cond_signal(&data_written_cond_); |
| 48 pthread_mutex_unlock(&shared_state_lock_); | 130 pthread_mutex_unlock(&shared_state_lock_); |
| 131 return written_bytes; | |
| 49 } | 132 } |
| 50 | 133 |
| 51 int64_t CompressorIOJavaScriptStream::Read(int64_t bytes_to_read, | 134 int64_t CompressorIOJavaScriptStream::Read(int64_t bytes_to_read, |
| 52 char* destination_buffer) { | 135 char* destination_buffer) { |
| 53 pthread_mutex_lock(&shared_state_lock_); | 136 pthread_mutex_lock(&shared_state_lock_); |
| 54 | 137 |
| 55 destination_buffer_ = destination_buffer; | 138 destination_buffer_ = destination_buffer; |
| 56 requestor_->ReadFileChunkRequest(bytes_to_read); | 139 requestor_->ReadFileChunkRequest(bytes_to_read); |
| 57 | 140 |
| 58 while (!available_data_) { | 141 while (!available_data_) { |
| 59 pthread_cond_wait(&available_data_cond_, &shared_state_lock_); | 142 pthread_cond_wait(&available_data_cond_, &shared_state_lock_); |
| 60 } | 143 } |
| 61 | 144 |
| 62 int64_t read_bytes = read_bytes_; | 145 int64_t read_bytes = read_bytes_; |
| 63 available_data_ = false; | 146 available_data_ = false; |
| 64 pthread_mutex_unlock(&shared_state_lock_); | 147 pthread_mutex_unlock(&shared_state_lock_); |
| 65 return read_bytes; | 148 return read_bytes; |
| 66 } | 149 } |
| 67 | 150 |
| 68 void CompressorIOJavaScriptStream::ReadFileChunkDone(int64_t read_bytes, | 151 int64_t CompressorIOJavaScriptStream::ReadFileChunkDone(int64_t read_bytes, |
| 69 pp::VarArrayBuffer* array_buffer) { | 152 pp::VarArrayBuffer* array_buffer) { |
| 70 pthread_mutex_lock(&shared_state_lock_); | 153 pthread_mutex_lock(&shared_state_lock_); |
| 71 | 154 |
| 72 // JavaScript sets a negative value in read_bytes if an error occurred while | 155 // JavaScript sets a negative value in read_bytes if an error occurred while |
| 73 // reading a chunk. | 156 // reading a chunk. |
| 74 if (read_bytes >= 0) { | 157 if (read_bytes >= 0) { |
| 75 char* array_buffer_data = static_cast<char*>(array_buffer->Map()); | 158 char* array_buffer_data = static_cast<char*>(array_buffer->Map()); |
| 76 memcpy(destination_buffer_, array_buffer_data, read_bytes); | 159 memcpy(destination_buffer_, array_buffer_data, read_bytes); |
| 77 array_buffer->Unmap(); | 160 array_buffer->Unmap(); |
| 78 } | 161 } |
| 79 | 162 |
| 80 read_bytes_ = read_bytes; | 163 read_bytes_ = read_bytes; |
| 81 available_data_ = true; | 164 available_data_ = true; |
| 82 pthread_cond_signal(&available_data_cond_); | 165 pthread_cond_signal(&available_data_cond_); |
| 83 pthread_mutex_unlock(&shared_state_lock_); | 166 pthread_mutex_unlock(&shared_state_lock_); |
| 167 return read_bytes; | |
| 84 } | 168 } |
| OLD | NEW |