Skip to content
This repository has been archived by the owner on Mar 22, 2023. It is now read-only.

Code duplication reported by PMD #1191

Open
KFilipek opened this issue Aug 4, 2021 · 0 comments
Open

Code duplication reported by PMD #1191

KFilipek opened this issue Aug 4, 2021 · 0 comments
Labels
new need to be triaged Priority: 4 low Type: Bug Something isn't working

Comments

@KFilipek
Copy link
Contributor

KFilipek commented Aug 4, 2021

ISSUE: Code duplication reported by PMD

Environment Information

  • libpmemobj-cpp version(s): e844778

Please provide a reproduction of the bug:

Get the tool from PMD site

./bin/run.sh cpd --minimum-tokens 100 --files ~/Development/work/libpmemobj-cpp/include/ --language cpp

How often bug is revealed:

(always, often, rare)

Details

./bin/run.sh cpd --minimum-tokens 100 --files ~/Development/work/libpmemobj-cpp/include/ --language cpp
Found a 34 line (240 tokens) duplication in the following files: 
Starting at line 597 of /home/kfilipek/Development/work/libpmemobj-cpp/include/libpmemobj++/container/segment_vector.hpp
Starting at line 133 of /home/kfilipek/Development/work/libpmemobj-cpp/include/libpmemobj++/container/vector.hpp

	slice<const_iterator> crange(size_type start, size_type n) const;

	/* Capacity */
	constexpr bool empty() const noexcept;
	size_type size() const noexcept;
	constexpr size_type max_size() const noexcept;
	void reserve(size_type capacity_new);
	size_type capacity() const noexcept;
	void shrink_to_fit();

	/* Modifiers */
	void clear();
	void free_data();
	iterator insert(const_iterator pos, const T &value);
	iterator insert(const_iterator pos, T &&value);
	iterator insert(const_iterator pos, size_type count, const T &value);
	template <typename InputIt,
		  typename std::enable_if<
			  detail::is_input_iterator<InputIt>::value,
			  InputIt>::type * = nullptr>
	iterator insert(const_iterator pos, InputIt first, InputIt last);
	iterator insert(const_iterator pos, std::initializer_list<T> ilist);
	template <class... Args>
	iterator emplace(const_iterator pos, Args &&... args);
	template <class... Args>
	reference emplace_back(Args &&... args);
	iterator erase(const_iterator pos);
	iterator erase(const_iterator first, const_iterator last);
	void push_back(const T &value);
	void push_back(T &&value);
	void pop_back();
	void resize(size_type count);
	void resize(size_type count, const value_type &value);
	void swap(segment_vector &other);
=====================================================================
Found a 56 line (148 tokens) duplication in the following files: 
Starting at line 61 of /home/kfilipek/Development/work/libpmemobj-cpp/include/libpmemobj++/make_persistent_array.hpp
Starting at line 121 of /home/kfilipek/Development/work/libpmemobj-cpp/include/libpmemobj++/make_persistent_array.hpp

	       static_cast<std::size_t>(std::numeric_limits<ptrdiff_t>::max()));

	if (pmemobj_tx_stage() != TX_STAGE_WORK)
		throw pmem::transaction_scope_error(
			"refusing to allocate memory outside of transaction scope");

	persistent_ptr<T> ptr = pmemobj_tx_xalloc(
		sizeof(I) * N, detail::type_num<I>(), flag.value);

	if (ptr == nullptr) {
		const char *msg = "Failed to allocate persistent memory array";
		if (errno == ENOMEM)
			throw detail::exception_with_errormsg<
				pmem::transaction_out_of_memory>(msg);
		else
			throw detail::exception_with_errormsg<
				pmem::transaction_alloc_error>(msg);
	}

	/*
	 * cache raw pointer to data - using persistent_ptr.get() in a loop
	 * is expensive.
	 */
	auto data = ptr.get();

	/*
	 * When an exception is thrown from one of the constructors
	 * we don't perform any cleanup - i.e. we don't call destructors
	 * (unlike new[] operator), we only rely on transaction abort.
	 * This approach was taken to ensure consistent behaviour for
	 * case when transaction is aborted after make_persistent completes and
	 * we have no way to call destructors.
	 */
	for (std::ptrdiff_t i = 0; i < static_cast<std::ptrdiff_t>(N); ++i)
		detail::create<I>(data + i);

	return ptr;
}

/**
 * Transactionally allocate and construct an array of objects of type T.
 *
 * This function can be used to *transactionally* allocate an array.
 * This overload only participates in overload resolution if T is an array.
 *
 * @param[in] flag affects behaviour of allocator
 *
 * @return persistent_ptr<T[N]> on success
 *
 * @throw transaction_scope_error if called outside of an active
 * transaction
 * @throw transaction_alloc_error on transactional allocation failure.
 * @throw rethrow exception from T constructor
 * @ingroup allocation
 */
template <typename T>
=====================================================================
Found a 19 line (130 tokens) duplication in the following files: 
Starting at line 2644 of /home/kfilipek/Development/work/libpmemobj-cpp/include/libpmemobj++/container/basic_string.hpp
Starting at line 2860 of /home/kfilipek/Development/work/libpmemobj-cpp/include/libpmemobj++/container/basic_string.hpp

	auto count2 = static_cast<size_type>(std::distance(first2, last2));

	count = (std::min)(count, sz - index);

	if (sz - count + count2 > max_size())
		throw std::length_error("Count exceeds max size.");

	auto new_size = sz - count + count2;

	auto pop = get_pool();

	flat_transaction::run(pop, [&] {
		if (is_sso_used() && new_size <= sso_capacity) {
			add_sso_to_tx(index, new_size - index + 1);

			assert(count2 < new_size + 1);
			traits_type::move(&sso_data()._data[index + count2],
					  &sso_data()._data[index + count],
					  sz - index - count);
=====================================================================
Found a 52 line (123 tokens) duplication in the following files: 
Starting at line 56 of /home/kfilipek/Development/work/libpmemobj-cpp/include/libpmemobj++/mutex.hpp
Starting at line 59 of /home/kfilipek/Development/work/libpmemobj-cpp/include/libpmemobj++/timed_mutex.hpp

	~mutex() = default;

	/**
	 * Locks the mutex, blocks if already locked.
	 *
	 * If a different thread already locked this mutex, the calling
	 * thread will block. If the same thread tries to lock a mutex
	 * it already owns, the behavior is undefined.
	 *
	 * @throw lock_error when an error occurs, this includes all
	 * system related errors with the underlying implementation of
	 * the mutex.
	 */
	void
	lock()
	{
		PMEMobjpool *pop = pmemobj_pool_by_ptr(this);
		if (int ret = pmemobj_mutex_lock(pop, &this->plock))
			throw pmem::lock_error(ret, std::system_category(),
					       "Failed to lock a mutex.")
				.with_pmemobj_errormsg();
	}

	/**
	 * Tries to lock the mutex, returns regardless if the lock
	 * succeeds.
	 *
	 * If the same thread tries to lock a mutex it already owns,
	 * the behavior is undefined.
	 *
	 * @return `true` on successful lock acquisition, `false`
	 * otherwise.
	 *
	 * @throw lock_error when an error occurs, this includes all
	 * system related errors with the underlying implementation of
	 * the mutex.
	 */
	bool
	try_lock()
	{
		PMEMobjpool *pop = pmemobj_pool_by_ptr(this);
		int ret = pmemobj_mutex_trylock(pop, &this->plock);

		if (ret == 0)
			return true;
		else if (ret == EBUSY)
			return false;
		else
			throw pmem::lock_error(ret, std::system_category(),
					       "Failed to lock a mutex.")
				.with_pmemobj_errormsg();
	}
=====================================================================
Found a 24 line (111 tokens) duplication in the following files: 
Starting at line 182 of /home/kfilipek/Development/work/libpmemobj-cpp/include/libpmemobj++/make_persistent_array.hpp
Starting at line 229 of /home/kfilipek/Development/work/libpmemobj-cpp/include/libpmemobj++/make_persistent_array.hpp

	typedef typename detail::pp_array_type<T>::type I;

	if (pmemobj_tx_stage() != TX_STAGE_WORK)
		throw pmem::transaction_scope_error(
			"refusing to free memory outside of transaction scope");

	if (ptr == nullptr)
		return;

	/*
	 * cache raw pointer to data - using persistent_ptr.get() in a loop
	 * is expensive.
	 */
	auto data = ptr.get();

	for (std::ptrdiff_t i = 0; i < static_cast<std::ptrdiff_t>(N); ++i)
		detail::destroy<I>(
			data[static_cast<std::ptrdiff_t>(N) - 1 - i]);

	if (pmemobj_tx_free(*ptr.raw_ptr()) != 0)
		throw detail::exception_with_errormsg<
			pmem::transaction_free_error>(
			"failed to delete persistent memory object");
}
=====================================================================
Found a 12 line (107 tokens) duplication in the following files: 
Starting at line 3514 of /home/kfilipek/Development/work/libpmemobj-cpp/include/libpmemobj++/experimental/radix_tree.hpp
Starting at line 3536 of /home/kfilipek/Development/work/libpmemobj-cpp/include/libpmemobj++/experimental/radix_tree.hpp

						      detail::pair<K, V> &&p)
{
	return make(parent, std::piecewise_construct,
		    std::forward_as_tuple(std::move(p.first)),
		    std::forward_as_tuple(std::move(p.second)));
}

template <typename Key, typename Value, typename BytesView, bool MtMode>
template <typename K, typename V>
persistent_ptr<typename radix_tree<Key, Value, BytesView, MtMode>::leaf>
radix_tree<Key, Value, BytesView, MtMode>::leaf::make(
	pointer_type parent, const detail::pair<K, V> &p)

Additional information about Priority and Help Requested:

Are you willing to submit a pull request with a proposed change? Yes

Requested priority: Low

@KFilipek KFilipek added the Type: Bug Something isn't working label Aug 4, 2021
@lukaszstolarczuk lukaszstolarczuk added new need to be triaged Priority: 4 low labels Aug 4, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
new need to be triaged Priority: 4 low Type: Bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants