Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrap libsolv Transaction #2554

Merged
merged 10 commits into from
Jun 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions libmamba/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ set(LIBMAMBA_SOURCES
${LIBMAMBA_SOURCE_DIR}/solv-cpp/repo.cpp
${LIBMAMBA_SOURCE_DIR}/solv-cpp/solvable.cpp
${LIBMAMBA_SOURCE_DIR}/solv-cpp/solver.cpp
${LIBMAMBA_SOURCE_DIR}/solv-cpp/transaction.cpp
# C++ wrapping of libcurl
${LIBMAMBA_SOURCE_DIR}/core/curl.cpp
# C++ wrapping of compression libs (zstd and bzlib)
Expand Down Expand Up @@ -278,6 +279,7 @@ set(LIBMAMBA_PRIVATE_HEADERS
${LIBMAMBA_SOURCE_DIR}/solv-cpp/solvable.hpp
${LIBMAMBA_SOURCE_DIR}/solv-cpp/solver.hpp
${LIBMAMBA_SOURCE_DIR}/solv-cpp/repo.hpp
${LIBMAMBA_SOURCE_DIR}/solv-cpp/transaction.hpp
# C++ wrapping of compression libs (zstd and bzlib)
${LIBMAMBA_SOURCE_DIR}/core/compression.hpp
# C++ wrapping of libcurl
Expand Down
3 changes: 3 additions & 0 deletions libmamba/src/solv-cpp/ids.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ namespace mamba::solv
using RelationFlag = int;
using DistType = int;
using SolverFlag = int;
using TransactionOrderFlag = int;
using TransactionStepType = int;
using TransactionMode = int;
}

#endif
5 changes: 5 additions & 0 deletions libmamba/src/solv-cpp/queue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,11 @@ namespace mamba::solv
return m_queue.elements;
}

auto ObjQueue::contains(value_type id) const -> bool
{
return std::find(cbegin(), cend(), id) != cend();
}

auto ObjQueue::raw() const -> const ::Queue*
{
return &m_queue;
Expand Down
2 changes: 2 additions & 0 deletions libmamba/src/solv-cpp/queue.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ namespace mamba::solv
auto data() -> pointer;
auto data() const -> const_pointer;

auto contains(value_type id) const -> bool;

template <template <typename, typename...> class C>
auto as() -> C<value_type>;

Expand Down
12 changes: 9 additions & 3 deletions libmamba/src/solv-cpp/solvable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ namespace mamba::solv
void ObjSolvableView::set_dependencies(const ObjQueue& q) const
{
::solvable_set_deparray(
const_cast<::Solvable*>(raw()),
raw(),
SOLVABLE_REQUIRES,
const_cast<::Queue*>(q.raw()),
/* marker= */ 0
Expand All @@ -385,7 +385,7 @@ namespace mamba::solv
void ObjSolvableView::set_provides(const ObjQueue& q) const
{
::solvable_set_deparray(
const_cast<::Solvable*>(raw()),
raw(),
SOLVABLE_PROVIDES,
const_cast<::Queue*>(q.raw()),
/* marker= */ 0
Expand Down Expand Up @@ -421,7 +421,7 @@ namespace mamba::solv
else
{
::solvable_set_deparray(
const_cast<::Solvable*>(raw()),
raw(),
SOLVABLE_CONSTRAINS,
const_cast<::Queue*>(q.raw()),
/* marker= */ -1
Expand Down Expand Up @@ -464,4 +464,10 @@ namespace mamba::solv
{
return add_track_feature(solvable_add_pool_str(raw()->repo->pool, feat));
}

auto ObjSolvableViewConst::installed() const -> bool
{
const auto* const repo = raw()->repo;
return (repo != nullptr) && (repo == repo->pool->installed);
}
}
3 changes: 3 additions & 0 deletions libmamba/src/solv-cpp/solvable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ namespace mamba::solv
/** Queue of ``StringId``. */
auto track_features() const -> ObjQueue;

/** Whether the solvable is in the installed repo. */
auto installed() const -> bool;

private:

const ::Solvable* m_solvable = nullptr;
Expand Down
10 changes: 5 additions & 5 deletions libmamba/src/solv-cpp/solver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,11 @@ namespace mamba::solv
return m_solver.get();
}

auto ObjSolver::raw() const -> const ::Solver*
{
return m_solver.get();
}

void ObjSolver::set_flag(SolverFlag flag, bool value)
{
::solver_set_flag(raw(), flag, value);
Expand All @@ -176,11 +181,6 @@ namespace mamba::solv
return val != 0;
}

auto ObjSolver::raw() const -> const ::Solver*
{
return m_solver.get();
}

auto ObjSolver::solve(const ObjPool& /* pool */, const ObjQueue& jobs) -> bool
{
// pool is captured inside solver so we take it as a parameter to be explicit.
Expand Down
6 changes: 3 additions & 3 deletions libmamba/src/solv-cpp/solver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ namespace mamba::solv
ObjSolver(const ObjPool& pool);
~ObjSolver();

auto raw() -> ::Solver*;
auto raw() const -> const ::Solver*;
[[nodiscard]] auto raw() -> ::Solver*;
[[nodiscard]] auto raw() const -> const ::Solver*;

void set_flag(SolverFlag flag, bool value);
[[nodiscard]] auto get_flag(SolverFlag flag) const -> bool;
Expand Down Expand Up @@ -83,7 +83,7 @@ namespace mamba::solv

std::unique_ptr<::Solver, ObjSolver::SolverDeleter> m_solver = nullptr;

auto next_problem(ProblemId id = 0) const -> ProblemId;
[[nodiscard]] auto next_problem(ProblemId id = 0) const -> ProblemId;
};

/*********************************
Expand Down
160 changes: 160 additions & 0 deletions libmamba/src/solv-cpp/transaction.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
// Copyright (c) 2023, QuantStack and Mamba Contributors
//
// Distributed under the terms of the BSD 3-Clause License.
//
// The full license is in the file LICENSE, distributed with this software.

#include <cassert>

#include <solv/solver.h>
#include <solv/transaction.h>

#include "solv-cpp/pool.hpp"
#include "solv-cpp/solver.hpp"
#include "solv-cpp/transaction.hpp"

namespace mamba::solv
{
void ObjTransaction::TransactionDeleter::operator()(::Transaction* ptr)
{
::transaction_free(ptr);
}

ObjTransaction::ObjTransaction(const ObjPool& pool)
: ObjTransaction(::transaction_create(const_cast<::Pool*>(pool.raw())))
{
}

ObjTransaction::ObjTransaction(::Transaction* ptr) noexcept
: m_transaction(ptr)
{
}

ObjTransaction::ObjTransaction(const ObjTransaction& other)
: ObjTransaction(::transaction_create_clone(const_cast<::Transaction*>(other.raw())))
{
}

ObjTransaction::~ObjTransaction() = default;
AntoinePrv marked this conversation as resolved.
Show resolved Hide resolved

auto ObjTransaction::operator=(const ObjTransaction& other) -> ObjTransaction&
{
*this = ObjTransaction(other);
return *this;
}

auto ObjTransaction::from_solvables(const ObjPool& pool, const ObjQueue& solvables)
-> ObjTransaction
{
return ObjTransaction{ ::transaction_create_decisionq(
const_cast<::Pool*>(pool.raw()),
const_cast<::Queue*>(solvables.raw()),
nullptr
) };
}
namespace
{
void
assert_same_pool([[maybe_unused]] const ObjPool& pool, [[maybe_unused]] const ObjTransaction& trans)
{
assert(pool.raw() == trans.raw()->pool);
}
}

auto ObjTransaction::from_solver(const ObjPool& pool, const ObjSolver& solver) -> ObjTransaction
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to force / be sure the user instantiated a pool before calling this method, and the pool he's using matches the one form the solver? Or is it just a sanity check?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's both? The libsolv type captures the pool by pointer so we make sure it cannot be used without the pool by asking to pass it as an argument (note the destructor does not need the pool).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You cannot create this type without a Pool, whatever constructor function would use the pool through a capture.

{
auto trans = ObjTransaction{ ::solver_create_transaction(const_cast<::Solver*>(solver.raw())
) };
assert_same_pool(pool, trans);
return trans;
}

auto ObjTransaction::raw() -> ::Transaction*
{
return m_transaction.get();
}

auto ObjTransaction::raw() const -> const ::Transaction*
{
return m_transaction.get();
}

auto ObjTransaction::empty() const -> bool
{
return raw()->steps.count <= 0;
}

auto ObjTransaction::size() const -> std::size_t
{
assert(raw()->steps.count);
return static_cast<std::size_t>(raw()->steps.count);
}

auto ObjTransaction::steps() const -> ObjQueue
{
ObjQueue out = {};
for_each_step_id([&](auto id) { out.push_back(id); });
return out;
}

auto ObjTransaction::step_type(const ObjPool& pool, SolvableId step, TransactionMode mode) const
-> TransactionStepType
AntoinePrv marked this conversation as resolved.
Show resolved Hide resolved
{
assert_same_pool(pool, *this);
return ::transaction_type(const_cast<::Transaction*>(raw()), step, mode);
}

auto ObjTransaction::step_newer(const ObjPool& pool, SolvableId step) const
-> std::optional<SolvableId>
{
assert_same_pool(pool, *this);
if (const auto solvable = pool.get_solvable(step); solvable && solvable->installed())
{
if (auto id = ::transaction_obs_pkg(const_cast<::Transaction*>(raw()), step); id != 0)
{
return { id };
}
}
return std::nullopt;
}

auto ObjTransaction::step_olders(const ObjPool& pool, SolvableId step) const -> ObjQueue
{
assert_same_pool(pool, *this);
auto out = ObjQueue{};
if (const auto solvable = pool.get_solvable(step); solvable && !solvable->installed())
{
::transaction_all_obs_pkgs(const_cast<::Transaction*>(raw()), step, out.raw());
}
return out;
}

void ObjTransaction::order(const ObjPool& pool, TransactionOrderFlag flag)
{
assert_same_pool(pool, *this);
::transaction_order(raw(), flag);
}

auto ObjTransaction::classify(const ObjPool& pool, TransactionMode mode) const -> ObjQueue
{
assert_same_pool(pool, *this);
auto out = ObjQueue{};
::transaction_classify(const_cast<::Transaction*>(raw()), mode, out.raw());
return out;
}

auto ObjTransaction::classify_pkgs(
const ObjPool& pool,
TransactionStepType type,
StringId from,
StringId to,
TransactionMode mode
) const -> ObjQueue
{
assert_same_pool(pool, *this);
auto out = ObjQueue{};
::transaction_classify_pkgs(const_cast<::Transaction*>(raw()), mode, type, from, to, out.raw());
return out;
}

}
Loading