| 180 | */ |
| 181 | |
| 182 | int queue_enqueue(cls_method_context_t hctx, cls_queue_enqueue_op& op, cls_queue_head& head) |
| 183 | { |
| 184 | if ((head.front.offset == head.tail.offset) && (head.tail.gen == head.front.gen + 1)) { |
| 185 | CLS_LOG(0, "ERROR: No space left in queue"); |
| 186 | return -ENOSPC; |
| 187 | } |
| 188 | |
| 189 | for (auto& bl_data : op.bl_data_vec) { |
| 190 | bufferlist bl; |
| 191 | uint16_t entry_start = QUEUE_ENTRY_START; |
| 192 | encode(entry_start, bl); |
| 193 | uint64_t data_size = bl_data.length(); |
| 194 | encode(data_size, bl); |
| 195 | bl.claim_append(bl_data); |
| 196 | |
| 197 | CLS_LOG(10, "INFO: queue_enqueue(): Total size to be written is %u and data size is %lu", bl.length(), data_size); |
| 198 | |
| 199 | if (head.tail.offset >= head.front.offset) { |
| 200 | // check if data can fit in the remaining space in queue |
| 201 | if ((head.tail.offset + bl.length()) <= head.queue_size) { |
| 202 | CLS_LOG(5, "INFO: queue_enqueue: Writing data size and data: offset: %s, size: %u", head.tail.to_str().c_str(), bl.length()); |
| 203 | //write data size and data at tail offset |
| 204 | auto ret = cls_cxx_write2(hctx, head.tail.offset, bl.length(), &bl, CEPH_OSD_OP_FLAG_FADVISE_SEQUENTIAL); |
| 205 | if (ret < 0) { |
| 206 | return ret; |
| 207 | } |
| 208 | head.tail.offset += bl.length(); |
| 209 | } else { |
| 210 | uint64_t free_space_available = (head.queue_size - head.tail.offset) + (head.front.offset - head.max_head_size); |
| 211 | //Split data if there is free space available |
| 212 | if (bl.length() <= free_space_available) { |
| 213 | uint64_t size_before_wrap = head.queue_size - head.tail.offset; |
| 214 | bufferlist bl_data_before_wrap; |
| 215 | bl.splice(0, size_before_wrap, &bl_data_before_wrap); |
| 216 | //write spliced (data size and data) at tail offset |
| 217 | CLS_LOG(5, "INFO: queue_enqueue: Writing spliced data at offset: %s and data size: %u", head.tail.to_str().c_str(), bl_data_before_wrap.length()); |
| 218 | auto ret = cls_cxx_write2(hctx, head.tail.offset, bl_data_before_wrap.length(), &bl_data_before_wrap, CEPH_OSD_OP_FLAG_FADVISE_SEQUENTIAL); |
| 219 | if (ret < 0) { |
| 220 | return ret; |
| 221 | } |
| 222 | head.tail.offset = head.max_head_size; |
| 223 | head.tail.gen += 1; |
| 224 | //write remaining data at tail offset after wrapping around |
| 225 | CLS_LOG(5, "INFO: queue_enqueue: Writing remaining data at offset: %s and data size: %u", head.tail.to_str().c_str(), bl.length()); |
| 226 | ret = cls_cxx_write2(hctx, head.tail.offset, bl.length(), &bl, CEPH_OSD_OP_FLAG_FADVISE_SEQUENTIAL); |
| 227 | if (ret < 0) { |
| 228 | return ret; |
| 229 | } |
| 230 | head.tail.offset += bl.length(); |
| 231 | } else { |
| 232 | CLS_LOG(0, "ERROR: No space left in queue\n"); |
| 233 | // return queue full error |
| 234 | return -ENOSPC; |
| 235 | } |
| 236 | } |
| 237 | } else if (head.front.offset > head.tail.offset) { |
| 238 | if ((head.tail.offset + bl.length()) <= head.front.offset) { |
| 239 | CLS_LOG(5, "INFO: queue_enqueue: Writing data size and data: offset: %s, size: %u", head.tail.to_str().c_str(), bl.length()); |
no test coverage detected