#pragma once
#include "density_state.h"
#include "gds_object_manager.h"
#include "graph/graph.h"
namespace lbug {
namespace storage {
class MemoryManager;
}
namespace processor {
struct ExecutionContext;
}
namespace function {
class ParentList {
public:
void setNbrInfo(common::nodeID_t nodeID_, common::relID_t edgeID_, bool isFwd_) {
nodeID = nodeID_;
edgeID = edgeID_;
isFwd = isFwd_;
}
common::nodeID_t getNodeID() const { return nodeID; }
common::relID_t getEdgeID() const { return edgeID; }
bool isFwdEdge() const { return isFwd; }
void setNextPtr(ParentList* ptr) { next.store(ptr, std::memory_order_relaxed); }
ParentList* getNextPtr() { return next.load(std::memory_order_relaxed); }
void setIter(uint16_t iter_) { iter = iter_; }
uint16_t getIter() const { return iter; }
void setCost(double cost_) { cost = cost_; }
double getCost() const { return cost; }
private:
common::nodeID_t nodeID;
common::relID_t edgeID;
bool isFwd = true;
uint16_t iter = UINT16_MAX;
double cost = std::numeric_limits<double>::max();
std::atomic<ParentList*> next;
};
class BaseBFSGraph {
friend class BFSGraphManager;
public:
explicit BaseBFSGraph(storage::MemoryManager* mm) : mm{mm} {}
virtual ~BaseBFSGraph() = default;
ObjectBlock<ParentList>* addNewBlock();
virtual void pinTableID(common::table_id_t tableID) = 0;
virtual void addParent(uint16_t iter, common::nodeID_t boundNodeID, common::relID_t edgeID,
common::nodeID_t nbrNodeID, bool fwdEdge, ObjectBlock<ParentList>* block) = 0;
virtual void addSingleParent(uint16_t iter, common::nodeID_t boundNodeID,
common::relID_t edgeID, common::nodeID_t nbrNodeID, bool fwdEdge,
ObjectBlock<ParentList>* block) = 0;
virtual bool tryAddParentWithWeight(common::nodeID_t boundNodeID, common::relID_t edgeID,
common::nodeID_t nbrNodeID, bool fwdEdge, double weight,
ObjectBlock<ParentList>* block) = 0;
virtual bool tryAddSingleParentWithWeight(common::nodeID_t boundNodeID, common::relID_t edgeID,
common::nodeID_t nbrNodeID, bool fwdEdge, double weight,
ObjectBlock<ParentList>* block) = 0;
virtual ParentList* getParentListHead(common::offset_t offset) = 0;
virtual ParentList* getParentListHead(common::nodeID_t nodeID) = 0;
virtual void setParentList(common::offset_t offset, ParentList* parentList) = 0;
template<class TARGET>
TARGET& cast() {
return common::dynamic_cast_checked<TARGET&>(*this);
}
protected:
std::mutex mtx;
storage::MemoryManager* mm;
std::vector<std::unique_ptr<ObjectBlock<ParentList>>> blocks;
};
class DenseBFSGraph : public BaseBFSGraph {
friend class BFSGraphManager;
friend class BFSGraphInitVertexCompute;
public:
DenseBFSGraph(storage::MemoryManager* mm, common::table_id_map_t<common::offset_t> maxOffsetMap)
: BaseBFSGraph{mm}, maxOffsetMap{std::move(maxOffsetMap)} {}
void init(processor::ExecutionContext* context, graph::Graph* graph);
void pinTableID(common::table_id_t tableID) override;
void addParent(uint16_t iter, common::nodeID_t boundNodeID, common::relID_t edgeID,
common::nodeID_t nbrNodeID, bool fwdEdge, ObjectBlock<ParentList>* block) override;
void addSingleParent(uint16_t iter, common::nodeID_t boundNodeID, common::relID_t edgeID,
common::nodeID_t nbrNodeID, bool fwdEdge, ObjectBlock<ParentList>* block) override;
bool tryAddParentWithWeight(common::nodeID_t boundNodeID, common::relID_t edgeID,
common::nodeID_t nbrNodeID, bool fwdEdge, double weight,
ObjectBlock<ParentList>* block) override;
bool tryAddSingleParentWithWeight(common::nodeID_t boundNodeID, common::relID_t edgeID,
common::nodeID_t nbrNodeID, bool fwdEdge, double weight,
ObjectBlock<ParentList>* block) override;
ParentList* getParentListHead(common::offset_t offset) override;
ParentList* getParentListHead(common::nodeID_t nodeID) override;
void setParentList(common::offset_t offset, ParentList* parentList) override;
private:
common::table_id_map_t<common::offset_t> maxOffsetMap;
GDSDenseObjectManager<std::atomic<ParentList*>> denseObjects;
std::atomic<ParentList*>* curData = nullptr;
};
class SparseBFSGraph : public BaseBFSGraph {
friend class BFSGraphManager;
public:
explicit SparseBFSGraph(storage::MemoryManager* mm,
common::table_id_map_t<common::offset_t> maxOffsetMap)
: BaseBFSGraph{mm}, sparseObjects{maxOffsetMap} {}
void pinTableID(common::table_id_t tableID) override;
void addParent(uint16_t iter, common::nodeID_t boundNodeID, common::relID_t edgeID,
common::nodeID_t nbrNodeID, bool fwdEdge, ObjectBlock<ParentList>* block) override;
void addSingleParent(uint16_t iter, common::nodeID_t boundNodeID, common::relID_t edgeID,
common::nodeID_t nbrNodeID, bool fwdEdge, ObjectBlock<ParentList>* block) override;
bool tryAddParentWithWeight(common::nodeID_t boundNodeID, common::relID_t edgeID,
common::nodeID_t nbrNodeID, bool fwdEdge, double weight,
ObjectBlock<ParentList>* block) override;
bool tryAddSingleParentWithWeight(common::nodeID_t boundNodeID, common::relID_t edgeID,
common::nodeID_t nbrNodeID, bool fwdEdge, double weight,
ObjectBlock<ParentList>* block) override;
ParentList* getParentListHead(common::offset_t offset) override;
ParentList* getParentListHead(common::nodeID_t nodeID) override;
void setParentList(common::offset_t offset, ParentList* parentList) override;
const std::unordered_map<common::offset_t, ParentList*>& getCurrentData() const {
return *curData;
}
private:
GDSSpareObjectManager<ParentList*> sparseObjects;
std::unordered_map<common::offset_t, ParentList*>* curData = nullptr;
};
class BFSGraphManager {
public:
BFSGraphManager(common::table_id_map_t<common::offset_t> maxOffsetMap,
storage::MemoryManager* mm);
BaseBFSGraph* getCurrentGraph() const {
DASSERT(curGraph);
return curGraph;
}
void switchToDense(processor::ExecutionContext* context, graph::Graph* graph);
private:
GDSDensityState state = GDSDensityState::SPARSE;
std::unique_ptr<DenseBFSGraph> denseBFSGraph;
std::unique_ptr<SparseBFSGraph> sparseBFSGraph;
BaseBFSGraph* curGraph = nullptr;
};
} }