Skip to content

Commit

Permalink
Merge pull request #86 from Esri/#58
Browse files Browse the repository at this point in the history
  • Loading branch information
mistafunk authored Mar 24, 2018
2 parents a6a460c + 62b4dc2 commit e864b79
Show file tree
Hide file tree
Showing 13 changed files with 266 additions and 116 deletions.
1 change: 1 addition & 0 deletions src/palladio/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ add_library(${PROJECT_NAME} SHARED
ShapeGenerator.cpp
NodeParameter.cpp
PRTContext.cpp
ResolveMapCache.cpp
SOPAssign.cpp
SOPGenerate.cpp
PrimitivePartition.cpp
Expand Down
9 changes: 5 additions & 4 deletions src/palladio/ModelConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,8 @@ GA_Offset createPrimitives(GU_Detail* mDetail, GenerateNodeParams::GroupCreation
} // namespace ModelConversion


ModelConverter::ModelConverter(GU_Detail* detail, GenerateNodeParams::GroupCreation gc, UT_AutoInterrupt* autoInterrupt)
: mDetail(detail), mGroupCreation(gc), mAutoInterrupt(autoInterrupt) { }
ModelConverter::ModelConverter(GU_Detail* detail, GenerateNodeParams::GroupCreation gc, std::vector<prt::Status>& statuses, UT_AutoInterrupt* autoInterrupt)
: mDetail(detail), mGroupCreation(gc), mStatuses(statuses), mAutoInterrupt(autoInterrupt) { }

void ModelConverter::add(const wchar_t* name,
const double* vtx, size_t vtxSize,
Expand Down Expand Up @@ -254,7 +254,8 @@ void ModelConverter::add(const wchar_t* name,
}

prt::Status ModelConverter::generateError(size_t isIndex, prt::Status status, const wchar_t* message) {
LOG_ERR << message;
LOG_WRN << message; // generate error for one shape is not yet a reason to abort cooking
mStatuses[isIndex] = status;
return prt::STATUS_OK;
}

Expand All @@ -264,7 +265,7 @@ prt::Status ModelConverter::assetError(size_t isIndex, prt::CGAErrorLevel level,
}

prt::Status ModelConverter::cgaError(size_t isIndex, int32_t shapeID, prt::CGAErrorLevel level, int32_t methodId, int32_t pc, const wchar_t* message) {
LOG_ERR << message;
LOG_WRN << message;
return prt::STATUS_OK;
}

Expand Down
3 changes: 2 additions & 1 deletion src/palladio/ModelConverter.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ void setUVs(

class ModelConverter : public HoudiniCallbacks {
public:
explicit ModelConverter(GU_Detail* gdp, GenerateNodeParams::GroupCreation gc, UT_AutoInterrupt* autoInterrupt = nullptr);
explicit ModelConverter(GU_Detail* gdp, GenerateNodeParams::GroupCreation gc, std::vector<prt::Status>& statuses, UT_AutoInterrupt* autoInterrupt = nullptr);

protected:
void add(
Expand Down Expand Up @@ -104,6 +104,7 @@ class ModelConverter : public HoudiniCallbacks {
private:
GU_Detail* mDetail;
GenerateNodeParams::GroupCreation mGroupCreation;
std::vector<prt::Status>& mStatuses;
UT_AutoInterrupt* mAutoInterrupt;
std::map<int32_t, AttributeMapBuilderUPtr> mShapeAttributeBuilders;
};
Expand Down
6 changes: 0 additions & 6 deletions src/palladio/NodeParameter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,6 @@ int updateRPK(void* data, int, fpreal32 time, const PRM_Template*) {
node->evalString(utNextRPKStr, AssignNodeParams::RPK.getToken(), 0, time);
const boost::filesystem::path nextRPK(utNextRPKStr.toStdString());

// -- early exit if rpk path is not valid
if (!boost::filesystem::exists(nextRPK)) {
LOG_WRN << "non-existent rpk";
return NOT_CHANGED;
}

const ResolveMapUPtr& resolveMap = prtCtx->getResolveMap(nextRPK);
if (!resolveMap ) {
LOG_WRN << "invalid resolve map";
Expand Down
24 changes: 13 additions & 11 deletions src/palladio/NodeParameter.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,17 @@ auto getRPK = [](const OP_Node* node, fpreal t) -> boost::filesystem::path {
};


// -- RPK RELOADER
static PRM_Name RPK_RELOAD("rpkReload", "Reload Rule Package");


// -- RULE FILE (cgb)
static PRM_Name RULE_FILE("ruleFile", "Rule File");
const std::string RULE_FILE_HELP = "Sets value for primitive attribute '" + PLD_RULE_FILE.toStdString() + "'";

void buildRuleFileMenu(void *data, PRM_Name *theMenu, int theMaxSize, const PRM_SpareData *, const PRM_Parm *);

static PRM_ChoiceList ruleFileMenu(static_cast<PRM_ChoiceListType>(PRM_CHOICELIST_EXCLUSIVE | PRM_CHOICELIST_REPLACE),
&buildRuleFileMenu);
static PRM_ChoiceList ruleFileMenu(static_cast<PRM_ChoiceListType>(PRM_CHOICELIST_REPLACE), &buildRuleFileMenu);

auto getRuleFile = [](const OP_Node* node, fpreal t) -> std::wstring {
UT_String s;
Expand All @@ -91,8 +94,7 @@ const std::string STYLE_HELP = "Sets value for primitive attribute '" + PLD_STYL

void buildStyleMenu(void *data, PRM_Name *theMenu, int theMaxSize, const PRM_SpareData *, const PRM_Parm *);

static PRM_ChoiceList styleMenu(static_cast<PRM_ChoiceListType>(PRM_CHOICELIST_EXCLUSIVE | PRM_CHOICELIST_REPLACE),
&buildStyleMenu);
static PRM_ChoiceList styleMenu(static_cast<PRM_ChoiceListType>(PRM_CHOICELIST_REPLACE), &buildStyleMenu);

auto getStyle = [](const OP_Node* node, fpreal t) -> std::wstring {
UT_String s;
Expand All @@ -112,8 +114,7 @@ const std::string START_RULE_HELP = "Sets value for primitive attribute '" + PLD

void buildStartRuleMenu(void *data, PRM_Name *theMenu, int theMaxSize, const PRM_SpareData *, const PRM_Parm *);

static PRM_ChoiceList startRuleMenu(static_cast<PRM_ChoiceListType>(PRM_CHOICELIST_EXCLUSIVE | PRM_CHOICELIST_REPLACE),
&buildStartRuleMenu);
static PRM_ChoiceList startRuleMenu(static_cast<PRM_ChoiceListType>(PRM_CHOICELIST_REPLACE), &buildStartRuleMenu);

auto getStartRule = [](const OP_Node* node, fpreal t) -> std::wstring {
UT_String s;
Expand All @@ -129,11 +130,12 @@ auto setStartRule = [](OP_Node* node, const std::wstring& s, fpreal t) {

// -- ASSIGN NODE PARAMS
static PRM_Template PARAM_TEMPLATES[] = {
PRM_Template(PRM_STRING, 1, &PRIM_CLS, &PRIM_CLS_DEFAULT, nullptr, nullptr, PRM_Callback(), nullptr, 1, PRIM_CLS_HELP.c_str()),
PRM_Template(PRM_FILE, 1, &RPK, &RPK_DEFAULT, nullptr, nullptr, rpkCallback, &PRM_SpareData::fileChooserModeRead, 1, RPK_HELP.c_str()),
PRM_Template(PRM_STRING, 1, &RULE_FILE, PRMoneDefaults, &ruleFileMenu, nullptr, PRM_Callback(), nullptr, 1, RULE_FILE_HELP.c_str()),
PRM_Template(PRM_STRING, 1, &STYLE, PRMoneDefaults, &styleMenu, nullptr, PRM_Callback(), nullptr, 1, STYLE_HELP.c_str()),
PRM_Template(PRM_STRING, 1, &START_RULE, PRMoneDefaults, &startRuleMenu, nullptr, PRM_Callback(), nullptr, 1, START_RULE_HELP.c_str()),
PRM_Template(PRM_STRING, 1, &PRIM_CLS, &PRIM_CLS_DEFAULT, nullptr, nullptr, PRM_Callback(), nullptr, 1, PRIM_CLS_HELP.c_str()),
PRM_Template(PRM_FILE, 1, &RPK, &RPK_DEFAULT, nullptr, nullptr, rpkCallback, &PRM_SpareData::fileChooserModeRead, 1, RPK_HELP.c_str()),
PRM_Template(PRM_CALLBACK, 1, &RPK_RELOAD, PRMoneDefaults, nullptr, nullptr, rpkCallback),
PRM_Template(PRM_STRING, 1, &RULE_FILE, PRMoneDefaults, &ruleFileMenu, nullptr, PRM_Callback(), nullptr, 1, RULE_FILE_HELP.c_str()),
PRM_Template(PRM_STRING, 1, &STYLE, PRMoneDefaults, &styleMenu, nullptr, PRM_Callback(), nullptr, 1, STYLE_HELP.c_str()),
PRM_Template(PRM_STRING, 1, &START_RULE, PRMoneDefaults, &startRuleMenu, nullptr, PRM_Callback(), nullptr, 1, START_RULE_HELP.c_str()),
PRM_Template()
};

Expand Down
59 changes: 39 additions & 20 deletions src/palladio/PRTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,13 @@
*/

#include "PRTContext.h"
#include "PalladioMain.h"
#include "LogHandler.h"
#include "SOPAssign.h"

#include "OP/OP_Node.h"
#include "OP/OP_Director.h"
#include "OP/OP_Network.h"

#include <thread>

Expand Down Expand Up @@ -92,15 +98,35 @@ uint32_t getNumCores() {
return n > 0 ? n : 1;
}

/**
* schedule recook of all assign nodes with matching rpk
*/
void scheduleRecook(const boost::filesystem::path& rpk) {
auto visit = [](OP_Node& n, void* data) -> bool {
if (n.getOperator()->getName().equal(OP_PLD_ASSIGN)) {
auto rpk = reinterpret_cast<boost::filesystem::path*>(data);
SOPAssign& sa = static_cast<SOPAssign&>(n);
if (sa.getRPK() == *rpk) {
LOG_DBG << "forcing recook of: " << n.getName() << ", " << n.getOpType() << ", " << n.getOperator()->getName();
sa.forceRecook();
}
}
return false;
};

OP_Network* objMgr = OPgetDirector()->getManager("obj");
objMgr->traverseChildren(visit, const_cast<void*>(reinterpret_cast<const void*>(&rpk)), true);
}

} // namespace


PRTContext::PRTContext(const std::vector<boost::filesystem::path>& addExtDirs)
: mLogHandler(new logging::LogHandler(PLD_LOG_PREFIX)),
mLicHandle{nullptr},
mPRTCache{prt::CacheObject::create(prt::CacheObject::CACHE_TYPE_DEFAULT)},
mRPKUnpackPath{boost::filesystem::temp_directory_path() / (PLD_TMP_PREFIX + std::to_string(::getpid()))},
mCores{getNumCores()}
mCores{getNumCores()},
mResolveMapCache{new ResolveMapCache(boost::filesystem::temp_directory_path() / (PLD_TMP_PREFIX + std::to_string(::getpid())))}
{
const prt::LogLevel logLevel = getLogLevel();
prt::setLogLevel(logLevel);
Expand Down Expand Up @@ -146,30 +172,23 @@ PRTContext::PRTContext(const std::vector<boost::filesystem::path>& addExtDirs)
}

PRTContext::~PRTContext() {
mPRTCache.reset();
mResolveMapCache.reset();
LOG_INF << "Released RPK Cache";

mPRTCache.reset(); // calling reset manually to ensure order
LOG_INF << "Released PRT cache";

mLicHandle.reset();
mLicHandle.reset(); // same here
LOG_INF << "Shutdown PRT & returned license";

boost::filesystem::remove_all(mRPKUnpackPath);
LOG_INF << "Removed RPK unpack directory";

prt::removeLogHandler(mLogHandler.get());
}

const ResolveMapUPtr& PRTContext::getResolveMap(const boost::filesystem::path& rpk) {
if (rpk.empty())
return mResolveMapNone;

auto it = mResolveMapCache.find(rpk);
if (it == mResolveMapCache.end()) {
prt::Status status = prt::STATUS_UNSPECIFIED_ERROR;
const auto rpkURI = toFileURI(rpk);
ResolveMapUPtr rm(prt::createResolveMap(rpkURI.c_str(), mRPKUnpackPath.wstring().c_str(), &status));
if (status != prt::STATUS_OK)
return mResolveMapNone;
it = mResolveMapCache.emplace(rpk, std::move(rm)).first;
}
return it->second;
auto lookupResult = mResolveMapCache->get(rpk);
if (lookupResult.second == ResolveMapCache::CacheStatus::MISS) {
mPRTCache->flushAll();
scheduleRecook(rpk);
}
return lookupResult.first;
}
7 changes: 2 additions & 5 deletions src/palladio/PRTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#pragma once

#include "ResolveMapCache.h"
#include "Utils.h"

#include "prt/Object.h"
Expand Down Expand Up @@ -47,12 +48,8 @@ struct PRTContext final {
logging::LogHandlerPtr mLogHandler;
ObjectUPtr mLicHandle;
CacheObjectUPtr mPRTCache;
boost::filesystem::path mRPKUnpackPath;
const uint32_t mCores;

using ResolveMapCache = std::map<boost::filesystem::path, ResolveMapUPtr>;
ResolveMapCache mResolveMapCache;
const ResolveMapUPtr mResolveMapNone;
ResolveMapCacheUPtr mResolveMapCache;
};

using PRTContextUPtr = std::unique_ptr<PRTContext>;
8 changes: 5 additions & 3 deletions src/palladio/PalladioMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@
* limitations under the License.
*/

#include "PalladioMain.h"

#include "PRTContext.h"
#include "SOPAssign.h"
#include "SOPGenerate.h"
#include "PRTContext.h"
#include "NodeParameter.h"

#include "OP/OP_OperatorTable.h"
Expand Down Expand Up @@ -47,15 +49,15 @@ void newSopOperator(OP_OperatorTable *table) {
auto createSOPAssign = [](OP_Network *net, const char *name, OP_Operator *op) -> OP_Node* {
return new SOPAssign(prtCtx, net, name, op);
};
table->addOperator(new OP_Operator("pldAssign", "pldAssign", createSOPAssign,
table->addOperator(new OP_Operator(OP_PLD_ASSIGN, OP_PLD_ASSIGN, createSOPAssign,
AssignNodeParams::PARAM_TEMPLATES, 1, 1, nullptr, OP_FLAG_GENERATOR
));

// instantiate generator sop
auto createSOPGenerate = [](OP_Network *net, const char *name, OP_Operator *op) -> OP_Node* {
return new SOPGenerate(prtCtx, net, name, op);
};
table->addOperator(new OP_Operator("pldGenerate", "pldGenerate", createSOPGenerate,
table->addOperator(new OP_Operator(OP_PLD_GENERATE, OP_PLD_GENERATE, createSOPGenerate,
GenerateNodeParams::PARAM_TEMPLATES, 1, 1, nullptr, OP_FLAG_GENERATOR
));
}
4 changes: 4 additions & 0 deletions src/palladio/PalladioMain.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#pragma once

constexpr const char* OP_PLD_ASSIGN = "pldAssign";
constexpr const char* OP_PLD_GENERATE = "pldGenerate";
73 changes: 73 additions & 0 deletions src/palladio/ResolveMapCache.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//
// Created by shaegler on 3/3/18.
//

#include "ResolveMapCache.h"
#include "LogHandler.h"


namespace {

const ResolveMapUPtr RESOLVE_MAP_NONE;
const timespec NO_MODIFICATION_TIME{0, 0};

timespec getFileModificationTime(const boost::filesystem::path& p) {
struct stat result;
if (stat(p.c_str(), &result) == 0) {
return result.st_mtim;
}
else
return NO_MODIFICATION_TIME;
}

} // namespace


ResolveMapCache::~ResolveMapCache() {
boost::filesystem::remove_all(mRPKUnpackPath);
LOG_INF << "Removed RPK unpack directory";
}

ResolveMapCache::LookupResult ResolveMapCache::get(const boost::filesystem::path& rpk) {
if (rpk.empty())
return { RESOLVE_MAP_NONE, CacheStatus::MISS };

if (!boost::filesystem::exists(rpk))
return { RESOLVE_MAP_NONE, CacheStatus::MISS };

const auto timeStamp = getFileModificationTime(rpk);
LOG_DBG << "rpk: current timestamp: " << timeStamp.tv_sec << "s " << timeStamp.tv_nsec << "ns";

CacheStatus cs = CacheStatus::HIT;
auto it = mCache.find(rpk);
if (it != mCache.end()) {
LOG_DBG << "rpk: cache timestamp: " << it->second.mTimeStamp.tv_sec << "s " << it->second.mTimeStamp.tv_nsec << "ns";
if (it->second.mTimeStamp.tv_sec != timeStamp.tv_sec || it->second.mTimeStamp.tv_nsec != timeStamp.tv_nsec) {
mCache.erase(it);
const auto cnt = boost::filesystem::remove_all(mRPKUnpackPath / rpk.leaf());
LOG_INF << "RPK change detected, forcing reload and clearing cache for " << rpk << " (removed " << cnt << " files)";
cs = CacheStatus::MISS;
}
}
else
cs = CacheStatus::MISS;

if (cs == CacheStatus::MISS) {
const auto rpkURI = toFileURI(rpk);

ResolveMapCacheEntry rmce;
rmce.mTimeStamp = timeStamp;

prt::Status status = prt::STATUS_UNSPECIFIED_ERROR;
rmce.mResolveMap.reset(prt::createResolveMap(rpkURI.c_str(), mRPKUnpackPath.wstring().c_str(), &status));
if (status != prt::STATUS_OK)
return { RESOLVE_MAP_NONE, CacheStatus::MISS };

it = mCache.emplace(rpk, std::move(rmce)).first;
LOG_INF << "Upacked RPK " << rpk << " to " << mRPKUnpackPath;
}

return { it->second.mResolveMap, cs };

}

37 changes: 37 additions & 0 deletions src/palladio/ResolveMapCache.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#pragma once

#include "Utils.h"

#include "boost/filesystem.hpp"

#include <sys/types.h>
#include <sys/stat.h>
#ifndef WIN32
# include <unistd.h>
#endif


class ResolveMapCache {
public:
ResolveMapCache(const boost::filesystem::path& unpackPath) : mRPKUnpackPath{unpackPath} { }
ResolveMapCache(const ResolveMapCache&) = delete;
ResolveMapCache(ResolveMapCache&&) = delete;
ResolveMapCache& operator=(ResolveMapCache&) = delete;
~ResolveMapCache();

enum class CacheStatus { HIT, MISS };
using LookupResult = std::pair<const ResolveMapUPtr&, CacheStatus>;
LookupResult get(const boost::filesystem::path& rpk);

private:
struct ResolveMapCacheEntry {
ResolveMapUPtr mResolveMap;
timespec mTimeStamp;
};
using Cache = std::map<boost::filesystem::path, ResolveMapCacheEntry>;
Cache mCache;

const boost::filesystem::path mRPKUnpackPath;
};

using ResolveMapCacheUPtr = std::unique_ptr<ResolveMapCache>;
1 change: 1 addition & 0 deletions src/palladio/SOPAssign.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class SOPAssign : public SOP_Node {
~SOPAssign() override = default;

const PRTContextUPtr& getPRTCtx() const { return mPRTCtx; }
const boost::filesystem::path& getRPK() const { return mShapeConverter->mRPK; }

void opChanged(OP_EventType reason, void* data = nullptr) override;

Expand Down
Loading

0 comments on commit e864b79

Please sign in to comment.