1 /*
2 Copyright 2013-2015 Skytechnology sp. z o.o.
3
4 This file is part of LizardFS.
5
6 LizardFS is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, version 3.
9
10 LizardFS is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with LizardFS. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "common/platform.h"
20 #include <fcntl.h>
21 #include <unistd.h>
22 #include <cassert>
23 #include <cerrno>
24 #include <cstddef>
25 #include <cstdint>
26 #include <ios>
27 #include <stdexcept>
28
29 #include "chunkserver/output_buffer.h"
30 #include "common/crc.h"
31 #include "common/massert.h"
32 #include "devtools/request_log.h"
33
OutputBuffer(size_t internalBufferCapacity)34 OutputBuffer::OutputBuffer(size_t internalBufferCapacity)
35 : internalBufferCapacity_(internalBufferCapacity),
36 buffer_(internalBufferCapacity, 0),
37 bufferUnflushedDataFirstIndex_(0),
38 bufferUnflushedDataOneAfterLastIndex_(0)
39 {
40 eassert(internalBufferCapacity > 0);
41 buffer_.reserve(internalBufferCapacity_);
42 }
43
writeOutToAFileDescriptor(int outputFileDescriptor)44 OutputBuffer::WriteStatus OutputBuffer::writeOutToAFileDescriptor(int outputFileDescriptor) {
45 while (bytesInABuffer() > 0) {
46 ssize_t ret = ::write(outputFileDescriptor, &buffer_[bufferUnflushedDataFirstIndex_],
47 bytesInABuffer());
48 if (ret <= 0) {
49 if (ret == 0 || errno == EAGAIN) {
50 return WRITE_AGAIN;
51 }
52 return WRITE_ERROR;
53 }
54 bufferUnflushedDataFirstIndex_ += ret;
55 }
56 return WRITE_DONE;
57 }
58
bytesInABuffer() const59 size_t OutputBuffer::bytesInABuffer() const {
60 return bufferUnflushedDataOneAfterLastIndex_ - bufferUnflushedDataFirstIndex_;
61 }
62
clear()63 void OutputBuffer::clear() {
64 bufferUnflushedDataFirstIndex_ = 0;
65 bufferUnflushedDataOneAfterLastIndex_ = 0;
66 }
67
copyIntoBuffer(int inputFileDescriptor,size_t len,off_t * offset)68 ssize_t OutputBuffer::copyIntoBuffer(int inputFileDescriptor, size_t len, off_t* offset) {
69 eassert(len + bufferUnflushedDataOneAfterLastIndex_ <= internalBufferCapacity_);
70 off_t bytes_written = 0;
71 while (len > 0) {
72 ssize_t ret = pread(inputFileDescriptor, (void*)&buffer_[bufferUnflushedDataOneAfterLastIndex_], len,
73 (offset ? *offset : 0));
74 if (ret <= 0) {
75 return bytes_written;
76 }
77 len -= ret;
78 bufferUnflushedDataOneAfterLastIndex_ += ret;
79 bytes_written += ret;
80 }
81 return bytes_written;
82 }
83
checkCRC(size_t bytes,uint32_t crc) const84 bool OutputBuffer::checkCRC(size_t bytes, uint32_t crc) const {
85 assert(bufferUnflushedDataOneAfterLastIndex_ - bytes > 0
86 && bufferUnflushedDataOneAfterLastIndex_ - bytes < buffer_.size());
87 return mycrc32(0, &buffer_[bufferUnflushedDataOneAfterLastIndex_ - bytes], bytes) == crc;
88 }
89
copyIntoBuffer(const void * mem,size_t len)90 ssize_t OutputBuffer::copyIntoBuffer(const void *mem, size_t len) {
91 eassert(bufferUnflushedDataOneAfterLastIndex_ + len <= internalBufferCapacity_);
92 memcpy((void*)&buffer_[bufferUnflushedDataOneAfterLastIndex_], mem, len);
93 bufferUnflushedDataOneAfterLastIndex_ += len;
94
95 return len;
96 }
97
~OutputBuffer()98 OutputBuffer::~OutputBuffer() {
99 }
100