@@ -28,6 +28,8 @@ Reader::Reader(unique_ptr<SequentialFile>&& file, Reporter* reporter,
28
28
backing_store_(new char [kBlockSize ]),
29
29
buffer_(),
30
30
eof_(false ),
31
+ read_error_(false ),
32
+ eof_offset_(0 ),
31
33
last_record_offset_(0 ),
32
34
end_of_buffer_offset_(0 ),
33
35
initial_offset_(initial_offset) {
@@ -170,6 +172,69 @@ uint64_t Reader::LastRecordOffset() {
170
172
return last_record_offset_;
171
173
}
172
174
175
+ void Reader::UnmarkEOF () {
176
+ if (read_error_) {
177
+ return ;
178
+ }
179
+
180
+ eof_ = false ;
181
+
182
+ if (eof_offset_ == 0 ) {
183
+ return ;
184
+ }
185
+
186
+ // If the EOF was in the middle of a block (a partial block was read) we have
187
+ // to read the rest of the block as ReadPhysicalRecord can only read full
188
+ // blocks and expects the file position indicator to be aligned to the start
189
+ // of a block.
190
+ //
191
+ // consumed_bytes + buffer_size() + remaining == kBlockSize
192
+
193
+ size_t consumed_bytes = eof_offset_ - buffer_.size ();
194
+ size_t remaining = kBlockSize - eof_offset_;
195
+
196
+ // backing_store_ is used to concatenate what is left in buffer_ and
197
+ // the remainder of the block. If buffer_ already uses backing_store_,
198
+ // we just append the new data.
199
+ if (buffer_.data () != backing_store_ + consumed_bytes) {
200
+ // Buffer_ does not use backing_store_ for storage.
201
+ // Copy what is left in buffer_ to backing_store.
202
+ memmove (backing_store_ + consumed_bytes, buffer_.data (), buffer_.size ());
203
+ }
204
+
205
+ Slice read_buffer;
206
+ Status status = file_->Read (remaining, &read_buffer,
207
+ backing_store_ + eof_offset_);
208
+
209
+ size_t added = read_buffer.size ();
210
+ end_of_buffer_offset_ += added;
211
+
212
+ if (!status.ok ()) {
213
+ if (added > 0 ) {
214
+ ReportDrop (added, status);
215
+ }
216
+
217
+ read_error_ = true ;
218
+ return ;
219
+ }
220
+
221
+ if (read_buffer.data () != backing_store_ + eof_offset_) {
222
+ // Read did not write to backing_store_
223
+ memmove (backing_store_ + eof_offset_, read_buffer.data (),
224
+ read_buffer.size ());
225
+ }
226
+
227
+ buffer_ = Slice (backing_store_ + consumed_bytes,
228
+ eof_offset_ + added - consumed_bytes);
229
+
230
+ if (added < remaining) {
231
+ eof_ = true ;
232
+ eof_offset_ += added;
233
+ } else {
234
+ eof_offset_ = 0 ;
235
+ }
236
+ }
237
+
173
238
void Reader::ReportCorruption (size_t bytes, const char * reason) {
174
239
ReportDrop (bytes, Status::Corruption (reason));
175
240
}
@@ -184,18 +249,19 @@ void Reader::ReportDrop(size_t bytes, const Status& reason) {
184
249
unsigned int Reader::ReadPhysicalRecord (Slice* result) {
185
250
while (true ) {
186
251
if (buffer_.size () < (size_t )kHeaderSize ) {
187
- if (!eof_) {
252
+ if (!eof_ && !read_error_ ) {
188
253
// Last read was a full read, so this is a trailer to skip
189
254
buffer_.clear ();
190
255
Status status = file_->Read (kBlockSize , &buffer_, backing_store_);
191
256
end_of_buffer_offset_ += buffer_.size ();
192
257
if (!status.ok ()) {
193
258
buffer_.clear ();
194
259
ReportDrop (kBlockSize , status);
195
- eof_ = true ;
260
+ read_error_ = true ;
196
261
return kEof ;
197
262
} else if (buffer_.size () < (size_t )kBlockSize ) {
198
263
eof_ = true ;
264
+ eof_offset_ = buffer_.size ();
199
265
}
200
266
continue ;
201
267
} else if (buffer_.size () == 0 ) {
0 commit comments