]> git.proxmox.com Git - ceph.git/blob - ceph/src/seastar/src/net/packet.cc
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / seastar / src / net / packet.cc
1 /*
2 * This file is open source software, licensed to you under the terms
3 * of the Apache License, Version 2.0 (the "License"). See the NOTICE file
4 * distributed with this work for additional information regarding copyright
5 * ownership. You may not use this file except in compliance with the License.
6 *
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing,
12 * software distributed under the License is distributed on an
13 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 * KIND, either express or implied. See the License for the
15 * specific language governing permissions and limitations
16 * under the License.
17 */
18 /*
19 * Copyright (C) 2014 Cloudius Systems, Ltd.
20 */
21
22 #include <seastar/core/reactor.hh>
23 #include <seastar/net/packet.hh>
24 #include <iostream>
25 #include <algorithm>
26 #include <cctype>
27
28 namespace seastar {
29
30 namespace net {
31
32 constexpr size_t packet::internal_data_size;
33 constexpr size_t packet::default_nr_frags;
34
35 void packet::linearize(size_t at_frag, size_t desired_size) {
36 _impl->unuse_internal_data();
37 size_t nr_frags = 0;
38 size_t accum_size = 0;
39 while (accum_size < desired_size) {
40 accum_size += _impl->_frags[at_frag + nr_frags].size;
41 ++nr_frags;
42 }
43 std::unique_ptr<char[]> new_frag{new char[accum_size]};
44 auto p = new_frag.get();
45 for (size_t i = 0; i < nr_frags; ++i) {
46 auto& f = _impl->_frags[at_frag + i];
47 p = std::copy(f.base, f.base + f.size, p);
48 }
49 // collapse nr_frags into one fragment
50 std::copy(_impl->_frags + at_frag + nr_frags, _impl->_frags + _impl->_nr_frags,
51 _impl->_frags + at_frag + 1);
52 _impl->_nr_frags -= nr_frags - 1;
53 _impl->_frags[at_frag] = fragment{new_frag.get(), accum_size};
54 if (at_frag == 0 && desired_size == len()) {
55 // We can drop the old buffer safely
56 auto x = std::move(_impl->_deleter);
57 _impl->_deleter = make_deleter([buf = std::move(new_frag)] {});
58 } else {
59 _impl->_deleter = make_deleter(std::move(_impl->_deleter), [buf = std::move(new_frag)] {});
60 }
61 }
62
63
64 packet packet::free_on_cpu(unsigned cpu, std::function<void()> cb)
65 {
66 // make new deleter that runs old deleter on an origin cpu
67 _impl->_deleter = make_deleter(deleter(), [d = std::move(_impl->_deleter), cpu, cb = std::move(cb)] () mutable {
68 smp::submit_to(cpu, [d = std::move(d), cb = std::move(cb)] () mutable {
69 // deleter needs to be moved from lambda capture to be destroyed here
70 // otherwise deleter destructor will be called on a cpu that called smp::submit_to()
71 // when work_item is destroyed.
72 deleter xxx(std::move(d));
73 cb();
74 });
75 });
76
77 return packet(impl::copy(_impl.get()));
78 }
79
80 std::ostream& operator<<(std::ostream& os, const packet& p) {
81 os << "packet{";
82 bool first = true;
83 for (auto&& frag : p.fragments()) {
84 if (!first) {
85 os << ", ";
86 }
87 first = false;
88 if (std::all_of(frag.base, frag.base + frag.size, [] (int c) { return c >= 9 && c <= 0x7f; })) {
89 os << '"';
90 for (auto p = frag.base; p != frag.base + frag.size; ++p) {
91 auto c = *p;
92 if (isprint(c)) {
93 os << c;
94 } else if (c == '\r') {
95 os << "\\r";
96 } else if (c == '\n') {
97 os << "\\n";
98 } else if (c == '\t') {
99 os << "\\t";
100 } else {
101 uint8_t b = c;
102 os << "\\x" << (b / 16) << (b % 16);
103 }
104 }
105 os << '"';
106 } else {
107 os << "{";
108 bool nfirst = true;
109 for (auto p = frag.base; p != frag.base + frag.size; ++p) {
110 if (!nfirst) {
111 os << " ";
112 }
113 nfirst = false;
114 uint8_t b = *p;
115 os << format("{:02x}", unsigned(b));
116 }
117 os << "}";
118 }
119 }
120 os << "}";
121 return os;
122 }
123
124 }
125
126 }