| 101 | } |
| 102 | |
| 103 | void UncompressedFile::write(const char * s, std::streamsize n) { |
| 104 | /* mutex lock */ |
| 105 | std::unique_lock<std::mutex> lock(m_mutex); |
| 106 | |
| 107 | /* wait for free space */ |
| 108 | tellgChanged.wait(lock, [&] { |
| 109 | return |
| 110 | m_abort || |
| 111 | ((m_tellp - m_tellg) < m_bufferSize); |
| 112 | }); |
| 113 | |
| 114 | /* write data */ |
| 115 | while (n > 0) { |
| 116 | /* find starting log container */ |
| 117 | std::shared_ptr<LogContainer> logContainer = logContainerContaining(m_tellp); |
| 118 | |
| 119 | /* append new log container */ |
| 120 | if (!logContainer) { |
| 121 | /* append new log container */ |
| 122 | logContainer = std::make_shared<LogContainer>(); |
| 123 | logContainer->uncompressedFile.resize(m_defaultLogContainerSize); |
| 124 | logContainer->uncompressedFileSize = logContainer->uncompressedFile.size(); |
| 125 | if (!m_data.empty()) { |
| 126 | logContainer->filePosition = |
| 127 | m_data.back()->uncompressedFileSize + |
| 128 | m_data.back()->filePosition; |
| 129 | } |
| 130 | m_data.push_back(logContainer); |
| 131 | } |
| 132 | |
| 133 | /* offset to write */ |
| 134 | std::streamoff offset = m_tellp - logContainer->filePosition; |
| 135 | |
| 136 | /* copy data */ |
| 137 | std::streamsize pcount = std::min(n, static_cast<std::streamsize>(logContainer->uncompressedFileSize - offset)); |
| 138 | if (pcount > 0) { |
| 139 | std::copy(s, s + pcount, logContainer->uncompressedFile.begin() + offset); |
| 140 | |
| 141 | /* new put position */ |
| 142 | m_tellp += pcount; |
| 143 | |
| 144 | /* advance */ |
| 145 | s += pcount; |
| 146 | |
| 147 | /* calculate remaining data to copy */ |
| 148 | n -= pcount; |
| 149 | } |
| 150 | } |
| 151 | |
| 152 | /* if new position is behind eof, shift it */ |
| 153 | if (m_tellp >= m_fileSize) |
| 154 | m_fileSize = m_tellp; |
| 155 | |
| 156 | /* notify */ |
| 157 | tellpChanged.notify_all(); |
| 158 | } |
| 159 | |
| 160 | std::streampos UncompressedFile::tellp() { |