Commit ae9b206037466b4e1f5a962f27c133141bec8b60
1 parent
7db8bdff
stowing circular buffer work
Showing
2 changed files
with
83 additions
and
56 deletions
client.cpp
| ... | ... | @@ -54,23 +54,12 @@ bool Client::readFdIntoBuffer() |
| 54 | 54 | if (disconnecting) |
| 55 | 55 | return false; |
| 56 | 56 | |
| 57 | - if (wi > CLIENT_MAX_BUFFER_SIZE) | |
| 58 | - { | |
| 59 | - setReadyForReading(false); | |
| 60 | - return true; | |
| 61 | - } | |
| 62 | - | |
| 63 | - int n; | |
| 64 | - while ((n = read(fd, &readbuf[wi], getReadBufMaxWriteSize())) != 0) | |
| 57 | + int n = 0; | |
| 58 | + while (getReadBufFreeSpace() > 0 && (n = read(fd, &readbuf[wi], getReadBufMaxWriteSize())) != 0) | |
| 65 | 59 | { |
| 66 | 60 | if (n > 0) |
| 67 | 61 | { |
| 68 | - wi += n; | |
| 69 | - | |
| 70 | - if (getReadBufMaxWriteSize() == 0) | |
| 71 | - { | |
| 72 | - growReadBuffer(); | |
| 73 | - } | |
| 62 | + wi = (wi + n) % readBufsize; | |
| 74 | 63 | } |
| 75 | 64 | |
| 76 | 65 | if (n < 0) |
| ... | ... | @@ -82,11 +71,24 @@ bool Client::readFdIntoBuffer() |
| 82 | 71 | else |
| 83 | 72 | check<std::runtime_error>(n); |
| 84 | 73 | } |
| 74 | + | |
| 75 | + // Make sure we either always have enough space for a next call of this method, or stop reading the fd. | |
| 76 | + if (getReadBufFreeSpace() == 0) | |
| 77 | + { | |
| 78 | + if (readBufsize * 2 < CLIENT_MAX_BUFFER_SIZE) | |
| 79 | + { | |
| 80 | + growReadBuffer(); | |
| 81 | + } | |
| 82 | + else | |
| 83 | + { | |
| 84 | + setReadyForReading(false); | |
| 85 | + break; | |
| 86 | + } | |
| 87 | + } | |
| 85 | 88 | } |
| 86 | 89 | |
| 87 | 90 | if (n == 0) // client disconnected. |
| 88 | 91 | { |
| 89 | - //std::cerr << "normal disconnect" << std::endl; | |
| 90 | 92 | return false; |
| 91 | 93 | } |
| 92 | 94 | |
| ... | ... | @@ -197,6 +199,36 @@ std::string Client::repr() |
| 197 | 199 | return a.str(); |
| 198 | 200 | } |
| 199 | 201 | |
| 202 | +void Client::growReadBuffer() // TODO: refactor | |
| 203 | +{ | |
| 204 | + const size_t newBufSize = readBufsize * 2; | |
| 205 | + char *readbuf = (char*)realloc(this->readbuf, newBufSize); | |
| 206 | + if (readbuf == NULL) | |
| 207 | + throw std::runtime_error("Memory allocation failure in growReadBuffer()"); | |
| 208 | + this->readbuf = readbuf; | |
| 209 | + readBufsize = newBufSize; | |
| 210 | + | |
| 211 | + std::cout << "New read buf size: " << readBufsize << std::endl; | |
| 212 | +} | |
| 213 | + | |
| 214 | +void Client::growWriteBuffer(size_t add_size) | |
| 215 | +{ | |
| 216 | + if (add_size == 0) | |
| 217 | + return; | |
| 218 | + | |
| 219 | + const size_t grow_by = std::max<size_t>(add_size, writeBufsize*2); | |
| 220 | + const size_t newBufSize = writeBufsize + grow_by; | |
| 221 | + char *writebuf = (char*)realloc(this->writebuf, newBufSize); | |
| 222 | + | |
| 223 | + if (writebuf == NULL) | |
| 224 | + throw std::runtime_error("Memory allocation failure in growWriteBuffer()"); | |
| 225 | + | |
| 226 | + this->writebuf = writebuf; | |
| 227 | + writeBufsize = newBufSize; | |
| 228 | + | |
| 229 | + std::cout << "New write buf size: " << writeBufsize << std::endl; | |
| 230 | +} | |
| 231 | + | |
| 200 | 232 | void Client::setReadyForWriting(bool val) |
| 201 | 233 | { |
| 202 | 234 | if (disconnecting) |
| ... | ... | @@ -250,7 +282,7 @@ bool Client::bufferToMqttPackets(std::vector<MqttPacket> &packetQueueIn, Client_ |
| 250 | 282 | fixed_header_length++; |
| 251 | 283 | if (remaining_length_i >= wi) |
| 252 | 284 | return false; |
| 253 | - encodedByte = readbuf[remaining_length_i++]; | |
| 285 | + encodedByte = readbuf[remaining_length_i++ % readBufsize]; | |
| 254 | 286 | packet_length += (encodedByte & 127) * multiplier; |
| 255 | 287 | multiplier *= 128; |
| 256 | 288 | if (multiplier > 128*128*128) |
| ... | ... | @@ -266,27 +298,28 @@ bool Client::bufferToMqttPackets(std::vector<MqttPacket> &packetQueueIn, Client_ |
| 266 | 298 | |
| 267 | 299 | if (packet_length <= getReadBufBytesUsed()) |
| 268 | 300 | { |
| 301 | + // TODO: deal with circularness here, or in the packet? | |
| 269 | 302 | MqttPacket packet(&readbuf[ri], packet_length, fixed_header_length, sender); |
| 270 | 303 | packetQueueIn.push_back(std::move(packet)); |
| 271 | 304 | |
| 272 | - ri += packet_length; | |
| 273 | - assert(ri <= wi); | |
| 305 | + ri = (ri + packet_length) % readBufsize; | |
| 274 | 306 | } |
| 275 | 307 | else |
| 276 | 308 | break; |
| 277 | 309 | |
| 278 | 310 | } |
| 279 | 311 | |
| 280 | - if (ri == wi) | |
| 312 | + if (getReadBufMaxWriteSize() > 0) | |
| 281 | 313 | { |
| 282 | - ri = 0; | |
| 283 | - wi = 0; | |
| 284 | 314 | setReadyForReading(true); |
| 285 | 315 | } |
| 286 | 316 | |
| 287 | - return true; | |
| 317 | + if (getReadBufBytesUsed() == 0) | |
| 318 | + { | |
| 319 | + // TODO: reset buffer to normal size after a while of not needing it, or not needing the extra space. | |
| 320 | + } | |
| 288 | 321 | |
| 289 | - // TODO: reset buffer to normal size after a while of not needing it, or not needing the extra space. | |
| 322 | + return true; | |
| 290 | 323 | } |
| 291 | 324 | |
| 292 | 325 | void Client::setClientProperties(const std::string &clientId, const std::string username, bool connectPacketSeen, uint16_t keepalive) | ... | ... |
client.h
| ... | ... | @@ -6,6 +6,7 @@ |
| 6 | 6 | #include <vector> |
| 7 | 7 | #include <mutex> |
| 8 | 8 | #include <iostream> |
| 9 | +#include | |
| 9 | 10 | |
| 10 | 11 | #include "forward_declarations.h" |
| 11 | 12 | |
| ... | ... | @@ -24,8 +25,8 @@ class Client |
| 24 | 25 | |
| 25 | 26 | char *readbuf = NULL; // With many clients, it may not be smart to keep a (big) buffer around. |
| 26 | 27 | size_t readBufsize = CLIENT_BUFFER_SIZE; |
| 27 | - int wi = 0; | |
| 28 | - int ri = 0; | |
| 28 | + uint wi = 0; | |
| 29 | + uint ri = 0; | |
| 29 | 30 | |
| 30 | 31 | char *writebuf = NULL; // With many clients, it may not be smart to keep a (big) buffer around. |
| 31 | 32 | size_t writeBufsize = CLIENT_BUFFER_SIZE; |
| ... | ... | @@ -51,30 +52,38 @@ class Client |
| 51 | 52 | ThreadData_p threadData; |
| 52 | 53 | std::mutex writeBufMutex; |
| 53 | 54 | |
| 54 | - // Note: this is not the inverse of free space, because there can be non-used lead-in in the buffer! | |
| 55 | - size_t getReadBufBytesUsed() | |
| 55 | + inline size_t getReadBufBytesUsed() const | |
| 56 | 56 | { |
| 57 | - return wi - ri; | |
| 57 | + size_t result; | |
| 58 | + if (wi >= ri) | |
| 59 | + result = wi - ri; | |
| 60 | + else | |
| 61 | + result = (readBufsize + wi) - ri; | |
| 62 | + return result; | |
| 58 | 63 | }; |
| 59 | 64 | |
| 60 | - size_t getReadBufMaxWriteSize() | |
| 65 | + inline size_t getReadBufFreeSpace() const | |
| 61 | 66 | { |
| 62 | - size_t available = readBufsize - wi; | |
| 63 | - return available; | |
| 67 | + size_t result = readBufsize - getReadBufBytesUsed() - 1; | |
| 68 | + return result; | |
| 64 | 69 | } |
| 65 | 70 | |
| 66 | - void growReadBuffer() | |
| 71 | + inline size_t getReadBufMaxWriteSize() const | |
| 67 | 72 | { |
| 68 | - const size_t newBufSize = readBufsize * 2; | |
| 69 | - char *readbuf = (char*)realloc(this->readbuf, newBufSize); | |
| 70 | - if (readbuf == NULL) | |
| 71 | - throw std::runtime_error("Memory allocation failure in growReadBuffer()"); | |
| 72 | - this->readbuf = readbuf; | |
| 73 | - readBufsize = newBufSize; | |
| 74 | - | |
| 75 | - //std::cout << "New read buf size: " << readBufsize << std::endl; | |
| 73 | + const size_t available_space = getReadBufFreeSpace(); | |
| 74 | + | |
| 75 | + size_t result = 0; | |
| 76 | + if (wi >= ri) | |
| 77 | + result = available_space - wi; | |
| 78 | + else | |
| 79 | + result = ri - wi - 1; | |
| 80 | + | |
| 81 | + return result; | |
| 76 | 82 | } |
| 77 | 83 | |
| 84 | + void growReadBuffer(); | |
| 85 | + | |
| 86 | + | |
| 78 | 87 | size_t getWriteBufMaxWriteSize() |
| 79 | 88 | { |
| 80 | 89 | size_t available = writeBufsize - wwi; |
| ... | ... | @@ -87,23 +96,8 @@ class Client |
| 87 | 96 | return wwi - wri; |
| 88 | 97 | }; |
| 89 | 98 | |
| 90 | - void growWriteBuffer(size_t add_size) | |
| 91 | - { | |
| 92 | - if (add_size == 0) | |
| 93 | - return; | |
| 94 | - | |
| 95 | - const size_t grow_by = std::max<size_t>(add_size, writeBufsize*2); | |
| 96 | - const size_t newBufSize = writeBufsize + grow_by; | |
| 97 | - char *writebuf = (char*)realloc(this->writebuf, newBufSize); | |
| 98 | - | |
| 99 | - if (writebuf == NULL) | |
| 100 | - throw std::runtime_error("Memory allocation failure in growWriteBuffer()"); | |
| 99 | + void growWriteBuffer(size_t add_size); | |
| 101 | 100 | |
| 102 | - this->writebuf = writebuf; | |
| 103 | - writeBufsize = newBufSize; | |
| 104 | - | |
| 105 | - //std::cout << "New write buf size: " << writeBufsize << std::endl; | |
| 106 | - } | |
| 107 | 101 | |
| 108 | 102 | void setReadyForWriting(bool val); |
| 109 | 103 | void setReadyForReading(bool val); | ... | ... |