diff options
Diffstat (limited to 'libtransport/src/utils')
20 files changed, 540 insertions, 1800 deletions
diff --git a/libtransport/src/utils/CMakeLists.txt b/libtransport/src/utils/CMakeLists.txt index 1a23459b5..e7c1c03ea 100644 --- a/libtransport/src/utils/CMakeLists.txt +++ b/libtransport/src/utils/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: @@ -11,20 +11,20 @@ # See the License for the specific language governing permissions and # limitations under the License. -cmake_minimum_required(VERSION 3.5 FATAL_ERROR) - list(APPEND SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/string_tokenizer.cc ${CMAKE_CURRENT_SOURCE_DIR}/uri.cc ${CMAKE_CURRENT_SOURCE_DIR}/log.cc ${CMAKE_CURRENT_SOURCE_DIR}/membuf.cc ${CMAKE_CURRENT_SOURCE_DIR}/content_store.cc + ${CMAKE_CURRENT_SOURCE_DIR}/traffic_generator.cc ) list(APPEND HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/event_reactor.h ${CMAKE_CURRENT_SOURCE_DIR}/min_filter.h + ${CMAKE_CURRENT_SOURCE_DIR}/max_filter.h ${CMAKE_CURRENT_SOURCE_DIR}/stream_buffer.h ${CMAKE_CURRENT_SOURCE_DIR}/suffix_strategy.h ${CMAKE_CURRENT_SOURCE_DIR}/content_store.h @@ -36,10 +36,6 @@ if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") ${CMAKE_CURRENT_SOURCE_DIR}/epoll_event_reactor.h ${CMAKE_CURRENT_SOURCE_DIR}/fd_deadline_timer.h ) - - list(APPEND SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/epoll_event_reactor.cc - ) endif() if(NOT WIN32) diff --git a/libtransport/src/utils/content_store.cc b/libtransport/src/utils/content_store.cc index cb3db6d94..d9d4147f7 100644 --- a/libtransport/src/utils/content_store.cc +++ b/libtransport/src/utils/content_store.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -13,11 +13,11 @@ * limitations under the License. */ +#include <glog/logging.h> #include <hicn/transport/core/content_object.h> #include <hicn/transport/core/interest.h> #include <hicn/transport/core/name.h> -#include <hicn/transport/utils/log.h> - +#include <hicn/transport/utils/chrono_typedefs.h> #include <utils/content_store.h> namespace utils { @@ -37,9 +37,9 @@ void ContentStore::insert( if (TRANSPORT_EXPECT_FALSE(content_store_hash_table_.size() != fifo_list_.size())) { - TRANSPORT_LOGW("Inconsistent size!!!!"); - TRANSPORT_LOGW("Hash Table: %zu |||| FIFO List: %zu", - content_store_hash_table_.size(), fifo_list_.size()); + LOG(WARNING) << "Inconsistent size!!!!"; + LOG(WARNING) << "Hash Table: " << content_store_hash_table_.size() + << " |||| FIFO List: " << fifo_list_.size(); } if (content_store_hash_table_.size() >= max_content_store_size_) { @@ -57,20 +57,19 @@ void ContentStore::insert( fifo_list_.push_front(std::cref(content_object->getName())); auto pos = fifo_list_.begin(); content_store_hash_table_[content_object->getName()] = ContentStoreEntry( - ObjectTimeEntry(content_object, std::chrono::steady_clock::now()), pos); + ObjectTimeEntry(content_object, utils::SteadyTime::now()), pos); } -const std::shared_ptr<ContentObject> ContentStore::find( - const Interest &interest) { +std::shared_ptr<ContentObject> ContentStore::find(const Name &name) { utils::SpinLock::Acquire locked(cs_mutex_); std::shared_ptr<ContentObject> ret = empty_reference_; - auto it = content_store_hash_table_.find(interest.getName()); + auto it = content_store_hash_table_.find(name); if (it != content_store_hash_table_.end()) { auto content_lifetime = it->second.first.first->getLifetime(); auto time_passed_since_creation = - std::chrono::duration_cast<std::chrono::milliseconds>( - std::chrono::steady_clock::now() - it->second.first.second) + utils::SteadyTime::getDurationMs(it->second.first.second, + utils::SteadyTime::now()) .count(); if (time_passed_since_creation > content_lifetime) { @@ -110,13 +109,11 @@ void ContentStore::printContent() { for (auto &item : content_store_hash_table_) { if (item.second.first.first->getPayloadType() == transport::core::PayloadType::MANIFEST) { - TRANSPORT_LOGI("Manifest: %s", - item.second.first.first->getName().toString().c_str()); + LOG(INFO) << "Manifest: " << item.second.first.first->getName(); } else { - TRANSPORT_LOGI("Data Packet: %s", - item.second.first.first->getName().toString().c_str()); + LOG(INFO) << "Data Packet: " << item.second.first.first->getName(); } } } -} // end namespace utils
\ No newline at end of file +} // end namespace utils diff --git a/libtransport/src/utils/content_store.h b/libtransport/src/utils/content_store.h index 03ce76f42..ecd62cc2c 100644 --- a/libtransport/src/utils/content_store.h +++ b/libtransport/src/utils/content_store.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -35,8 +35,7 @@ using Name = transport::core::Name; using ContentObject = transport::core::ContentObject; using Interest = transport::core::Interest; -typedef std::pair<std::shared_ptr<ContentObject>, - std::chrono::steady_clock::time_point> +typedef std::pair<std::shared_ptr<ContentObject>, utils::SteadyTime::TimePoint> ObjectTimeEntry; typedef std::pair<ObjectTimeEntry, std::list<std::reference_wrapper<const Name>>::iterator> @@ -52,7 +51,7 @@ class ContentStore { void insert(const std::shared_ptr<ContentObject> &content_object); - const std::shared_ptr<ContentObject> find(const Interest &interest); + std::shared_ptr<ContentObject> find(const Name &name); void erase(const Name &exact_name); @@ -73,4 +72,4 @@ class ContentStore { mutable utils::SpinLock cs_mutex_; }; -} // end namespace utils
\ No newline at end of file +} // end namespace utils diff --git a/libtransport/src/utils/daemonizator.cc b/libtransport/src/utils/daemonizator.cc index c51a68d14..4c17aa96b 100644 --- a/libtransport/src/utils/daemonizator.cc +++ b/libtransport/src/utils/daemonizator.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -14,10 +14,9 @@ */ #ifndef _WIN32 +#include <glog/logging.h> #include <hicn/transport/errors/runtime_exception.h> #include <hicn/transport/utils/daemonizator.h> -#include <hicn/transport/utils/log.h> - #include <sys/stat.h> #include <unistd.h> @@ -37,7 +36,7 @@ void Daemonizator::daemonize(bool close_fds) { // PARENT PROCESS. Need to kill it. if (process_id > 0) { - TRANSPORT_LOGE("Process id of child process %d", process_id); + LOG(ERROR) << "Process id of child process " << process_id; // return success in exit status exit(EXIT_SUCCESS); } diff --git a/libtransport/src/utils/deadline_timer.h b/libtransport/src/utils/deadline_timer.h index 5187754f0..6c105ed3d 100644 --- a/libtransport/src/utils/deadline_timer.h +++ b/libtransport/src/utils/deadline_timer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -22,61 +22,6 @@ #include <cstring> #include <utility> -namespace std { -namespace chrono { -namespace detail { - -template <typename From, typename To> -struct posix_duration_cast; - -// chrono -> timespec caster -template <typename Rep, typename Period> -struct posix_duration_cast<std::chrono::duration<Rep, Period>, - struct timespec> { - static struct timespec cast(std::chrono::duration<Rep, Period> const &d) { - struct timespec tv; - - std::chrono::seconds const sec = - std::chrono::duration_cast<std::chrono::seconds>(d); - - tv.tv_sec = sec.count(); - tv.tv_nsec = - std::chrono::duration_cast<std::chrono::nanoseconds>(d - sec).count(); - - return tv; - } -}; - -// timespec -> chrono caster -template <typename Rep, typename Period> -struct posix_duration_cast<struct timespec, - std::chrono::duration<Rep, Period>> { - static std::chrono::duration<Rep, Period> cast(struct timespec const &tv) { - return std::chrono::duration_cast<std::chrono::duration<Rep, Period>>( - std::chrono::seconds(tv.tv_sec) + std::chrono::nanoseconds(tv.tv_nsec)); - } -}; - -} // namespace detail - -// chrono -> timespec -template <typename T, typename Rep, typename Period> -auto duration_cast(std::chrono::duration<Rep, Period> const &d) -> - typename std::enable_if<std::is_same<T, struct timespec>::value, - struct timespec>::type { - return detail::posix_duration_cast<std::chrono::duration<Rep, Period>, - timespec>::cast(d); -} - -// timespec -> chrono -template <typename Duration> -Duration duration_cast(struct timespec const &tv) { - return detail::posix_duration_cast<struct timespec, Duration>::cast(tv); -} - -} // namespace chrono -} // namespace std - namespace utils { template <typename Implementation> diff --git a/libtransport/src/utils/epoll_event_reactor.cc b/libtransport/src/utils/epoll_event_reactor.cc deleted file mode 100644 index 63c08df95..000000000 --- a/libtransport/src/utils/epoll_event_reactor.cc +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <hicn/transport/utils/branch_prediction.h> - -#include <utils/epoll_event_reactor.h> -#include <utils/fd_deadline_timer.h> - -#include <signal.h> -#include <unistd.h> -#include <iostream> - -namespace utils { - -EpollEventReactor::EpollEventReactor() - : epoll_fd_(epoll_create(20000)), run_event_loop_(true) {} - -EpollEventReactor::~EpollEventReactor() { close(epoll_fd_); } - -int EpollEventReactor::addFileDescriptor(int fd, uint32_t events) { - if (TRANSPORT_EXPECT_FALSE(fd < 0)) { - TRANSPORT_LOGE("invalid fd %d", fd); - return -1; - } - - struct epoll_event evt; - std::memset(&evt, 0, sizeof(evt)); - evt.events = events; - evt.data.fd = fd; - - if (TRANSPORT_EXPECT_FALSE(epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, fd, &evt) < - 0)) { - TRANSPORT_LOGE("epoll_ctl: %s fd %d", strerror(errno), fd); - return -1; - } - - return 0; -} - -int EpollEventReactor::modFileDescriptor(int fd, uint32_t events) { - if (TRANSPORT_EXPECT_FALSE(fd < 0)) { - TRANSPORT_LOGE("invalid fd %d", fd); - return -1; - } - - struct epoll_event evt; - memset(&evt, 0, sizeof(evt)); - evt.events = events; - evt.data.fd = fd; - - if (TRANSPORT_EXPECT_FALSE(epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, fd, &evt) < - 0)) { - TRANSPORT_LOGE("epoll_ctl: %s fd %d", strerror(errno), fd); - return -1; - } - - return 0; -} - -std::size_t EpollEventReactor::mapSize() { return event_callback_map_.size(); } - -int EpollEventReactor::delFileDescriptor(int fd) { - if (TRANSPORT_EXPECT_FALSE(fd < 0)) { - TRANSPORT_LOGE("invalid fd %d", fd); - return -1; - } - - struct epoll_event evt; - memset(&evt, 0, sizeof(evt)); - - if (TRANSPORT_EXPECT_FALSE(epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, fd, &evt) < - 0)) { - TRANSPORT_LOGE("epoll_ctl: %s fd %d", strerror(errno), fd); - return -1; - } - - utils::SpinLock::Acquire locked(event_callback_map_lock_); - event_callback_map_.erase(fd); - - return 0; -} - -void EpollEventReactor::runEventLoop(int timeout) { - Event evt[128]; - int en = 0; - EventCallbackMap::iterator it; - EventCallback callback; - - // evt.events = EPOLLIN | EPOLLOUT; - sigset_t sigset; - sigemptyset(&sigset); - - while (run_event_loop_) { - memset(&evt, 0, sizeof(evt)); - en = epoll_pwait(epoll_fd_, evt, 128, timeout, &sigset); - - if (TRANSPORT_EXPECT_FALSE(en < 0)) { - TRANSPORT_LOGE("epoll_pwait: %s", strerror(errno)); - if (errno == EINTR) { - continue; - } else { - return; - } - } - - for (int i = 0; i < en; i++) { - if (evt[i].data.fd > 0) { - { - utils::SpinLock::Acquire locked(event_callback_map_lock_); - it = event_callback_map_.find(evt[i].data.fd); - } - - if (TRANSPORT_EXPECT_FALSE(it == event_callback_map_.end())) { - TRANSPORT_LOGE("unexpected event. fd %d", evt[i].data.fd); - } else { - { - utils::SpinLock::Acquire locked(event_callback_map_lock_); - callback = event_callback_map_[evt[i].data.fd]; - } - - callback(evt[i]); - - // In the callback the epoll event reactor could have been stopped, - // then we need to check whether the event loop is still running. - if (TRANSPORT_EXPECT_FALSE(!run_event_loop_)) { - return; - } - } - } else { - TRANSPORT_LOGE("unexpected event. fd %d", evt[i].data.fd); - } - } - } -} - -void EpollEventReactor::runOneEvent() { - Event evt; - int en = 0; - EventCallbackMap::iterator it; - EventCallback callback; - - // evt.events = EPOLLIN | EPOLLOUT; - sigset_t sigset; - sigemptyset(&sigset); - - memset(&evt, 0, sizeof(evt)); - - en = epoll_pwait(epoll_fd_, &evt, 1, -1, &sigset); - - if (TRANSPORT_EXPECT_FALSE(en < 0)) { - TRANSPORT_LOGE("epoll_pwait: %s", strerror(errno)); - return; - } - - if (TRANSPORT_EXPECT_TRUE(evt.data.fd > 0)) { - { - utils::SpinLock::Acquire locked(event_callback_map_lock_); - it = event_callback_map_.find(evt.data.fd); - } - - if (TRANSPORT_EXPECT_FALSE(it == event_callback_map_.end())) { - TRANSPORT_LOGE("unexpected event. fd %d", evt.data.fd); - } else { - { - utils::SpinLock::Acquire locked(event_callback_map_lock_); - callback = event_callback_map_[evt.data.fd]; - } - - callback(evt); - } - } else { - TRANSPORT_LOGE("unexpected event. fd %d", evt.data.fd); - } -} - -void EpollEventReactor::stop() { run_event_loop_ = false; } - -} // namespace utils
\ No newline at end of file diff --git a/libtransport/src/utils/epoll_event_reactor.h b/libtransport/src/utils/epoll_event_reactor.h index 4cb87ebd4..32d99c837 100644 --- a/libtransport/src/utils/epoll_event_reactor.h +++ b/libtransport/src/utils/epoll_event_reactor.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -15,10 +15,11 @@ #pragma once +#include <glog/logging.h> #include <hicn/transport/utils/spinlock.h> +#include <sys/epoll.h> #include <utils/event_reactor.h> -#include <sys/epoll.h> #include <atomic> #include <cstddef> #include <functional> @@ -35,9 +36,10 @@ typedef std::unordered_map<int, EventCallback> EventCallbackMap; class EpollEventReactor : public EventReactor { public: - explicit EpollEventReactor(); + explicit EpollEventReactor() + : epoll_fd_(epoll_create(20000)), run_event_loop_(true) {} - ~EpollEventReactor(); + ~EpollEventReactor() { close(epoll_fd_); } template <typename EventHandler> int addFileDescriptor(int fd, uint32_t events, EventHandler &&callback) { @@ -47,7 +49,7 @@ class EpollEventReactor : public EventReactor { if (it == event_callback_map_.end()) { { utils::SpinLock::Acquire locked(event_callback_map_lock_); - event_callback_map_[fd] = std::forward<EventHandler &&>(callback); + event_callback_map_[fd] = std::forward<EventHandler>(callback); } ret = addFileDescriptor(fd, events); @@ -56,20 +58,163 @@ class EpollEventReactor : public EventReactor { return ret; } - int delFileDescriptor(int fd); + int delFileDescriptor(int fd) { + if (TRANSPORT_EXPECT_FALSE(fd < 0)) { + LOG(ERROR) << "invalid fd " << fd; + return -1; + } + + struct epoll_event evt; + memset(&evt, 0, sizeof(evt)); + + if (TRANSPORT_EXPECT_FALSE(epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, fd, &evt) < + 0)) { + return -1; + } + + utils::SpinLock::Acquire locked(event_callback_map_lock_); + event_callback_map_.erase(fd); + + return 0; + } + + int modFileDescriptor(int fd, uint32_t events) { + if (TRANSPORT_EXPECT_FALSE(fd < 0)) { + LOG(ERROR) << "invalid fd " << fd; + return -1; + } + + struct epoll_event evt; + memset(&evt, 0, sizeof(evt)); + evt.events = events; + evt.data.fd = fd; + + if (TRANSPORT_EXPECT_FALSE(epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, fd, &evt) < + 0)) { + LOG(ERROR) << "epoll_ctl: " << strerror(errno) << " fd " << fd; + return -1; + } + + return 0; + } + + void runEventLoop(int timeout = -1) override { + Event evt[128]; + int en = 0; + EventCallbackMap::iterator it; + EventCallback callback; + + // evt.events = EPOLLIN | EPOLLOUT; + sigset_t sigset; + sigemptyset(&sigset); + + while (run_event_loop_) { + memset(&evt, 0, sizeof(evt)); + en = epoll_pwait(epoll_fd_, evt, 128, timeout, &sigset); + + if (TRANSPORT_EXPECT_FALSE(en < 0)) { + LOG(ERROR) << "epoll_pwait: " << strerror(errno); + if (errno == EINTR) { + continue; + } else { + return; + } + } + + for (int i = 0; i < en; i++) { + if (evt[i].data.fd > 0) { + { + utils::SpinLock::Acquire locked(event_callback_map_lock_); + it = event_callback_map_.find(evt[i].data.fd); + } + + if (TRANSPORT_EXPECT_FALSE(it == event_callback_map_.end())) { + LOG(ERROR) << "unexpected event. fd " << evt[i].data.fd; + } else { + { + utils::SpinLock::Acquire locked(event_callback_map_lock_); + callback = event_callback_map_[evt[i].data.fd]; + } + + callback(evt[i]); + + // In the callback the epoll event reactor could have been stopped, + // then we need to check whether the event loop is still running. + if (TRANSPORT_EXPECT_FALSE(!run_event_loop_)) { + return; + } + } + } else { + LOG(ERROR) << "unexpected event. fd " << evt[i].data.fd; + } + } + } + } + + void runOneEvent() override { + Event evt; + int en = 0; + EventCallbackMap::iterator it; + EventCallback callback; + + // evt.events = EPOLLIN | EPOLLOUT; + sigset_t sigset; + sigemptyset(&sigset); + + memset(&evt, 0, sizeof(evt)); - int modFileDescriptor(int fd, uint32_t events); + en = epoll_pwait(epoll_fd_, &evt, 1, -1, &sigset); + + if (TRANSPORT_EXPECT_FALSE(en < 0)) { + LOG(ERROR) << "epoll_pwait: " << strerror(errno); + return; + } + + if (TRANSPORT_EXPECT_TRUE(evt.data.fd > 0)) { + { + utils::SpinLock::Acquire locked(event_callback_map_lock_); + it = event_callback_map_.find(evt.data.fd); + } - void runEventLoop(int timeout = -1) override; + if (TRANSPORT_EXPECT_FALSE(it == event_callback_map_.end())) { + LOG(ERROR) << "unexpected event. fd " << evt.data.fd; + } else { + { + utils::SpinLock::Acquire locked(event_callback_map_lock_); + callback = event_callback_map_[evt.data.fd]; + } - void runOneEvent() override; + callback(evt); + } + } else { + LOG(ERROR) << "unexpected event. fd " << evt.data.fd; + } + } - void stop() override; + void stop() override { run_event_loop_ = false; } - std::size_t mapSize(); + std::size_t mapSize() { return event_callback_map_.size(); } private: - int addFileDescriptor(int fd, uint32_t events); + int addFileDescriptor(int fd, uint32_t events) { + if (TRANSPORT_EXPECT_FALSE(fd < 0)) { + LOG(ERROR) << "invalid fd " << fd; + return -1; + } + + struct epoll_event evt; + std::memset(&evt, 0, sizeof(evt)); + evt.events = events; + evt.data.fd = fd; + + if (TRANSPORT_EXPECT_FALSE(epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, fd, &evt) < + 0)) { + LOG(ERROR) << "epoll_ctl: " << strerror(errno) << " fd " << fd; + return -1; + } + + return 0; + } int epoll_fd_; std::atomic_bool run_event_loop_; diff --git a/libtransport/src/utils/event_reactor.h b/libtransport/src/utils/event_reactor.h index 4f8b58296..09af6f84c 100644 --- a/libtransport/src/utils/event_reactor.h +++ b/libtransport/src/utils/event_reactor.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: diff --git a/libtransport/src/utils/fd_deadline_timer.h b/libtransport/src/utils/fd_deadline_timer.h index 8bc3bbca3..7ecbba69b 100644 --- a/libtransport/src/utils/fd_deadline_timer.h +++ b/libtransport/src/utils/fd_deadline_timer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -16,17 +16,15 @@ #pragma once #include <hicn/transport/errors/runtime_exception.h> -#include <hicn/transport/utils/log.h> - +#include <hicn/transport/utils/chrono_typedefs.h> +#include <sys/timerfd.h> +#include <unistd.h> #include <utils/deadline_timer.h> #include <utils/epoll_event_reactor.h> #include <chrono> #include <cstddef> -#include <sys/timerfd.h> -#include <unistd.h> - namespace utils { class FdDeadlineTimer : public DeadlineTimer<FdDeadlineTimer> { @@ -40,6 +38,11 @@ class FdDeadlineTimer : public DeadlineTimer<FdDeadlineTimer> { } } + FdDeadlineTimer(const FdDeadlineTimer &other) + : reactor_(other.reactor_), + timer_fd_(other.timer_fd_), + flags_(other.flags_) {} + ~FdDeadlineTimer() { close(timer_fd_); } template <typename WaitHandler> @@ -54,13 +57,13 @@ class FdDeadlineTimer : public DeadlineTimer<FdDeadlineTimer> { reactor_.addFileDescriptor( timer_fd_, events, - [callback = std::forward<WaitHandler &&>(callback)]( - const Event &event) -> int { + [callback = + std::forward<WaitHandler>(callback)](const Event &event) -> int { uint64_t s = 0; std::error_code ec; if (read(event.data.fd, &s, sizeof(s)) == -1) { - TRANSPORT_LOGE("Read error!!"); + LOG(ERROR) << "Read error!!"; } if (!(event.events & EPOLLIN)) { @@ -89,8 +92,7 @@ class FdDeadlineTimer : public DeadlineTimer<FdDeadlineTimer> { template <typename T, typename R> void expiresFromNowImpl(std::chrono::duration<T, R> &&duration) { std::memset(&new_value_, 0, sizeof(new_value_)); - new_value_.it_value = std::chrono::duration_cast<struct timespec>( - std::forward<std::chrono::duration<T, R>>(duration)); + new_value_.it_value = std::chrono::duration_cast<struct timespec>(duration); } template <typename TimePoint, diff --git a/libtransport/src/utils/log.cc b/libtransport/src/utils/log.cc index 27dd3f541..44acf4595 100644 --- a/libtransport/src/utils/log.cc +++ b/libtransport/src/utils/log.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -13,1391 +13,79 @@ * limitations under the License. */ -/* - * The MIT License (MIT) - * - * Copyright (c) 2017 wonder-mice - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/* When defined, Android log (android/log.h) will be used by default instead of - * stderr (ignored on non-Android platforms). Date, time, pid and tid (context) - * will be provided by Android log. Android log features will be used to output - * log level and tag. - */ - -#if defined(__ANDROID__) -#define TRANSPORT_LOG_USE_ANDROID_LOG 1 -#define ANDROID_TAG "HicnTransport" -#else -#define TRANSPORT_LOG_USE_ANDROID_LOG 0 -#endif - -/* When defined, NSLog (uses Apple System Log) will be used instead of stderr - * (ignored on non-Apple platforms). Date, time, pid and tid (context) will be - * provided by NSLog. Curiously, doesn't use NSLog() directly, but piggybacks on - * non-public CFLog() function. Both use Apple System Log internally, but it's - * easier to call CFLog() from C than NSLog(). Current implementation doesn't - * support "%@" format specifier. - */ -#ifdef TRANSPORT_LOG_USE_NSLOG -#undef TRANSPORT_LOG_USE_NSLOG -#if defined(__APPLE__) && defined(__MACH__) -#define TRANSPORT_LOG_USE_NSLOG 1 -#else -#define TRANSPORT_LOG_USE_NSLOG 0 -#endif -#else -#define TRANSPORT_LOG_USE_NSLOG 0 -#endif -/* When defined, OutputDebugString() will be used instead of stderr (ignored on - * non-Windows platforms). Uses OutputDebugStringA() variant and feeds it with - * UTF-8 data. - */ -#ifdef TRANSPORT_LOG_USE_DEBUGSTRING -#undef TRANSPORT_LOG_USE_DEBUGSTRING -#if defined(_WIN32) || defined(_WIN64) -#define TRANSPORT_LOG_USE_DEBUGSTRING 1 -#else -#define TRANSPORT_LOG_USE_DEBUGSTRING 0 -#endif -#else -#define TRANSPORT_LOG_USE_DEBUGSTRING 0 -#endif -/* When defined, TRANSPORT_LOG library will not contain definition of tag prefix - * variable. In that case it must be defined elsewhere using - * TRANSPORT_LOG_DEFINE_TAG_PREFIX macro, for example: - * - * TRANSPORT_LOG_DEFINE_TAG_PREFIX = "ProcessName"; - * - * This allows to specify custom value for static initialization and avoid - * overhead of setting this value in runtime. - */ -#ifdef TRANSPORT_LOG_EXTERN_TAG_PREFIX -#undef TRANSPORT_LOG_EXTERN_TAG_PREFIX -#define TRANSPORT_LOG_EXTERN_TAG_PREFIX 1 -#else -#define TRANSPORT_LOG_EXTERN_TAG_PREFIX 0 -#endif -/* When defined, TRANSPORT_LOG library will not contain definition of global - * format variable. In that case it must be defined elsewhere using - * TRANSPORT_LOG_DEFINE_GLOBAL_FORMAT macro, for example: - * - * TRANSPORT_LOG_DEFINE_GLOBAL_FORMAT = {MEM_WIDTH}; - * - * This allows to specify custom value for static initialization and avoid - * overhead of setting this value in runtime. - */ -#ifdef TRANSPORT_LOG_EXTERN_GLOBAL_FORMAT -#undef TRANSPORT_LOG_EXTERN_GLOBAL_FORMAT -#define TRANSPORT_LOG_EXTERN_GLOBAL_FORMAT 1 -#else -#define TRANSPORT_LOG_EXTERN_GLOBAL_FORMAT 0 -#endif -/* When defined, transport_log library will not contain definition of global - * output variable. In that case it must be defined elsewhere using - * TRANSPORT_LOG_DEFINE_GLOBAL_OUTPUT macro, for example: - * - * TRANSPORT_LOG_DEFINE_GLOBAL_OUTPUT = {TRANSPORT_LOG_PUT_STD, - * custom_output_callback}; - * - * This allows to specify custom value for static initialization and avoid - * overhead of setting this value in runtime. - */ -#ifdef TRANSPORT_LOG_EXTERN_GLOBAL_OUTPUT -#undef TRANSPORT_LOG_EXTERN_GLOBAL_OUTPUT -#define TRANSPORT_LOG_EXTERN_GLOBAL_OUTPUT 1 -#else -#define TRANSPORT_LOG_EXTERN_GLOBAL_OUTPUT 0 -#endif -/* When defined, transport_log library will not contain definition of global - * output level variable. In that case it must be defined elsewhere using - * TRANSPORT_LOG_DEFINE_GLOBAL_OUTPUT_LEVEL macro, for example: - * - * TRANSPORT_LOG_DEFINE_GLOBAL_OUTPUT_LEVEL = TRANSPORT_LOG_WARN; - * - * This allows to specify custom value for static initialization and avoid - * overhead of setting this value in runtime. - */ -#ifdef TRANSPORT_LOG_EXTERN_GLOBAL_OUTPUT_LEVEL -#undef TRANSPORT_LOG_EXTERN_GLOBAL_OUTPUT_LEVEL -#define TRANSPORT_LOG_EXTERN_GLOBAL_OUTPUT_LEVEL 1 -#else -#define TRANSPORT_LOG_EXTERN_GLOBAL_OUTPUT_LEVEL 0 -#endif -/* When defined, implementation will prefer smaller code size over speed. - * Very rough estimate is that code will be up to 2x smaller and up to 2x - * slower. Disabled by default. - */ -#ifdef TRANSPORT_LOG_OPTIMIZE_SIZE -#undef TRANSPORT_LOG_OPTIMIZE_SIZE -#define TRANSPORT_LOG_OPTIMIZE_SIZE 1 -#else -#define TRANSPORT_LOG_OPTIMIZE_SIZE 0 -#endif -/* Size of the log line buffer. The buffer is allocated on stack. It limits - * maximum length of a log line. - */ -#ifndef TRANSPORT_LOG_BUF_SZ -#define TRANSPORT_LOG_BUF_SZ 512 -#endif -/* Default number of bytes in one line of memory output. For large values - * TRANSPORT_LOG_BUF_SZ also must be increased. - */ -#ifndef TRANSPORT_LOG_MEM_WIDTH -#define TRANSPORT_LOG_MEM_WIDTH 32 -#endif -/* String to put in the end of each log line (can be empty). Its value used by - * stderr output callback. Its size used as a default value for - * TRANSPORT_LOG_EOL_SZ. - */ -#ifndef TRANSPORT_LOG_EOL -#define TRANSPORT_LOG_EOL "\n" -#endif -/* Default delimiter that separates parts of log message. Can NOT contain '%' - * or '\0'. - * - * Log message format specifications can override (or ignore) this value. For - * more details see TRANSPORT_LOG_MESSAGE_CTX_FORMAT, - * TRANSPORT_LOG_MESSAGE_SRC_FORMAT and TRANSPORT_LOG_MESSAGE_TAG_FORMAT. - */ -#ifndef TRANSPORT_LOG_DEF_DELIMITER -#define TRANSPORT_LOG_DEF_DELIMITER " " -#endif -/* Specifies log message context format. Log message context includes date, - * time, process id, thread id and message's log level. Custom information can - * be added as well. Supported fields: YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, - * MILLISECOND, PID, TID, LEVEL, S(str), F_INIT(statements), - * F_UINT(width, value). - * - * Must be defined as a tuple, for example: - * - * #define TRANSPORT_LOG_MESSAGE_CTX_FORMAT (YEAR, S("."), MONTH, S("."), DAY, - * S(" > ")) - * - * In that case, resulting log message will be: - * - * 2016.12.22 > TAG function@filename.c:line Message text - * - * Note, that tag, source location and message text are not impacted by - * this setting. See TRANSPORT_LOG_MESSAGE_TAG_FORMAT and - * TRANSPORT_LOG_MESSAGE_SRC_FORMAT. - * - * If message context must be visually separated from the rest of the message, - * it must be reflected in context format (notice trailing S(" > ") in the - * example above). - * - * S(str) adds constant string str. String can NOT contain '%' or '\0'. - * - * F_INIT(statements) adds initialization statement(s) that will be evaluated - * once for each log message. All statements are evaluated in specified order. - * Several F_INIT() fields can be used in every log message format - * specification. Fields, like F_UINT(width, value), are allowed to use results - * of initialization statements. If statement introduces variables (or other - * names, like structures) they must be prefixed with "f_". Statements must be - * enclosed into additional "()". Example: - * - * #define TRANSPORT_LOG_MESSAGE_CTX_FORMAT \ - * (F_INIT(( struct rusage f_ru; getrusage(RUSAGE_SELF, &f_ru); )), \ - * YEAR, S("."), MONTH, S("."), DAY, S(" "), \ - * F_UINT(5, f_ru.ru_nsignals), \ - * S(" ")) - * - * F_UINT(width, value) adds unsigned integer value extended with up to width - * spaces (for alignment purposes). Value can be any expression that evaluates - * to unsigned integer. If expression contains non-standard functions, they - * must be declared with F_INIT(). Example: - * - * #define TRANSPORT_LOG_MESSAGE_CTX_FORMAT \ - * (YEAR, S("."), MONTH, S("."), DAY, S(" "), \ - * F_INIT(( unsigned tickcount(); )), \ - * F_UINT(5, tickcount()), \ - * S(" ")) - * - * Other log message format specifications follow same rules, but have a - * different set of supported fields. - */ -#ifndef TRANSPORT_LOG_MESSAGE_CTX_FORMAT -#define TRANSPORT_LOG_MESSAGE_CTX_FORMAT \ - (MONTH, S("-"), DAY, S(TRANSPORT_LOG_DEF_DELIMITER), HOUR, S(":"), MINUTE, \ - S(":"), SECOND, S("."), MILLISECOND, S(TRANSPORT_LOG_DEF_DELIMITER), PID, \ - S(TRANSPORT_LOG_DEF_DELIMITER), TID, S(TRANSPORT_LOG_DEF_DELIMITER), LEVEL, \ - S(TRANSPORT_LOG_DEF_DELIMITER)) -#endif -/* Example: - */ -/* Specifies log message tag format. It includes tag prefix and tag. Custom - * information can be added as well. Supported fields: - * TAG(prefix_delimiter, tag_delimiter), S(str), F_INIT(statements), - * F_UINT(width, value). - * - * TAG(prefix_delimiter, tag_delimiter) adds following string to log message: - * - * PREFIX<prefix_delimiter>TAG<tag_delimiter> - * - * Prefix delimiter will be used only when prefix is not empty. Tag delimiter - * will be used only when prefixed tag is not empty. Example: - * - * #define TRANSPORT_LOG_TAG_FORMAT (S("["), TAG(".", ""), S("] ")) - * - * See TRANSPORT_LOG_MESSAGE_CTX_FORMAT for details. - */ -#ifndef TRANSPORT_LOG_MESSAGE_TAG_FORMAT -#define TRANSPORT_LOG_MESSAGE_TAG_FORMAT (TAG(".", TRANSPORT_LOG_DEF_DELIMITER)) -#endif -/* Specifies log message source location format. It includes function name, - * file name and file line. Custom information can be added as well. Supported - * fields: FUNCTION, FILENAME, FILELINE, S(str), F_INIT(statements), - * F_UINT(width, value). - * - * See TRANSPORT_LOG_MESSAGE_CTX_FORMAT for details. - */ -#ifndef TRANSPORT_LOG_MESSAGE_SRC_FORMAT -#define TRANSPORT_LOG_MESSAGE_SRC_FORMAT \ - (FUNCTION, S("@"), FILENAME, S(":"), FILELINE, S(TRANSPORT_LOG_DEF_DELIMITER)) -#endif -/* Fields that can be used in log message format specifications (see above). - * Mentioning them here explicitly, so we know that nobody else defined them - * before us. See TRANSPORT_LOG_MESSAGE_CTX_FORMAT for details. - */ -#define YEAR YEAR -#define MONTH MONTH -#define DAY DAY -#define MINUTE MINUTE -#define SECOND SECOND -#define MILLISECOND MILLISECOND -#define PID PID -#define TID TID -#define LEVEL LEVEL -#define TAG(prefix_delim, tag_delim) TAG(prefix_delim, tag_delim) -#define FUNCTION FUNCTION -#define FILENAME FILENAME -#define FILELINE FILELINE -#define S(str) S(str) -#define F_INIT(statements) F_INIT(statements) -#define F_UINT(width, value) F_UINT(width, value) -/* Number of bytes to reserve for EOL in the log line buffer (must be >0). - * Must be larger than or equal to length of TRANSPORT_LOG_EOL with terminating - * null. - */ -#ifndef TRANSPORT_LOG_EOL_SZ -#define TRANSPORT_LOG_EOL_SZ sizeof(TRANSPORT_LOG_EOL) -#endif -/* Compile instrumented version of the library to facilitate unit testing. - */ -#ifndef TRANSPORT_LOG_INSTRUMENTED -#define TRANSPORT_LOG_INSTRUMENTED 0 -#endif +#define GLOG_CUSTOM_PREFIX_SUPPORT 1 +#include <glog/logging.h> +#undef GLOG_CUSTOM_PREFIX_SUPPORT -#if defined(__linux__) -#if !defined(__ANDROID__) && !defined(_GNU_SOURCE) -#define _GNU_SOURCE -#endif -#endif -#if defined(__MINGW32__) -#ifdef __STRICT_ANSI__ -#undef __STRICT_ANSI__ -#endif -#endif - -#include <assert.h> -#include <ctype.h> +#include <core/global_configuration.h> +#include <hicn/transport/config.h> #include <hicn/transport/utils/log.h> -#include <stdarg.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> - -#if defined(_WIN32) || defined(_WIN64) -#include <windows.h> -#else -#include <sys/time.h> -#include <unistd.h> -#if defined(__linux__) -#include <linux/limits.h> -#else -#include <sys/syslimits.h> -#endif -#endif - -#if defined(__linux__) -#include <sys/prctl.h> -#include <sys/types.h> -#if !defined(__ANDROID__) -#include <sys/syscall.h> -#endif -#endif -#if defined(__MACH__) -#include <pthread.h> -#endif - -#define INLINE _TRANSPORT_LOG_INLINE -#define VAR_UNUSED(var) (void)var -#define RETVAL_UNUSED(expr) \ - do { \ - while (expr) break; \ - } while (0) -#define STATIC_ASSERT(name, cond) typedef char assert_##name[(cond) ? 1 : -1] -#define ASSERT_UNREACHABLE(why) assert(!sizeof(why)) -#ifndef _countof -#define _countof(xs) (sizeof(xs) / sizeof((xs)[0])) -#endif - -#if TRANSPORT_LOG_INSTRUMENTED -#define INSTRUMENTED_CONST -#else -#define INSTRUMENTED_CONST const -#endif - -#define _PP_PASTE_2(a, b) a##b -#define _PP_CONCAT_2(a, b) _PP_PASTE_2(a, b) - -#define _PP_PASTE_3(a, b, c) a##b##c -#define _PP_CONCAT_3(a, b, c) _PP_PASTE_3(a, b, c) - -/* Microsoft C preprocessor is a piece of shit. This moron treats __VA_ARGS__ - * as a single token and requires additional expansion to realize that it's - * actually a list. If not for it, there would be no need in this extra - * expansion. - */ -#define _PP_ID(x) x -#define _PP_NARGS_N(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, \ - _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, \ - _24, ...) \ - _24 -#define _PP_NARGS(...) \ - _PP_ID(_PP_NARGS_N(__VA_ARGS__, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, \ - 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)) - -/* There is a more efficient way to implement this, but it requires - * working C preprocessor. Unfortunately, Microsoft Visual Studio doesn't - * have one. - */ -#define _PP_HEAD__(x, ...) x -#define _PP_HEAD_(...) _PP_ID(_PP_HEAD__(__VA_ARGS__, ~)) -#define _PP_HEAD(xs) _PP_HEAD_ xs -#define _PP_TAIL_(x, ...) (__VA_ARGS__) -#define _PP_TAIL(xs) _PP_TAIL_ xs -#define _PP_UNTUPLE_(...) __VA_ARGS__ -#define _PP_UNTUPLE(xs) _PP_UNTUPLE_ xs - -/* Apply function macro to each element in tuple. Output is not - * enforced to be a tuple. - */ -#define _PP_MAP_1(f, xs) f(_PP_HEAD(xs)) -#define _PP_MAP_2(f, xs) f(_PP_HEAD(xs)) _PP_MAP_1(f, _PP_TAIL(xs)) -#define _PP_MAP_3(f, xs) f(_PP_HEAD(xs)) _PP_MAP_2(f, _PP_TAIL(xs)) -#define _PP_MAP_4(f, xs) f(_PP_HEAD(xs)) _PP_MAP_3(f, _PP_TAIL(xs)) -#define _PP_MAP_5(f, xs) f(_PP_HEAD(xs)) _PP_MAP_4(f, _PP_TAIL(xs)) -#define _PP_MAP_6(f, xs) f(_PP_HEAD(xs)) _PP_MAP_5(f, _PP_TAIL(xs)) -#define _PP_MAP_7(f, xs) f(_PP_HEAD(xs)) _PP_MAP_6(f, _PP_TAIL(xs)) -#define _PP_MAP_8(f, xs) f(_PP_HEAD(xs)) _PP_MAP_7(f, _PP_TAIL(xs)) -#define _PP_MAP_9(f, xs) f(_PP_HEAD(xs)) _PP_MAP_8(f, _PP_TAIL(xs)) -#define _PP_MAP_10(f, xs) f(_PP_HEAD(xs)) _PP_MAP_9(f, _PP_TAIL(xs)) -#define _PP_MAP_11(f, xs) f(_PP_HEAD(xs)) _PP_MAP_10(f, _PP_TAIL(xs)) -#define _PP_MAP_12(f, xs) f(_PP_HEAD(xs)) _PP_MAP_11(f, _PP_TAIL(xs)) -#define _PP_MAP_13(f, xs) f(_PP_HEAD(xs)) _PP_MAP_12(f, _PP_TAIL(xs)) -#define _PP_MAP_14(f, xs) f(_PP_HEAD(xs)) _PP_MAP_13(f, _PP_TAIL(xs)) -#define _PP_MAP_15(f, xs) f(_PP_HEAD(xs)) _PP_MAP_14(f, _PP_TAIL(xs)) -#define _PP_MAP_16(f, xs) f(_PP_HEAD(xs)) _PP_MAP_15(f, _PP_TAIL(xs)) -#define _PP_MAP_17(f, xs) f(_PP_HEAD(xs)) _PP_MAP_16(f, _PP_TAIL(xs)) -#define _PP_MAP_18(f, xs) f(_PP_HEAD(xs)) _PP_MAP_17(f, _PP_TAIL(xs)) -#define _PP_MAP_19(f, xs) f(_PP_HEAD(xs)) _PP_MAP_18(f, _PP_TAIL(xs)) -#define _PP_MAP_20(f, xs) f(_PP_HEAD(xs)) _PP_MAP_19(f, _PP_TAIL(xs)) -#define _PP_MAP_21(f, xs) f(_PP_HEAD(xs)) _PP_MAP_20(f, _PP_TAIL(xs)) -#define _PP_MAP_22(f, xs) f(_PP_HEAD(xs)) _PP_MAP_21(f, _PP_TAIL(xs)) -#define _PP_MAP_23(f, xs) f(_PP_HEAD(xs)) _PP_MAP_22(f, _PP_TAIL(xs)) -#define _PP_MAP_24(f, xs) f(_PP_HEAD(xs)) _PP_MAP_23(f, _PP_TAIL(xs)) -#define _PP_MAP(f, xs) _PP_CONCAT_2(_PP_MAP_, _PP_NARGS xs)(f, xs) - -/* Apply function macro to each element in tuple in reverse order. - * Output is not enforced to be a tuple. - */ -#define _PP_RMAP_1(f, xs) f(_PP_HEAD(xs)) -#define _PP_RMAP_2(f, xs) _PP_RMAP_1(f, _PP_TAIL(xs)) f(_PP_HEAD(xs)) -#define _PP_RMAP_3(f, xs) _PP_RMAP_2(f, _PP_TAIL(xs)) f(_PP_HEAD(xs)) -#define _PP_RMAP_4(f, xs) _PP_RMAP_3(f, _PP_TAIL(xs)) f(_PP_HEAD(xs)) -#define _PP_RMAP_5(f, xs) _PP_RMAP_4(f, _PP_TAIL(xs)) f(_PP_HEAD(xs)) -#define _PP_RMAP_6(f, xs) _PP_RMAP_5(f, _PP_TAIL(xs)) f(_PP_HEAD(xs)) -#define _PP_RMAP_7(f, xs) _PP_RMAP_6(f, _PP_TAIL(xs)) f(_PP_HEAD(xs)) -#define _PP_RMAP_8(f, xs) _PP_RMAP_7(f, _PP_TAIL(xs)) f(_PP_HEAD(xs)) -#define _PP_RMAP_9(f, xs) _PP_RMAP_8(f, _PP_TAIL(xs)) f(_PP_HEAD(xs)) -#define _PP_RMAP_10(f, xs) _PP_RMAP_9(f, _PP_TAIL(xs)) f(_PP_HEAD(xs)) -#define _PP_RMAP_11(f, xs) _PP_RMAP_10(f, _PP_TAIL(xs)) f(_PP_HEAD(xs)) -#define _PP_RMAP_12(f, xs) _PP_RMAP_11(f, _PP_TAIL(xs)) f(_PP_HEAD(xs)) -#define _PP_RMAP_13(f, xs) _PP_RMAP_12(f, _PP_TAIL(xs)) f(_PP_HEAD(xs)) -#define _PP_RMAP_14(f, xs) _PP_RMAP_13(f, _PP_TAIL(xs)) f(_PP_HEAD(xs)) -#define _PP_RMAP_15(f, xs) _PP_RMAP_14(f, _PP_TAIL(xs)) f(_PP_HEAD(xs)) -#define _PP_RMAP_16(f, xs) _PP_RMAP_15(f, _PP_TAIL(xs)) f(_PP_HEAD(xs)) -#define _PP_RMAP_17(f, xs) _PP_RMAP_16(f, _PP_TAIL(xs)) f(_PP_HEAD(xs)) -#define _PP_RMAP_18(f, xs) _PP_RMAP_17(f, _PP_TAIL(xs)) f(_PP_HEAD(xs)) -#define _PP_RMAP_19(f, xs) _PP_RMAP_18(f, _PP_TAIL(xs)) f(_PP_HEAD(xs)) -#define _PP_RMAP_20(f, xs) _PP_RMAP_19(f, _PP_TAIL(xs)) f(_PP_HEAD(xs)) -#define _PP_RMAP_21(f, xs) _PP_RMAP_20(f, _PP_TAIL(xs)) f(_PP_HEAD(xs)) -#define _PP_RMAP_22(f, xs) _PP_RMAP_21(f, _PP_TAIL(xs)) f(_PP_HEAD(xs)) -#define _PP_RMAP_23(f, xs) _PP_RMAP_22(f, _PP_TAIL(xs)) f(_PP_HEAD(xs)) -#define _PP_RMAP_24(f, xs) _PP_RMAP_23(f, _PP_TAIL(xs)) f(_PP_HEAD(xs)) -#define _PP_RMAP(f, xs) _PP_CONCAT_2(_PP_RMAP_, _PP_NARGS xs)(f, xs) - -/* Used to implement _TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS() macro. All - * possible fields must be mentioned here. Not counting F_INIT() here because - * it's somewhat special and is handled spearatly (at least for now). - */ -#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__ (0 << 0) -#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__YEAR (1 << 1) -#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__MONTH (1 << 2) -#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__DAY (1 << 3) -#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__HOUR (1 << 4) -#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__MINUTE (1 << 5) -#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__SECOND (1 << 6) -#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__MILLISECOND (1 << 7) -#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__PID (1 << 8) -#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__TID (1 << 9) -#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__LEVEL (1 << 10) -#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__TAG(ps, ts) (1 << 11) -#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__FUNCTION (1 << 12) -#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__FILENAME (1 << 13) -#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__FILELINE (1 << 14) -#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__S(s) (1 << 15) -#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__F_INIT(expr) (0 << 16) -#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__F_UINT(w, v) (1 << 17) -#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK(field) \ - _PP_CONCAT_3(_TRANSPORT_LOG_MESSAGE_FORMAT_MASK_, _, field) - -/* Logical "or" of masks of fields used in specified format specification. - */ -#define _TRANSPORT_LOG_MESSAGE_FORMAT_FIELDS(format) \ - (0 _PP_MAP(| _TRANSPORT_LOG_MESSAGE_FORMAT_MASK, format)) - -/* Expands to expressions that evaluates to true if field is used in - * specified format specification. Example: - * - * #if _TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(F_UINT, - * TRANSPORT_LOG_MESSAGE_CTX_FORMAT) - * ... - * #endif - */ -#define _TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(field, format) \ - (_TRANSPORT_LOG_MESSAGE_FORMAT_MASK(field) & \ - _TRANSPORT_LOG_MESSAGE_FORMAT_FIELDS(format)) - -/* Same, but checks all supported format specifications. - */ -#define _TRANSPORT_LOG_MESSAGE_FORMAT_FIELD_USED(field) \ - (_TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(field, \ - TRANSPORT_LOG_MESSAGE_CTX_FORMAT) || \ - _TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(field, \ - TRANSPORT_LOG_MESSAGE_TAG_FORMAT) || \ - _TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(field, \ - TRANSPORT_LOG_MESSAGE_SRC_FORMAT)) - -#define _TRANSPORT_LOG_MESSAGE_FORMAT_DATETIME_USED \ - (_TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(YEAR, \ - TRANSPORT_LOG_MESSAGE_CTX_FORMAT) || \ - _TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(MONTH, \ - TRANSPORT_LOG_MESSAGE_CTX_FORMAT) || \ - _TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(DAY, \ - TRANSPORT_LOG_MESSAGE_CTX_FORMAT) || \ - _TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(HOUR, \ - TRANSPORT_LOG_MESSAGE_CTX_FORMAT) || \ - _TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(MINUTE, \ - TRANSPORT_LOG_MESSAGE_CTX_FORMAT) || \ - _TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(SECOND, \ - TRANSPORT_LOG_MESSAGE_CTX_FORMAT) || \ - _TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(MILLISECOND, \ - TRANSPORT_LOG_MESSAGE_CTX_FORMAT)) - -#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) -#pragma warning(disable : 4204) /* nonstandard extension used: non-constant \ - aggregate initializer */ -#define memccpy _memccpy -#endif - -#if (defined(_MSC_VER) && !defined(__INTEL_COMPILER)) || defined(__MINGW64__) -#define vsnprintf(s, sz, fmt, va) fake_vsnprintf(s, sz, fmt, va) -static int fake_vsnprintf(char *s, size_t sz, const char *fmt, va_list ap) { - const int n = vsnprintf_s(s, sz, _TRUNCATE, fmt, ap); - return 0 < n ? n : (int)sz + 1; /* no need in _vscprintf() for now */ -} -#if TRANSPORT_LOG_OPTIMIZE_SIZE -#define snprintf(s, sz, ...) fake_snprintf(s, sz, __VA_ARGS__) -static int fake_snprintf(char *s, size_t sz, const char *fmt, ...) { - va_list va; - va_start(va, fmt); - const int n = fake_vsnprintf(s, sz, fmt, va); - va_end(va); - return n; -} -#endif -#endif - -typedef void (*time_cb)(struct tm *const tm, unsigned *const usec); -typedef void (*pid_cb)(int *const pid, int *const tid); -typedef void (*buffer_cb)(transport_log_message *msg, char *buf); - -typedef struct src_location { - const char *const func; - const char *const file; - const unsigned line; -} src_location; - -typedef struct mem_block { - const void *const d; - const unsigned d_sz; -} mem_block; - -static void time_callback(struct tm *const tm, unsigned *const usec); -static void pid_callback(int *const pid, int *const tid); -static void buffer_callback(transport_log_message *msg, char *buf); - -STATIC_ASSERT(eol_fits_eol_sz, - sizeof(TRANSPORT_LOG_EOL) <= TRANSPORT_LOG_EOL_SZ); -STATIC_ASSERT(eol_sz_greater_than_zero, 0 < TRANSPORT_LOG_EOL_SZ); -STATIC_ASSERT(eol_sz_less_than_buf_sz, - TRANSPORT_LOG_EOL_SZ < TRANSPORT_LOG_BUF_SZ); -#if !defined(_WIN32) && !defined(_WIN64) -STATIC_ASSERT(buf_sz_less_than_pipe_buf, TRANSPORT_LOG_BUF_SZ <= PIPE_BUF); -#endif -static const char c_hex[] = "0123456789abcdef"; - -static INSTRUMENTED_CONST unsigned g_buf_sz = - TRANSPORT_LOG_BUF_SZ - TRANSPORT_LOG_EOL_SZ; -static INSTRUMENTED_CONST time_cb g_time_cb = time_callback; -static INSTRUMENTED_CONST pid_cb g_pid_cb = pid_callback; -static INSTRUMENTED_CONST buffer_cb g_buffer_cb = buffer_callback; -#if TRANSPORT_LOG_USE_ANDROID_LOG -#include <android/log.h> - -static INLINE int android_lvl(const int lvl) { - switch (lvl) { - case TRANSPORT_LOG_VERBOSE: - return ANDROID_LOG_VERBOSE; - case TRANSPORT_LOG_DEBUG: - return ANDROID_LOG_DEBUG; - case TRANSPORT_LOG_INFO: - return ANDROID_LOG_INFO; - case TRANSPORT_LOG_WARN: - return ANDROID_LOG_WARN; - case TRANSPORT_LOG_ERROR: - return ANDROID_LOG_ERROR; - case TRANSPORT_LOG_FATAL: - return ANDROID_LOG_FATAL; - default: - ASSERT_UNREACHABLE("Bad log level"); - return ANDROID_LOG_UNKNOWN; - } -} - -static void out_android_callback(const transport_log_message *const msg, - void *arg) { - VAR_UNUSED(arg); - *msg->p = 0; - const char *tag = msg->p; - if (msg->tag_e != msg->tag_b) { - tag = msg->tag_b; - *msg->tag_e = 0; +#include <iomanip> +#include <iostream> +#include <libconfig.h++> + +namespace utils { + +#define _(class_name, macro_name) \ + std::ostream &CLASS_NAME(class_name)::getStream() { return macro_name; } +foreach_log_level +#undef _ + + class LogConfiguration { + static constexpr char log_config_section[] = "log"; +#define LOG_NAME \ + "Libhicntransport-" HICNTRANSPORT_VERSION_MAJOR \ + "." HICNTRANSPORT_VERSION_MINOR "." HICNTRANSPORT_VERSION_PATCH + static constexpr char log_name[] = LOG_NAME; + +#define foreach_log_config \ + _(bool, logtostderr, true) \ + _(bool, alsologtostderr, false) \ + _(bool, colorlogtostderr, true) \ + _(int32_t, stderrthreshold, 2) \ + _(int32_t, minloglevel, 0) \ + _(bool, log_prefix, true) \ + _(std::string, log_dir, "") \ + _(int32_t, v, 1) \ + _(std::string, vmodule, "") \ + _(int32_t, max_log_size, 5) \ + _(bool, stop_logging_if_full_disk, true) + + public: + LogConfiguration() { + auto &conf = transport::core::GlobalConfiguration::getInstance(); + + using namespace std::placeholders; + conf.registerConfigurationParser( + log_config_section, + std::bind(&LogConfiguration::parseLogConfiguration, this, _1, _2)); + } + + private: + void parseLogConfiguration(const libconfig::Setting &log_config, + std::error_code &ec) { +#define _(type, name, default) \ + type _##name = default; \ + \ + if (log_config.exists(#name)) { \ + log_config.lookupValue(#name, _##name); \ + VLOG(2) << "Setting log config " << #name << " to " << _##name; \ + \ + FLAGS_##name = _##name; \ + } else { \ + VLOG(2) << "Log config " << #name << " do not exists"; \ + } + foreach_log_config +#undef _ + + google::InitGoogleLogging(log_name); } - __android_log_print(android_lvl(msg->lvl), ANDROID_TAG, "%s", msg->msg_b); -} - -enum { OUT_ANDROID_MASK = TRANSPORT_LOG_PUT_STD & ~TRANSPORT_LOG_PUT_CTX }; -#define OUT_ANDROID OUT_ANDROID_MASK, 0, out_android_callback -#endif - -#if TRANSPORT_LOG_USE_NSLOG -#include <CoreFoundation/CoreFoundation.h> -CF_EXPORT void CFLog(int32_t level, CFStringRef format, ...); - -static INLINE int apple_lvl(const int lvl) { - switch (lvl) { - case TRANSPORT_LOG_VERBOSE: - return 7; /* ASL_LEVEL_DEBUG / kCFLogLevelDebug */ - ; - case TRANSPORT_LOG_DEBUG: - return 7; /* ASL_LEVEL_DEBUG / kCFLogLevelDebug */ - ; - case TRANSPORT_LOG_INFO: - return 6; /* ASL_LEVEL_INFO / kCFLogLevelInfo */ - ; - case TRANSPORT_LOG_WARN: - return 4; /* ASL_LEVEL_WARNING / kCFLogLevelWarning */ - ; - case TRANSPORT_LOG_ERROR: - return 3; /* ASL_LEVEL_ERR / kCFLogLevelError */ - ; - case TRANSPORT_LOG_FATAL: - return 0; /* ASL_LEVEL_EMERG / kCFLogLevelEmergency */ - ; - default: - ASSERT_UNREACHABLE("Bad log level"); - return 0; /* ASL_LEVEL_EMERG / kCFLogLevelEmergency */ - ; - } -} - -static void out_nslog_callback(const transport_log_message *const msg, - void *arg) { - VAR_UNUSED(arg); - *msg->p = 0; - CFLog(apple_lvl(msg->lvl), CFSTR("%s"), msg->tag_b); -} - -enum { OUT_NSLOG_MASK = TRANSPORT_LOG_PUT_STD & ~TRANSPORT_LOG_PUT_CTX }; -#define OUT_NSLOG OUT_NSLOG_MASK, 0, out_nslog_callback -#endif - -#if TRANSPORT_LOG_USE_DEBUGSTRING -#include <windows.h> - -static void out_debugstring_callback(const transport_log_message *const msg, - void *arg) { - VAR_UNUSED(arg); - msg->p[0] = '\n'; - msg->p[1] = '\0'; - OutputDebugStringA(msg->buf); -} - -enum { OUT_DEBUGSTRING_MASK = TRANSPORT_LOG_PUT_STD }; -#define OUT_DEBUGSTRING OUT_DEBUGSTRING_MASK, 0, out_debugstring_callback -#endif - -void transport_log_out_stderr_callback(const transport_log_message *const msg, - void *arg) { - VAR_UNUSED(arg); - const size_t eol_len = sizeof(TRANSPORT_LOG_EOL) - 1; - memcpy(msg->p, TRANSPORT_LOG_EOL, eol_len); -#if defined(_WIN32) || defined(_WIN64) - /* WriteFile() is atomic for local files opened with FILE_APPEND_DATA and - without FILE_WRITE_DATA */ - DWORD written; - WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg->buf, - (DWORD)(msg->p - msg->buf + eol_len), &written, 0); -#else - /* write() is atomic for buffers less than or equal to PIPE_BUF. */ - RETVAL_UNUSED( - write(STDERR_FILENO, msg->buf, (size_t)(msg->p - msg->buf) + eol_len)); -#endif -} - -static const transport_log_output out_stderr = {TRANSPORT_LOG_OUT_STDERR}; - -#if !TRANSPORT_LOG_EXTERN_TAG_PREFIX -TRANSPORT_LOG_DEFINE_TAG_PREFIX = 0; -#endif - -#if !TRANSPORT_LOG_EXTERN_GLOBAL_FORMAT -TRANSPORT_LOG_DEFINE_GLOBAL_FORMAT = {TRANSPORT_LOG_MEM_WIDTH}; -#endif - -#if !TRANSPORT_LOG_EXTERN_GLOBAL_OUTPUT -#if TRANSPORT_LOG_USE_ANDROID_LOG -TRANSPORT_LOG_DEFINE_GLOBAL_OUTPUT = {OUT_ANDROID}; -#elif TRANSPORT_LOG_USE_NSLOG -TRANSPORT_LOG_DEFINE_GLOBAL_OUTPUT = {OUT_NSLOG}; -#elif TRANSPORT_LOG_USE_DEBUGSTRING -TRANSPORT_LOG_DEFINE_GLOBAL_OUTPUT = {OUT_DEBUGSTRING}; -#else -TRANSPORT_LOG_DEFINE_GLOBAL_OUTPUT = {TRANSPORT_LOG_OUT_STDERR}; -#endif -#endif - -#if !TRANSPORT_LOG_EXTERN_GLOBAL_OUTPUT_LEVEL -TRANSPORT_LOG_DEFINE_GLOBAL_OUTPUT_LEVEL = 0; -#endif - -const transport_log_spec _transport_log_stderr_spec = { - TRANSPORT_LOG_GLOBAL_FORMAT, - &out_stderr, }; -static const transport_log_spec global_spec = { - TRANSPORT_LOG_GLOBAL_FORMAT, - TRANSPORT_LOG_GLOBAL_OUTPUT, -}; - -#if _TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(LEVEL, \ - TRANSPORT_LOG_MESSAGE_CTX_FORMAT) -static char lvl_char(const int lvl) { - switch (lvl) { - case TRANSPORT_LOG_VERBOSE: - return 'V'; - case TRANSPORT_LOG_DEBUG: - return 'D'; - case TRANSPORT_LOG_INFO: - return 'I'; - case TRANSPORT_LOG_WARN: - return 'W'; - case TRANSPORT_LOG_ERROR: - return 'E'; - case TRANSPORT_LOG_FATAL: - return 'F'; - default: - ASSERT_UNREACHABLE("Bad log level"); - return '?'; - } -} -#endif - -#define GCCVER_LESS(MAJOR, MINOR, PATCH) \ - (__GNUC__ < MAJOR || (__GNUC__ == MAJOR && (__GNUC_MINOR__ < MINOR || \ - (__GNUC_MINOR__ == MINOR && \ - __GNUC_PATCHLEVEL__ < PATCH)))) - -#if !defined(__clang__) && defined(__GNUC__) && GCCVER_LESS(4, 7, 0) -#define __atomic_load_n(vp, model) __sync_fetch_and_add(vp, 0) -#define __atomic_fetch_add(vp, n, model) __sync_fetch_and_add(vp, n) -#define __atomic_sub_fetch(vp, n, model) __sync_sub_and_fetch(vp, n) -#define __atomic_or_fetch(vp, n, model) __sync_or_and_fetch(vp, n) -#define __atomic_and_fetch(vp, n, model) __sync_and_and_fetch(vp, n) -/* Note: will not store old value of *vp in *ep (non-standard behaviour) */ -#define __atomic_compare_exchange_n(vp, ep, d, weak, smodel, fmodel) \ - __sync_bool_compare_and_swap(vp, *(ep), d) -#endif - -#if !TRANSPORT_LOG_OPTIMIZE_SIZE && !defined(_WIN32) && !defined(_WIN64) -#define TCACHE -#define TCACHE_STALE (0x40000000) -#define TCACHE_FLUID (0x40000000 | 0x80000000) -static unsigned g_tcache_mode = TCACHE_STALE; -static struct timeval g_tcache_tv = {0, 0}; -static struct tm g_tcache_tm = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - -static INLINE int tcache_get(const struct timeval *const tv, - struct tm *const tm) { - unsigned mode; - mode = __atomic_load_n(&g_tcache_mode, __ATOMIC_RELAXED); - if (0 == (mode & TCACHE_FLUID)) { - mode = __atomic_fetch_add(&g_tcache_mode, 1, __ATOMIC_ACQUIRE); - if (0 == (mode & TCACHE_FLUID)) { - if (g_tcache_tv.tv_sec == tv->tv_sec) { - *tm = g_tcache_tm; - __atomic_sub_fetch(&g_tcache_mode, 1, __ATOMIC_RELEASE); - return !0; - } - __atomic_or_fetch(&g_tcache_mode, TCACHE_STALE, __ATOMIC_RELAXED); - } - __atomic_sub_fetch(&g_tcache_mode, 1, __ATOMIC_RELEASE); - } - return 0; -} - -static INLINE void tcache_set(const struct timeval *const tv, - struct tm *const tm) { - unsigned stale = TCACHE_STALE; - if (__atomic_compare_exchange_n(&g_tcache_mode, &stale, TCACHE_FLUID, 0, - __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)) { - g_tcache_tv = *tv; - g_tcache_tm = *tm; - __atomic_and_fetch(&g_tcache_mode, ~TCACHE_FLUID, __ATOMIC_RELEASE); - } -} -#endif - -static void time_callback(struct tm *const tm, unsigned *const msec) { -#if !_TRANSPORT_LOG_MESSAGE_FORMAT_DATETIME_USED - VAR_UNUSED(tm); - VAR_UNUSED(msec); -#else -#if defined(_WIN32) || defined(_WIN64) - SYSTEMTIME st; - GetLocalTime(&st); - tm->tm_year = st.wYear; - tm->tm_mon = st.wMonth - 1; - tm->tm_mday = st.wDay; - tm->tm_wday = st.wDayOfWeek; - tm->tm_hour = st.wHour; - tm->tm_min = st.wMinute; - tm->tm_sec = st.wSecond; - *msec = st.wMilliseconds; -#else - struct timeval tv; - gettimeofday(&tv, 0); -#ifndef TCACHE - localtime_r(&tv.tv_sec, tm); -#else - if (!tcache_get(&tv, tm)) { - localtime_r(&tv.tv_sec, tm); - tcache_set(&tv, tm); - } -#endif - *msec = (unsigned)tv.tv_usec / 1000; -#endif -#endif -} - -static void pid_callback(int *const pid, int *const tid) { -#if !_TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(PID, \ - TRANSPORT_LOG_MESSAGE_CTX_FORMAT) - VAR_UNUSED(pid); -#else -#if defined(_WIN32) || defined(_WIN64) - *pid = GetCurrentProcessId(); -#else - *pid = getpid(); -#endif -#endif - -#if !_TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(TID, \ - TRANSPORT_LOG_MESSAGE_CTX_FORMAT) - VAR_UNUSED(tid); -#else -#if defined(_WIN32) || defined(_WIN64) - *tid = GetCurrentThreadId(); -#elif defined(__ANDROID__) - *tid = gettid(); -#elif defined(__linux__) - *tid = syscall(SYS_gettid); -#elif defined(__MACH__) - *tid = (int)pthread_mach_thread_np(pthread_self()); -#else -#define Platform not supported -#endif -#endif -} - -static void buffer_callback(transport_log_message *msg, char *buf) { - msg->e = (msg->p = msg->buf = buf) + g_buf_sz; -} - -#if _TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(FUNCTION, \ - TRANSPORT_LOG_MESSAGE_SRC_FORMAT) -static const char *funcname(const char *func) { return func ? func : ""; } -#endif - -#if _TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(FILENAME, \ - TRANSPORT_LOG_MESSAGE_SRC_FORMAT) -static const char *filename(const char *file) { - const char *f = file; - for (const char *p = file; 0 != *p; ++p) { - if ('/' == *p || '\\' == *p) { - f = p + 1; - } - } - return f; -} -#endif - -static INLINE size_t nprintf_size(transport_log_message *const msg) { - // *nprintf() always puts 0 in the end when input buffer is not empty. This - // 0 is not desired because its presence sets (ctx->p) to (ctx->e - 1) which - // leaves space for one more character. Some put_xxx() functions don't use - // *nprintf() and could use that last character. In that case log line will - // have multiple (two) half-written parts which is confusing. To workaround - // that we allow *nprintf() to write its 0 in the eol area (which is always - // not empty). - return (size_t)(msg->e - msg->p + 1); -} - -static INLINE void put_nprintf(transport_log_message *const msg, const int n) { - if (0 < n) { - msg->p = n < msg->e - msg->p ? msg->p + n : msg->e; - } -} - -static INLINE char *put_padding_r(const unsigned w, const char wc, char *p, - char *e) { - for (char *const b = e - w; b < p; *--p = wc) { - } - return p; -} - -static char *put_integer_r(unsigned v, const int sign, const unsigned w, - const char wc, char *const e) { - static const char _signs[] = {'-', '0', '+'}; - static const char *const signs = _signs + 1; - char *p = e; - do { - *--p = '0' + v % 10; - } while (0 != (v /= 10)); - if (0 == sign) return put_padding_r(w, wc, p, e); - if ('0' != wc) { - *--p = signs[sign]; - return put_padding_r(w, wc, p, e); - } - p = put_padding_r(w, wc, p, e + 1); - *--p = signs[sign]; - return p; -} - -static INLINE char *put_uint_r(const unsigned v, const unsigned w, - const char wc, char *const e) { - return put_integer_r(v, 0, w, wc, e); -} - -static INLINE char *put_int_r(const int v, const unsigned w, const char wc, - char *const e) { - return 0 <= v ? put_integer_r((unsigned)v, 0, w, wc, e) - : put_integer_r((unsigned)-v, -1, w, wc, e); -} - -static INLINE char *put_stringn(const char *const s_p, const char *const s_e, - char *const p, char *const e) { - const ptrdiff_t m = e - p; - ptrdiff_t n = s_e - s_p; - if (n > m) { - n = m; - } - memcpy(p, s_p, n); - return p + n; -} - -static INLINE char *put_string(const char *s, char *p, char *const e) { - const ptrdiff_t n = e - p; - char *const c = (char *)memccpy(p, s, '\0', n); - return 0 != c ? c - 1 : e; -} - -static INLINE char *put_uint(unsigned v, const unsigned w, const char wc, - char *const p, char *const e) { - char buf[16]; - char *const se = buf + _countof(buf); - char *sp = put_uint_r(v, w, wc, se); - return put_stringn(sp, se, p, e); -} - -#define PUT_CSTR_R(p, STR) \ - do { \ - for (unsigned i = sizeof(STR) - 1; 0 < i--;) { \ - *--(p) = (STR)[i]; \ - } \ - } \ - _TRANSPORT_LOG_ONCE - -#define PUT_CSTR_CHECKED(p, e, STR) \ - do { \ - for (unsigned i = 0; (e) > (p) && (sizeof(STR) - 1) > i; ++i) { \ - *(p)++ = (STR)[i]; \ - } \ - } \ - _TRANSPORT_LOG_ONCE - -/* F_INIT field support. - */ -#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__ -#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__YEAR -#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__MONTH -#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__DAY -#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__HOUR -#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__MINUTE -#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__SECOND -#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__MILLISECOND -#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__PID -#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__TID -#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__LEVEL -#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__TAG(ps, ts) -#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__FUNCTION -#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__FILENAME -#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__FILELINE -#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__S(s) -#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__F_INIT(expr) _PP_UNTUPLE(expr); -#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__F_UINT(w, v) -#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT(field) \ - _PP_CONCAT_3(_TRANSPORT_LOG_MESSAGE_FORMAT_INIT_, _, field) - -/* Implements generation of printf-like format string for log message - * format specification. - */ -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__ "" -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__YEAR "%04u" -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__MONTH "%02u" -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__DAY "%02u" -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__HOUR "%02u" -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__MINUTE "%02u" -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__SECOND "%02u" -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__MILLISECOND "%03u" -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__PID "%5i" -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__TID "%5i" -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__LEVEL "%c" -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__TAG UNDEFINED -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__FUNCTION "%s" -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__FILENAME "%s" -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__FILELINE "%u" -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__S(s) s -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__F_INIT(expr) "" -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__F_UINT(w, v) "%" #w "u" -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT(field) \ - _PP_CONCAT_3(_TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT_, _, field) - -/* Implements generation of printf-like format parameters for log message - * format specification. - */ -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__ -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__YEAR \ - , (unsigned)(tm.tm_year + 1900) -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__MONTH \ - , (unsigned)(tm.tm_mon + 1) -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__DAY , (unsigned)tm.tm_mday -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__HOUR , (unsigned)tm.tm_hour -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__MINUTE , (unsigned)tm.tm_min -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__SECOND , (unsigned)tm.tm_sec -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__MILLISECOND , (unsigned)msec -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__PID , pid -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__TID , tid -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__LEVEL \ - , (char)lvl_char(msg->lvl) -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__TAG UNDEFINED -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__FUNCTION , funcname(src->func) -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__FILENAME , filename(src->file) -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__FILELINE , src->line -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__S(s) -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__F_INIT(expr) -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__F_UINT(w, v) , v -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL(field) \ - _PP_CONCAT_3(_TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL_, _, field) - -/* Implements generation of put_xxx_t statements for log message specification. - */ -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__ -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__YEAR \ - p = put_uint_r(tm.tm_year + 1900, 4, '0', p); -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__MONTH \ - p = put_uint_r((unsigned)tm.tm_mon + 1, 2, '0', p); -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__DAY \ - p = put_uint_r((unsigned)tm.tm_mday, 2, '0', p); -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__HOUR \ - p = put_uint_r((unsigned)tm.tm_hour, 2, '0', p); -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__MINUTE \ - p = put_uint_r((unsigned)tm.tm_min, 2, '0', p); -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__SECOND \ - p = put_uint_r((unsigned)tm.tm_sec, 2, '0', p); -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__MILLISECOND \ - p = put_uint_r(msec, 3, '0', p); -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__PID p = put_int_r(pid, 5, ' ', p); -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__TID p = put_int_r(tid, 5, ' ', p); -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__LEVEL *--p = lvl_char(msg->lvl); -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__TAG UNDEFINED -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__FUNCTION UNDEFINED -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__FILENAME UNDEFINED -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__FILELINE UNDEFINED -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__S(s) PUT_CSTR_R(p, s); -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__F_INIT(expr) -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__F_UINT(w, v) \ - p = put_uint_r(v, w, ' ', p); -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R(field) \ - _PP_CONCAT_3(_TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R_, _, field) - -static void put_ctx(transport_log_message *const msg) { - _PP_MAP(_TRANSPORT_LOG_MESSAGE_FORMAT_INIT, TRANSPORT_LOG_MESSAGE_CTX_FORMAT) -#if !_TRANSPORT_LOG_MESSAGE_FORMAT_FIELDS(TRANSPORT_LOG_MESSAGE_CTX_FORMAT) - VAR_UNUSED(msg); -#else -#if _TRANSPORT_LOG_MESSAGE_FORMAT_DATETIME_USED - struct tm tm; - unsigned msec; - g_time_cb(&tm, &msec); -#endif -#if _TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS( \ - PID, TRANSPORT_LOG_MESSAGE_CTX_FORMAT) || \ - _TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(TID, \ - TRANSPORT_LOG_MESSAGE_CTX_FORMAT) - int pid, tid; - g_pid_cb(&pid, &tid); -#endif - -#if TRANSPORT_LOG_OPTIMIZE_SIZE - int n; - n = snprintf(msg->p, nprintf_size(msg), - _PP_MAP(_TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT, - TRANSPORT_LOG_MESSAGE_CTX_FORMAT) - _PP_MAP(_TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL, - TRANSPORT_LOG_MESSAGE_CTX_FORMAT)); - put_nprintf(msg, n); -#else - char buf[64]; - char *const e = buf + sizeof(buf); - char *p = e; - _PP_RMAP(_TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R, - TRANSPORT_LOG_MESSAGE_CTX_FORMAT) - msg->p = put_stringn(p, e, msg->p, msg->e); -#endif -#endif -} - -#define PUT_TAG(msg, tag, prefix_delim, tag_delim) \ - do { \ - const char *ch; \ - msg->tag_b = msg->p; \ - if (0 != (ch = _transport_log_tag_prefix)) { \ - for (; msg->e != msg->p && 0 != (*msg->p = *ch); ++msg->p, ++ch) { \ - } \ - } \ - if (0 != (ch = tag) && 0 != tag[0]) { \ - if (msg->tag_b != msg->p) { \ - PUT_CSTR_CHECKED(msg->p, msg->e, prefix_delim); \ - } \ - for (; msg->e != msg->p && 0 != (*msg->p = *ch); ++msg->p, ++ch) { \ - } \ - } \ - msg->tag_e = msg->p; \ - if (msg->tag_b != msg->p) { \ - PUT_CSTR_CHECKED(msg->p, msg->e, tag_delim); \ - } \ - } \ - _TRANSPORT_LOG_ONCE - -/* Implements simple put statements for log message specification. - */ -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__ -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__YEAR UNDEFINED -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__MONTH UNDEFINED -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__DAY UNDEFINED -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__HOUR UNDEFINED -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__MINUTE UNDEFINED -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__SECOND UNDEFINED -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__MILLISECOND UNDEFINED -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__PID UNDEFINED -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__TID UNDEFINED -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__LEVEL UNDEFINED -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__TAG(pd, td) \ - PUT_TAG(msg, tag, pd, td); -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__FUNCTION \ - msg->p = put_string(funcname(src->func), msg->p, msg->e); -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__FILENAME \ - msg->p = put_string(filename(src->file), msg->p, msg->e); -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__FILELINE \ - msg->p = put_uint(src->line, 0, '\0', msg->p, msg->e); -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__S(s) \ - PUT_CSTR_CHECKED(msg->p, msg->e, s); -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__F_INIT(expr) -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__F_UINT(w, v) \ - msg->p = put_uint(v, w, ' ', msg->p, msg->e); -#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT(field) \ - _PP_CONCAT_3(_TRANSPORT_LOG_MESSAGE_FORMAT_PUT_, _, field) - -static void put_tag(transport_log_message *const msg, const char *const tag) { - _PP_MAP(_TRANSPORT_LOG_MESSAGE_FORMAT_INIT, TRANSPORT_LOG_MESSAGE_TAG_FORMAT) -#if !_TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(TAG, \ - TRANSPORT_LOG_MESSAGE_TAG_FORMAT) - VAR_UNUSED(tag); -#endif -#if !_TRANSPORT_LOG_MESSAGE_FORMAT_FIELDS(TRANSPORT_LOG_MESSAGE_TAG_FORMAT) - VAR_UNUSED(msg); -#else - _PP_MAP(_TRANSPORT_LOG_MESSAGE_FORMAT_PUT, TRANSPORT_LOG_MESSAGE_TAG_FORMAT) -#endif -} - -static void put_src(transport_log_message *const msg, - const src_location *const src) { - _PP_MAP(_TRANSPORT_LOG_MESSAGE_FORMAT_INIT, TRANSPORT_LOG_MESSAGE_SRC_FORMAT) -#if !_TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS( \ - FUNCTION, TRANSPORT_LOG_MESSAGE_SRC_FORMAT) && \ - !_TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS( \ - FILENAME, TRANSPORT_LOG_MESSAGE_SRC_FORMAT) && \ - !_TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(FILELINE, \ - TRANSPORT_LOG_MESSAGE_SRC_FORMAT) - VAR_UNUSED(src); -#endif -#if !_TRANSPORT_LOG_MESSAGE_FORMAT_FIELDS(TRANSPORT_LOG_MESSAGE_SRC_FORMAT) - VAR_UNUSED(msg); -#else -#if TRANSPORT_LOG_OPTIMIZE_SIZE - int n; - n = snprintf(msg->p, nprintf_size(msg), - _PP_MAP(_TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT, - TRANSPORT_LOG_MESSAGE_SRC_FORMAT) - _PP_MAP(_TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL, - TRANSPORT_LOG_MESSAGE_SRC_FORMAT)); - put_nprintf(msg, n); -#else - _PP_MAP(_TRANSPORT_LOG_MESSAGE_FORMAT_PUT, TRANSPORT_LOG_MESSAGE_SRC_FORMAT) -#endif -#endif -} - -static void put_msg(transport_log_message *const msg, const char *const fmt, - va_list va) { - int n; - msg->msg_b = msg->p; - n = vsnprintf(msg->p, nprintf_size(msg), fmt, va); - put_nprintf(msg, n); -} - -static void output_mem(const transport_log_spec *log, - transport_log_message *const msg, - const mem_block *const mem) { - if (0 == mem->d || 0 == mem->d_sz) { - return; - } - const unsigned char *mem_p = (const unsigned char *)mem->d; - const unsigned char *const mem_e = mem_p + mem->d_sz; - const unsigned char *mem_cut; - const ptrdiff_t mem_width = (ptrdiff_t)log->format->mem_width; - char *const hex_b = msg->msg_b; - char *const ascii_b = hex_b + 2 * mem_width + 2; - char *const ascii_e = ascii_b + mem_width; - if (msg->e < ascii_e) { - return; - } - while (mem_p != mem_e) { - char *hex = hex_b; - char *ascii = ascii_b; - for (mem_cut = mem_width < mem_e - mem_p ? mem_p + mem_width : mem_e; - mem_cut != mem_p; ++mem_p) { - const unsigned char ch = *mem_p; - *hex++ = c_hex[(0xf0 & ch) >> 4]; - *hex++ = c_hex[(0x0f & ch)]; - *ascii++ = isprint(ch) ? (char)ch : '?'; - } - while (hex != ascii_b) { - *hex++ = ' '; - } - msg->p = ascii; - log->output->callback(msg, log->output->arg); - } -} - -void transport_log_set_tag_prefix(const char *const prefix) { - _transport_log_tag_prefix = prefix; -} - -void transport_log_set_mem_width(const unsigned w) { - _transport_log_global_format.mem_width = w; -} - -void transport_log_set_output_level(const int lvl) { - _transport_log_global_output_lvl = lvl; -} - -void transport_log_set_output_v(const unsigned mask, void *const arg, - const transport_log_output_cb callback) { - _transport_log_global_output.mask = mask; - _transport_log_global_output.arg = arg; - _transport_log_global_output.callback = callback; -} - -static void _transport_log_write_imp(const transport_log_spec *log, - const src_location *const src, - const mem_block *const mem, const int lvl, - const char *const tag, - const char *const fmt, va_list va) { - transport_log_message msg; - char buf[TRANSPORT_LOG_BUF_SZ]; - const unsigned mask = log->output->mask; - msg.lvl = lvl; - msg.tag = tag; - g_buffer_cb(&msg, buf); - if (TRANSPORT_LOG_PUT_CTX & mask) { - put_ctx(&msg); - } - if (TRANSPORT_LOG_PUT_TAG & mask) { - put_tag(&msg, tag); - } - if (0 != src && TRANSPORT_LOG_PUT_SRC & mask) { - put_src(&msg, src); - } - if (TRANSPORT_LOG_PUT_MSG & mask) { - put_msg(&msg, fmt, va); - } - log->output->callback(&msg, log->output->arg); - if (0 != mem && TRANSPORT_LOG_PUT_MSG & mask) { - output_mem(log, &msg, mem); - } -} - -void _transport_log_write_d(const char *const func, const char *const file, - const unsigned line, const int lvl, - const char *const tag, const char *const fmt, ...) { - const src_location src = {func, file, line}; - va_list va; - va_start(va, fmt); - _transport_log_write_imp(&global_spec, &src, 0, lvl, tag, fmt, va); - va_end(va); -} - -void _transport_log_write_aux_d(const char *const func, const char *const file, - const unsigned line, - const transport_log_spec *const log, - const int lvl, const char *const tag, - const char *const fmt, ...) { - const src_location src = {func, file, line}; - va_list va; - va_start(va, fmt); - _transport_log_write_imp(log, &src, 0, lvl, tag, fmt, va); - va_end(va); -} - -void _transport_log_write(const int lvl, const char *const tag, - const char *const fmt, ...) { - va_list va; - va_start(va, fmt); - _transport_log_write_imp(&global_spec, 0, 0, lvl, tag, fmt, va); - va_end(va); -} - -void _transport_log_write_aux(const transport_log_spec *const log, - const int lvl, const char *const tag, - const char *const fmt, ...) { - va_list va; - va_start(va, fmt); - _transport_log_write_imp(log, 0, 0, lvl, tag, fmt, va); - va_end(va); -} - -void _transport_log_write_mem_d(const char *const func, const char *const file, - const unsigned line, const int lvl, - const char *const tag, const void *const d, - const unsigned d_sz, const char *const fmt, - ...) { - const src_location src = {func, file, line}; - const mem_block mem = {d, d_sz}; - va_list va; - va_start(va, fmt); - _transport_log_write_imp(&global_spec, &src, &mem, lvl, tag, fmt, va); - va_end(va); -} - -void _transport_log_write_mem_aux_d(const char *const func, - const char *const file, const unsigned line, - const transport_log_spec *const log, - const int lvl, const char *const tag, - const void *const d, const unsigned d_sz, - const char *const fmt, ...) { - const src_location src = {func, file, line}; - const mem_block mem = {d, d_sz}; - va_list va; - va_start(va, fmt); - _transport_log_write_imp(log, &src, &mem, lvl, tag, fmt, va); - va_end(va); -} +constexpr char LogConfiguration::log_config_section[]; +constexpr char LogConfiguration::log_name[]; -void _transport_log_write_mem(const int lvl, const char *const tag, - const void *const d, const unsigned d_sz, - const char *const fmt, ...) { - const mem_block mem = {d, d_sz}; - va_list va; - va_start(va, fmt); - _transport_log_write_imp(&global_spec, 0, &mem, lvl, tag, fmt, va); - va_end(va); -} +LogConfiguration log_conf = LogConfiguration(); -void _transport_log_write_mem_aux(const transport_log_spec *const log, - const int lvl, const char *const tag, - const void *const d, const unsigned d_sz, - const char *const fmt, ...) { - const mem_block mem = {d, d_sz}; - va_list va; - va_start(va, fmt); - _transport_log_write_imp(log, 0, &mem, lvl, tag, fmt, va); - va_end(va); -}
\ No newline at end of file +} // namespace utils diff --git a/libtransport/src/utils/max_filter.h b/libtransport/src/utils/max_filter.h new file mode 100644 index 000000000..db1a1a565 --- /dev/null +++ b/libtransport/src/utils/max_filter.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License.sudo make instamake install + */ + +#pragma once + +#include <deque> +#include <iostream> +#include <set> +#include <type_traits> +#include <vector> + +namespace utils { + +template <typename T> +class MaxFilter { + public: + MaxFilter(std::size_t size) : size_(size) {} + + std::size_t size() const { return by_arrival_.size(); } + + template <typename R> + void pushBack(R&& value) { + if (by_arrival_.size() >= size_) { + by_order_.erase(by_arrival_.back()); + by_arrival_.pop_back(); + } + + by_arrival_.push_front(by_order_.insert(std::forward<R>(value))); + } + + void clear() { + by_arrival_.clear(); + by_order_.clear(); + } + + const T& begin() const { return *by_order_.crbegin(); } + + const T& rBegin() const { return *by_order_.rbegin(); } + + private: + std::multiset<T> by_order_; + std::deque<typename std::multiset<T>::const_iterator> by_arrival_; + std::size_t size_; +}; + +} // namespace utils diff --git a/libtransport/src/utils/membuf.cc b/libtransport/src/utils/membuf.cc index 94e5b13a1..952116bb7 100644 --- a/libtransport/src/utils/membuf.cc +++ b/libtransport/src/utils/membuf.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Copyright 2013-present Facebook, Inc. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,7 @@ #include <hicn/transport/portability/win_portability.h> #endif +#include <glog/logging.h> #include <hicn/transport/utils/membuf.h> #include <cassert> @@ -145,6 +146,18 @@ void MemBuf::operator delete(void* /* ptr */, void* /* placement */) { // constructor. } +bool MemBuf::operator==(const MemBuf& other) { + if (length() != other.length()) { + return false; + } + + return (memcmp(data(), other.data(), length()) == 0); +} + +bool MemBuf::operator!=(const MemBuf& other) { + return !this->operator==(other); +} + void MemBuf::releaseStorage(HeapStorage* storage, uint16_t freeFlags) { // Use relaxed memory order here. If we are unlucky and happen to get // out-of-date data the compare_exchange_weak() call below will catch @@ -197,7 +210,7 @@ MemBuf::MemBuf(CopyBufferOp /* op */, const void* buf, std::size_t size, : MemBuf(CREATE, headroom + size + min_tailroom) { advance(headroom); if (size > 0) { - assert(buf != nullptr); + DCHECK(buf != nullptr); memcpy(writableData(), buf, size); append(size); } @@ -299,21 +312,23 @@ unique_ptr<MemBuf> MemBuf::takeOwnership(void* buf, std::size_t capacity, } } -MemBuf::MemBuf(WrapBufferOp, const void* buf, std::size_t capacity) noexcept +MemBuf::MemBuf(WrapBufferOp, const void* buf, std::size_t length, + std::size_t capacity) noexcept : MemBuf(InternalConstructor(), 0, // We cast away the const-ness of the buffer here. // This is okay since MemBuf users must use unshare() to create a // copy of this buffer before writing to the buffer. static_cast<uint8_t*>(const_cast<void*>(buf)), capacity, - static_cast<uint8_t*>(const_cast<void*>(buf)), capacity) {} + static_cast<uint8_t*>(const_cast<void*>(buf)), length) {} -unique_ptr<MemBuf> MemBuf::wrapBuffer(const void* buf, std::size_t capacity) { - return std::make_unique<MemBuf>(WRAP_BUFFER, buf, capacity); +unique_ptr<MemBuf> MemBuf::wrapBuffer(const void* buf, std::size_t length, + std::size_t capacity) { + return std::make_unique<MemBuf>(WRAP_BUFFER, buf, length, capacity); } -MemBuf MemBuf::wrapBufferAsValue(const void* buf, +MemBuf MemBuf::wrapBufferAsValue(const void* buf, std::size_t length, std::size_t capacity) noexcept { - return MemBuf(WrapBufferOp::WRAP_BUFFER, buf, capacity); + return MemBuf(WrapBufferOp::WRAP_BUFFER, buf, length, capacity); } MemBuf::MemBuf() noexcept {} @@ -355,8 +370,8 @@ MemBuf::MemBuf(InternalConstructor, uintptr_t flagsAndSharedInfo, uint8_t* buf, length_(length), capacity_(capacity), flags_and_shared_info_(flagsAndSharedInfo) { - assert(data >= buf); - assert(data + length <= buf + capacity); + DCHECK(data >= buf); + DCHECK(data + length <= buf + capacity); } MemBuf::~MemBuf() { @@ -545,7 +560,7 @@ void MemBuf::unshareOneSlow() { // minimum capacity we also maintain at least the same amount of tailroom. std::size_t headlen = headroom(); if (length_ > 0) { - assert(data_ != nullptr); + DCHECK(data_ != nullptr); memcpy(buf + headlen, data_, length_); } @@ -562,7 +577,7 @@ void MemBuf::unshareOneSlow() { void MemBuf::unshareChained() { // unshareChained() should only be called if we are part of a chain of // multiple MemBufs. The caller should have already verified this. - assert(isChained()); + DCHECK(isChained()); MemBuf* current = this; while (true) { @@ -592,7 +607,7 @@ void MemBuf::markExternallyShared() { } void MemBuf::makeManagedChained() { - assert(isChained()); + DCHECK(isChained()); MemBuf* current = this; while (true) { @@ -663,15 +678,15 @@ void MemBuf::coalesceAndReallocate(size_t new_headroom, size_t new_length, size_t remaining = new_length; do { if (current->length_ > 0) { - assert(current->length_ <= remaining); - assert(current->data_ != nullptr); + DCHECK(current->length_ <= remaining); + DCHECK(current->data_ != nullptr); remaining -= current->length_; memcpy(p, current->data_, current->length_); p += current->length_; } current = current->next_; } while (current != end); - assert(remaining == 0); + DCHECK(remaining == 0); // Point at the new buffer decrementRefcount(); @@ -785,7 +800,7 @@ void MemBuf::reserveSlow(std::size_t min_headroom, std::size_t min_tailroom) { new_allocated_capacity = goodExtBufferSize(new_capacity); new_buffer = static_cast<uint8_t*>(malloc(new_allocated_capacity)); if (length_ > 0) { - assert(data_ != nullptr); + DCHECK(data_ != nullptr); memcpy(new_buffer + min_headroom, data_, length_); } if (sharedInfo()) { @@ -862,4 +877,22 @@ void MemBuf::initExtBuffer(uint8_t* buf, size_t mallocSize, *infoReturn = sharedInfo; } +bool MemBuf::ensureCapacity(std::size_t capacity) { + return !isChained() && std::size_t((bufferEnd() - data())) >= capacity; +} + +bool MemBuf::ensureCapacityAndFillUnused(std::size_t capacity, + uint8_t placeholder) { + auto ret = ensureCapacity(capacity); + if (!ret) { + return ret; + } + + if (length() < capacity) { + std::memset(writableTail(), placeholder, capacity - length()); + } + + return ret; +} + } // namespace utils
\ No newline at end of file diff --git a/libtransport/src/utils/memory_pool_allocator.h b/libtransport/src/utils/memory_pool_allocator.h index adc1443ad..c2b34e7aa 100644 --- a/libtransport/src/utils/memory_pool_allocator.h +++ b/libtransport/src/utils/memory_pool_allocator.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -149,4 +149,4 @@ class Allocator : private MemoryPool<T, growSize> { void destroy(pointer p) { p->~T(); } }; -}
\ No newline at end of file +} // namespace utils
\ No newline at end of file diff --git a/libtransport/src/utils/min_filter.h b/libtransport/src/utils/min_filter.h index dcfd5652d..4a3882601 100644 --- a/libtransport/src/utils/min_filter.h +++ b/libtransport/src/utils/min_filter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -15,9 +15,6 @@ #pragma once -#include <hicn/transport/portability/portability.h> -#include <hicn/transport/utils/log.h> - #include <deque> #include <iostream> #include <set> @@ -31,10 +28,10 @@ class MinFilter { public: MinFilter(std::size_t size) : size_(size) {} - std::size_t size() { return by_arrival_.size(); } + std::size_t size() const { return by_arrival_.size(); } template <typename R> - TRANSPORT_ALWAYS_INLINE void pushBack(R&& value) { + void pushBack(R&& value) { if (by_arrival_.size() >= size_) { by_order_.erase(by_arrival_.back()); by_arrival_.pop_back(); @@ -43,9 +40,14 @@ class MinFilter { by_arrival_.push_front(by_order_.insert(std::forward<R>(value))); } - TRANSPORT_ALWAYS_INLINE const T& begin() { return *by_order_.cbegin(); } + void clear() { + by_arrival_.clear(); + by_order_.clear(); + } + + const T& begin() const { return *by_order_.cbegin(); } - TRANSPORT_ALWAYS_INLINE const T& rBegin() { return *by_order_.crbegin(); } + const T& rBegin() const { return *by_order_.crbegin(); } private: std::multiset<T> by_order_; diff --git a/libtransport/src/utils/stream_buffer.h b/libtransport/src/utils/stream_buffer.h index adfb696f2..dde769a55 100644 --- a/libtransport/src/utils/stream_buffer.h +++ b/libtransport/src/utils/stream_buffer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: diff --git a/libtransport/src/utils/string_tokenizer.cc b/libtransport/src/utils/string_tokenizer.cc index a280a3c43..cb0a4a3ad 100644 --- a/libtransport/src/utils/string_tokenizer.cc +++ b/libtransport/src/utils/string_tokenizer.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: diff --git a/libtransport/src/utils/suffix_strategy.h b/libtransport/src/utils/suffix_strategy.h index 6c4dd2785..4b3ddbc74 100644 --- a/libtransport/src/utils/suffix_strategy.h +++ b/libtransport/src/utils/suffix_strategy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -15,149 +15,128 @@ #pragma once -#include <core/manifest_format.h> +#include <hicn/transport/core/name.h> +#include <hicn/transport/errors/runtime_exception.h> namespace utils { -using transport::core::NextSegmentCalculationStrategy; +/** + * INCREMENTAL: Manifests will be received inline with the data with no specific + * assumption regarding the manifest capacity. Consumers can send interests + * using a +1 heuristic. + * + * MANIFEST_CAPACITY_BASED: manifests with capacity N have a suffix multiple of + * N+1: 0, N+1, 2(N+1) etc. Contents have a suffix incremented by 1 except when + * it conflicts with a manifest: 1, 2, ..., N, N+2, N+3, ..., 2N+1, 2N+3 + */ +enum class NextSuffixStrategy : uint8_t { + INCREMENTAL = 1, +}; class SuffixStrategy { public: - static constexpr uint32_t INVALID_SUFFIX = - std::numeric_limits<uint32_t>::max(); + static constexpr uint32_t MAX_SUFFIX = std::numeric_limits<uint32_t>::max(); + static constexpr uint8_t MANIFEST_MAX_CAPACITY = + std::numeric_limits<uint8_t>::max(); - SuffixStrategy(NextSegmentCalculationStrategy strategy) + SuffixStrategy(NextSuffixStrategy strategy, uint32_t offset = 0, + uint32_t manifest_capacity = MANIFEST_MAX_CAPACITY) : suffix_stragegy_(strategy), + next_suffix_(offset), + manifest_capacity_(manifest_capacity), total_count_(0), - final_suffix_(INVALID_SUFFIX) {} + final_suffix_(MAX_SUFFIX) {} virtual ~SuffixStrategy() = default; + virtual uint32_t checkNextSuffix() const = 0; virtual uint32_t getNextSuffix() = 0; - virtual uint32_t getFinalSuffix() { return final_suffix_; } - - virtual void setFinalSuffix(std::uint32_t final_suffix) { - if (final_suffix != INVALID_SUFFIX) { - final_suffix_ = final_suffix; - } - } - + virtual uint32_t checkNextManifestSuffix() const = 0; virtual uint32_t getNextManifestSuffix() = 0; + virtual uint32_t checkNextContentSuffix() const = 0; virtual uint32_t getNextContentSuffix() = 0; - virtual void reset(uint32_t offset = 0) = 0; + virtual void reset(uint32_t offset = 0) { + next_suffix_ = offset; + total_count_ = 0; + } - virtual uint32_t getManifestCapacity() = 0; + virtual uint32_t getManifestCapacity() const { return manifest_capacity_; }; - virtual void setManifestCapacity(uint32_t capacity) = 0; + virtual void setManifestCapacity(uint8_t capacity) { + manifest_capacity_ = capacity; + } - virtual uint32_t getTotalCount() { return total_count_; }; + virtual uint32_t getFinalSuffix() const { return final_suffix_; } - NextSegmentCalculationStrategy getSuffixStrategy() { - return suffix_stragegy_; + virtual void setFinalSuffix(std::uint32_t final_suffix) { + if (final_suffix != MAX_SUFFIX) { + final_suffix_ = final_suffix; + } } - protected: - inline void incrementTotalCount() { total_count_++; }; + NextSuffixStrategy getSuffixStrategy() const { return suffix_stragegy_; } + + virtual uint32_t getTotalCount() const { return total_count_; } protected: - NextSegmentCalculationStrategy suffix_stragegy_; + NextSuffixStrategy suffix_stragegy_; + std::uint32_t next_suffix_; + std::uint8_t manifest_capacity_; std::uint32_t total_count_; std::uint32_t final_suffix_; + + inline void incrementTotalCount() { total_count_++; }; }; class IncrementalSuffixStrategy : public SuffixStrategy { public: IncrementalSuffixStrategy(std::uint32_t start_offset) - : SuffixStrategy(NextSegmentCalculationStrategy::INCREMENTAL), - next_suffix_(start_offset) {} - - TRANSPORT_ALWAYS_INLINE std::uint32_t getNextSuffix() override { - incrementTotalCount(); - return next_suffix_++; - } - - TRANSPORT_ALWAYS_INLINE std::uint32_t getNextContentSuffix() override { - return getNextSuffix(); - } - - TRANSPORT_ALWAYS_INLINE std::uint32_t getNextManifestSuffix() override { - return getNextSuffix(); - } - - uint32_t getManifestCapacity() override { - throw errors::RuntimeException( - "No manifest capacity in IncrementalSuffixStrategy."); - } + : SuffixStrategy(NextSuffixStrategy::INCREMENTAL, start_offset) {} - void setManifestCapacity(uint32_t capacity) override { - throw errors::RuntimeException( - "No manifest capacity in IncrementalSuffixStrategy."); + TRANSPORT_ALWAYS_INLINE std::uint32_t checkNextSuffix() const override { + return next_suffix_; } - void reset(std::uint32_t offset = 0) override { next_suffix_ = offset; } - - protected: - std::uint32_t next_suffix_; -}; - -class CapacityBasedSuffixStrategy : public SuffixStrategy { - public: - CapacityBasedSuffixStrategy(std::uint32_t start_offset, - std::uint32_t manifest_capacity) - : SuffixStrategy(NextSegmentCalculationStrategy::INCREMENTAL), - next_suffix_(start_offset), - segments_in_manifest_(manifest_capacity), - current_manifest_iteration_(0) {} - TRANSPORT_ALWAYS_INLINE std::uint32_t getNextSuffix() override { incrementTotalCount(); return next_suffix_++; } - TRANSPORT_ALWAYS_INLINE std::uint32_t getNextContentSuffix() override { - incrementTotalCount(); - return next_suffix_ % segments_in_manifest_ == 0 ? next_suffix_++ - : ++next_suffix_; + TRANSPORT_ALWAYS_INLINE std::uint32_t checkNextContentSuffix() + const override { + return checkNextSuffix(); } - TRANSPORT_ALWAYS_INLINE std::uint32_t getNextManifestSuffix() override { - incrementTotalCount(); - return (current_manifest_iteration_++) * (segments_in_manifest_ + 1); + TRANSPORT_ALWAYS_INLINE std::uint32_t getNextContentSuffix() override { + return getNextSuffix(); } - TRANSPORT_ALWAYS_INLINE uint32_t getManifestCapacity() override { - return segments_in_manifest_; + TRANSPORT_ALWAYS_INLINE std::uint32_t checkNextManifestSuffix() + const override { + return checkNextSuffix(); } - TRANSPORT_ALWAYS_INLINE void setManifestCapacity(uint32_t capacity) override { - segments_in_manifest_ = capacity; + TRANSPORT_ALWAYS_INLINE std::uint32_t getNextManifestSuffix() override { + return getNextSuffix(); } void reset(std::uint32_t offset = 0) override { next_suffix_ = offset; } - - protected: - std::uint32_t next_suffix_; - std::uint32_t segments_in_manifest_; - std::uint32_t current_manifest_iteration_; }; class SuffixStrategyFactory { public: static std::unique_ptr<SuffixStrategy> getSuffixStrategy( - NextSegmentCalculationStrategy strategy, uint32_t start_offset, - uint32_t manifest_capacity = 0) { + NextSuffixStrategy strategy, uint32_t start_offset = 0, + uint32_t manifest_capacity = SuffixStrategy::MANIFEST_MAX_CAPACITY) { switch (strategy) { - case NextSegmentCalculationStrategy::INCREMENTAL: + case NextSuffixStrategy::INCREMENTAL: return std::make_unique<IncrementalSuffixStrategy>(start_offset); - case NextSegmentCalculationStrategy::MANIFEST_CAPACITY_BASED: - return std::make_unique<CapacityBasedSuffixStrategy>(start_offset, - manifest_capacity); default: throw errors::RuntimeException( - "No valid NextSegmentCalculationStrategy specified."); + "No valid NextSuffixStrategy specified."); } } }; diff --git a/libtransport/src/utils/test.h b/libtransport/src/utils/test.h index e3dd619ac..b91c8cb1f 100644 --- a/libtransport/src/utils/test.h +++ b/libtransport/src/utils/test.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: diff --git a/libtransport/src/utils/traffic_generator.cc b/libtransport/src/utils/traffic_generator.cc new file mode 100644 index 000000000..a617e3dc9 --- /dev/null +++ b/libtransport/src/utils/traffic_generator.cc @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <hicn/transport/core/prefix.h> +#include <hicn/transport/utils/traffic_generator.h> + +#include <iostream> + +namespace transport { + +/* TrafficGenerator */ + +TrafficGenerator::TrafficGenerator(uint32_t count) : count_(count), sent_(0) {} + +bool TrafficGenerator::hasFinished() { return sent_ >= count_; } + +uint32_t TrafficGenerator::getSentCount() { return sent_; } + +std::pair<std::string, uint32_t> TrafficGenerator::getPrefixAndSuffix() { + return std::make_pair(getPrefix(), getSuffix()); +} + +void TrafficGenerator::reset() { sent_ = 0; }; + +void TrafficGenerator::onSuffixGenerated() { + if (hasFinished()) throw std::runtime_error("Too many pings"); + sent_++; +}; + +/* IncrSuffixTrafficGenerator */ + +IncrSuffixTrafficGenerator::IncrSuffixTrafficGenerator(std::string prefix, + uint32_t suffix, + uint32_t count) + : TrafficGenerator(count), + prefix_(prefix), + suffix_(suffix), + initial_suffix_(suffix) {} + +std::string IncrSuffixTrafficGenerator::getPrefix() { return prefix_; } + +uint32_t IncrSuffixTrafficGenerator::getSuffix() { + TrafficGenerator::onSuffixGenerated(); + return suffix_++; +} + +void IncrSuffixTrafficGenerator::reset() { + TrafficGenerator::reset(); + suffix_ = initial_suffix_; +}; + +/* RandomTrafficGenerator */ + +RandomTrafficGenerator::RandomTrafficGenerator(uint32_t count, + std::string net_prefix) + : TrafficGenerator(count), + net_prefix_(net_prefix), + rand_engine_((std::random_device())()), + uniform_distribution_(0, std::numeric_limits<uint32_t>::max()) {} + +std::string RandomTrafficGenerator::getPrefix() { + // Generate random prefix + core::Prefix prefix(net_prefix_); + core::Name name = prefix.makeRandomName(); + return name.getPrefix(); +} + +uint32_t RandomTrafficGenerator::getSuffix() { + TrafficGenerator::onSuffixGenerated(); + + // Generate random suffix + return uniform_distribution_(rand_engine_); +} + +} // namespace transport
\ No newline at end of file diff --git a/libtransport/src/utils/uri.cc b/libtransport/src/utils/uri.cc index 33eb8b45b..12b11641c 100644 --- a/libtransport/src/utils/uri.cc +++ b/libtransport/src/utils/uri.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: |