]>
git.proxmox.com Git - ceph.git/blob - ceph/src/msg/async/dpdk/PacketUtil.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
3 * This file is open source software, licensed to you under the terms
4 * of the Apache License, Version 2.0 (the "License"). See the NOTICE file
5 * distributed with this work for additional information regarding copyright
6 * ownership. You may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
20 * Copyright (C) 2014 Cloudius Systems, Ltd.
23 #ifndef CEPH_MSG_PACKET_UTIL_H_
24 #define CEPH_MSG_PACKET_UTIL_H_
31 template <typename Offset
, typename Tag
>
34 static uint64_t& linearizations_ref() {
35 static thread_local
uint64_t linearization_count
;
36 return linearization_count
;
39 std::map
<Offset
, Packet
> map
;
41 static uint64_t linearizations() {
42 return linearizations_ref();
45 void merge(Offset offset
, Packet p
) {
48 auto end
= beg
+ p
.len();
49 // First, try to merge the packet with existing segment
50 for (auto it
= map
.begin(); it
!= map
.end();) {
51 auto& seg_pkt
= it
->second
;
52 auto seg_beg
= it
->first
;
53 auto seg_end
= seg_beg
+ seg_pkt
.len();
55 if (seg_beg
<= beg
&& end
<= seg_end
) {
56 // 1) seg_beg beg end seg_end
57 // We already have data in this packet
59 } else if (beg
<= seg_beg
&& seg_end
<= end
) {
60 // 2) beg seg_beg seg_end end
61 // The new segment contains more data than this old segment
62 // Delete the old one, insert the new one
66 } else if (beg
< seg_beg
&& seg_beg
<= end
&& end
<= seg_end
) {
67 // 3) beg seg_beg end seg_end
68 // Merge two segments, trim front of old segment
69 auto trim
= end
- seg_beg
;
70 seg_pkt
.trim_front(trim
);
71 p
.append(std::move(seg_pkt
));
72 // Delete the old one, insert the new one
76 } else if (seg_beg
<= beg
&& beg
<= seg_end
&& seg_end
< end
) {
77 // 4) seg_beg beg seg_end end
78 // Merge two segments, trim front of new segment
79 auto trim
= seg_end
- beg
;
81 // Append new data to the old segment, keep the old segment
82 seg_pkt
.append(std::move(p
));
84 ++linearizations_ref();
88 // 5) beg end < seg_beg seg_end
90 // 6) seg_beg seg_end < beg end
91 // Can not merge with this segment, keep looking
99 ++linearizations_ref();
100 map
.emplace(beg
, std::move(p
));
103 // Second, merge adjacent segments after this packet has been merged,
104 // because this packet might fill a "whole" and make two adjacent
106 for (auto it
= map
.begin(); it
!= map
.end();) {
108 auto& seg_pkt
= it
->second
;
109 auto seg_beg
= it
->first
;
110 auto seg_end
= seg_beg
+ seg_pkt
.len();
112 // The second segment
115 if (it_next
== map
.end()) {
118 auto& p
= it_next
->second
;
119 auto beg
= it_next
->first
;
120 auto end
= beg
+ p
.len();
122 // Merge the the second segment into first segment if possible
123 if (seg_beg
<= beg
&& beg
<= seg_end
&& seg_end
< end
) {
124 // Merge two segments, trim front of second segment
125 auto trim
= seg_end
- beg
;
127 // Append new data to the first segment, keep the first segment
128 seg_pkt
.append(std::move(p
));
130 // Delete the second segment
133 // Keep merging this first segment with its new next packet
134 // So we do not update the iterator: it
136 } else if (end
<= seg_end
) {
137 // The first segment has all the data in the second segment
138 // Delete the second segment
141 } else if (seg_end
< beg
) {
142 // Can not merge first segment with second segment
146 // If we reach here, we have a bug with merge.
147 std::cout
<< "packet_merger: merge error\n";