| 165 | } |
| 166 | |
| 167 | ssize_t PersistentCacheFile::preadv(const struct iovec *iov, int iovcnt, off_t offset) { |
| 168 | ssize_t ret = 0; |
| 169 | if (!ready) { |
| 170 | LOG_WARN("local path or size not set, read from source ", VALUE(offset)); |
| 171 | SCOPE_AUDIT("download", AU_FILEOP(m_name, offset, ret)); |
| 172 | ret = m_file->preadv(iov, iovcnt, offset); |
| 173 | return ret; |
| 174 | } |
| 175 | |
| 176 | iovector_view view((iovec *)iov, iovcnt); |
| 177 | size_t count = view.sum(); |
| 178 | if (count == 0) { |
| 179 | return 0; |
| 180 | } |
| 181 | |
| 182 | std::pair<off_t, size_t> q; |
| 183 | |
| 184 | off_t align_left = align_down(offset, m_fs->block_size); |
| 185 | off_t align_right = align_up(offset + count, m_fs->block_size); |
| 186 | |
| 187 | again: |
| 188 | |
| 189 | m_local_file->lock(align_left, align_right - align_left); |
| 190 | { |
| 191 | DEFER({m_local_file->unlock(align_left, align_right - align_left);}); |
| 192 | q = m_local_file->query_refill_range(offset, count); |
| 193 | if (q.second == 0) { // no need to refill |
| 194 | return m_local_file->preadv(iov, iovcnt, offset); |
| 195 | } |
| 196 | } |
| 197 | |
| 198 | // refill |
| 199 | uint64_t r_offset = q.first; |
| 200 | uint64_t r_count = q.second; |
| 201 | if (r_offset + r_count > m_size) { |
| 202 | r_count = m_size - r_offset; |
| 203 | } |
| 204 | |
| 205 | IOVector buffer(*m_fs->io_alloc); |
| 206 | |
| 207 | auto lr = m_local_file->try_lock_wait(r_offset, r_count); |
| 208 | if (lr < 0) { |
| 209 | goto again; |
| 210 | } |
| 211 | DEFER({ m_local_file->unlock(r_offset, r_count); }); |
| 212 | |
| 213 | auto alloc = buffer.push_back(r_count); |
| 214 | if (alloc < r_count) { |
| 215 | LOG_ERROR("memory allocate failed, refill size:`, alloc:`", r_count, alloc); |
| 216 | SCOPE_AUDIT("download", AU_FILEOP(m_name, offset, ret)); |
| 217 | ret = m_file->preadv(iov, iovcnt, offset); |
| 218 | return ret; |
| 219 | } |
| 220 | |
| 221 | ssize_t read = 0; |
| 222 | { |
| 223 | SCOPE_AUDIT("download", AU_FILEOP(m_name, r_offset, read)); |
| 224 | read = m_file->preadv(buffer.iovec(), buffer.iovcnt(), r_offset); |
no test coverage detected