diff options
author | randomdan <randomdan@localhost> | 2014-03-10 20:24:23 +0000 |
---|---|---|
committer | randomdan <randomdan@localhost> | 2014-03-10 20:24:23 +0000 |
commit | a5d682ffb36c05cd12fd6064ec380c8608ebf75b (patch) | |
tree | 114a2d8c8b1534f05fe10d002ff031f590e4f3f8 | |
parent | Adds native support for time_duration as a variable type (diff) | |
download | project2-a5d682ffb36c05cd12fd6064ec380c8608ebf75b.tar.bz2 project2-a5d682ffb36c05cd12fd6064ec380c8608ebf75b.tar.xz project2-a5d682ffb36c05cd12fd6064ec380c8608ebf75b.zip |
Add basic workings of the Ice client and daemon modules - will probably change, but basic functionality works
43 files changed, 1900 insertions, 1 deletions
diff --git a/project2/Jamfile.jam b/project2/Jamfile.jam index c432bfa..2aca8d7 100644 --- a/project2/Jamfile.jam +++ b/project2/Jamfile.jam @@ -13,6 +13,7 @@ alias p2parts : : : : <library>mail//p2mail <library>regex//p2regex <library>xml//p2xml + <library>ice//p2iceclient <library>json//p2json <library>compression//p2compression <library>streams//p2streams @@ -21,6 +22,7 @@ alias p2parts : : : : ; alias p2daemonparts : : : : + <library>ice//p2icedaemon ; build-project console ; diff --git a/project2/basics/preload.cpp b/project2/basics/preload.cpp index 104dc22..03f275b 100644 --- a/project2/basics/preload.cpp +++ b/project2/basics/preload.cpp @@ -19,7 +19,7 @@ class Preload { { const auto beforeOpts = InstanceSet<Options>::GetAll(); - void * handle = dlopen(librarypath, RTLD_NOW); + void * handle = dlopen(librarypath, RTLD_GLOBAL | RTLD_NOW); if (handle) { Logger()->messagebf(LOG_DEBUG, "Loaded library '%s'", librarypath.as<std::string>()); } diff --git a/project2/common/commonObjects.cpp b/project2/common/commonObjects.cpp index a25bb9f..cb973cc 100644 --- a/project2/common/commonObjects.cpp +++ b/project2/common/commonObjects.cpp @@ -1,5 +1,6 @@ #include <pch.hpp> #include "commonObjects.h" +#include "logger.h" #include "safeMapFind.h" #include "scriptLoader.h" diff --git a/project2/common/flatView.cpp b/project2/common/flatView.cpp new file mode 100644 index 0000000..05e8b09 --- /dev/null +++ b/project2/common/flatView.cpp @@ -0,0 +1,58 @@ +#include "pch.hpp" +#include "flatView.h" +#include "presenter.h" +#include "scopeObject.h" +#include "scriptLoader.h" +#include "scopeObject.h" +#include <boost/foreach.hpp> +#include <boost/bind.hpp> + +DECLARE_LOADER("flatview", FlatView); + +FlatView::FlatView(ScriptNodePtr p) : + SourceObject(p), + RowProcessor(p), + recordName(p, "recordname"), + required(p, "required", false) +{ + BOOST_FOREACH(ScriptNodePtr node, p->childrenIn("columns")) { + viewColumns.insert(Columns::value_type(node->get_name(), Variable(node))); + } +} + +FlatView::~FlatView() +{ +} + +void +FlatView::loadComplete(const CommonObjects * co) +{ + RowProcessor::loadComplete(co); +} + +void +FlatView::rowReady(const RowState * rs, const RowSetPresenter * presenter, ExecContext * ec, bool & rowsFound) const +{ + rowsFound = true; + presenter->addNewRow(recordName(ec)); + if (viewColumns.empty()) { + rs->foreachColumn(ec, boost::bind(&RowSetPresenter::addNamedValue, presenter, _2, _3)); + } + else { + BOOST_FOREACH(const Columns::value_type & col, viewColumns) { + presenter->addNamedValue(col.first, col.second(ec)); + } + } + presenter->finishRow(); +} + +void +FlatView::execute(const RowSetPresenter * p, ExecContext * ec) const +{ + bool rowsFound = false; + RowProcessor::execute(ec, boost::bind(&FlatView::rowReady, this, _1, p, ec, boost::ref(rowsFound))); + if (required(ec) && !rowsFound) { + throw EmptyRequiredRows(name); + } +} + diff --git a/project2/common/flatView.h b/project2/common/flatView.h new file mode 100644 index 0000000..5dc24dc --- /dev/null +++ b/project2/common/flatView.h @@ -0,0 +1,28 @@ +#ifndef FLATVIEW_H +#define FLATVIEW_H + +#include <boost/intrusive_ptr.hpp> +#include "rowProcessor.h" +#include "view.h" +#include "aggregate.h" + +/// Project2 component to create output based on a records in a flat row set +class FlatView : public SourceObject, public RowProcessor { + public: + FlatView(ScriptNodePtr); + virtual ~FlatView(); + + void loadComplete(const CommonObjects *); + void execute(const RowSetPresenter *, ExecContext *) const; + void rowReady(const RowState *, const RowSetPresenter *, ExecContext *, bool & found) const; + + const Variable recordName; + const Variable required; + + protected: + typedef std::map<Glib::ustring, Variable> Columns; + Columns viewColumns; +}; + +#endif + diff --git a/project2/ice/Jamfile.jam b/project2/ice/Jamfile.jam new file mode 100644 index 0000000..4ecca91 --- /dev/null +++ b/project2/ice/Jamfile.jam @@ -0,0 +1,69 @@ +alias glibmm : : : : + <cflags>"`pkg-config --cflags glibmm-2.4`" + <linkflags>"`pkg-config --libs glibmm-2.4`" + ; + +lib dl ; +lib Slice ; +lib Ice ; +lib IceUtil ; +lib pthread ; +lib boost_filesystem ; + +cpp-pch pch : pch.hpp : + <include>../../libmisc + <library>../lib//p2lib + <library>../common//p2common + <library>glibmm + ; + +lib p2iceclient : + pch iceDataSource.cpp iceClient.cpp buildClient.cpp slice2Task.cpp slice2Rows.cpp + : + <include>../../libmisc + <library>glibmm + <library>../common//p2common + <library>../lib//p2lib + <library>p2ice + <library>dl + <library>Ice + <library>Slice + <library>IceUtil + <library>boost_filesystem + <library>pthread + : : + <library>p2ice + ; + +lib p2icedaemon : + pch iceDaemon.cpp iceModule.cpp buildDaemon.cpp slice2Daemon.cpp slice2DaemonLoader.cpp slice2Presenter.cpp + : + <include>../../libmisc + <library>glibmm + <library>../common//p2common + <library>../lib//p2lib + <library>../daemon/lib//p2daemonlib + <library>p2ice + <library>dl + <library>Ice + <library>Slice + <library>IceUtil + <library>boost_filesystem + : : + <library>../daemon/lib//p2daemonlib + <library>p2ice + ; + +lib p2ice : + pch iceConvert.cpp iceCompile.cpp sliceCompile.cpp buildComms.cpp buildShared.cpp slice2Type.cpp + : + <include>../../libmisc + <library>glibmm + <library>../common//p2common + <library>../lib//p2lib + <library>dl + <library>Ice + <library>Slice + <library>IceUtil + <library>boost_filesystem + ; diff --git a/project2/ice/buildClient.cpp b/project2/ice/buildClient.cpp new file mode 100644 index 0000000..676af31 --- /dev/null +++ b/project2/ice/buildClient.cpp @@ -0,0 +1,33 @@ +#include <pch.hpp> +#include "buildClient.h" +#include "slice2Task.h" +#include "slice2Rows.h" + +BuildClient::BuildClient(const boost::filesystem::path & slice, const IceCompile::Deps & dep) : + SliceCompile(slice, dep) +{ +} + +void +BuildClient::Headers(FILE * out) const +{ + fprintf(out, "#include <iceTask.h>\n"); + fprintf(out, "#include <iceRows.h>\n"); +} + +void +BuildClient::Body(FILE * out, Slice::UnitPtr u) const +{ + Slice2Task taskBuilder(out); + Slice2Rows rowsBuilder(out); + u->visit(&taskBuilder, false); + u->visit(&rowsBuilder, false); +} + +boost::filesystem::path +BuildClient::OutputName(const std::string & type) const +{ + return slice.filename().replace_extension(".client" + type); +} + + diff --git a/project2/ice/buildClient.h b/project2/ice/buildClient.h new file mode 100644 index 0000000..a8c0b6c --- /dev/null +++ b/project2/ice/buildClient.h @@ -0,0 +1,19 @@ +#ifndef BUILDCLIENT_H +#define BUILDCLIENT_H + +#include "sliceCompile.h" +#include <string> + +class BuildClient : public SliceCompile { + public: + BuildClient(const boost::filesystem::path & slice, const IceCompile::Deps & dep); + + virtual void Headers(FILE *) const; + virtual void Body(FILE *, Slice::UnitPtr) const; + + boost::filesystem::path OutputName(const std::string & type) const; +}; + +#endif + + diff --git a/project2/ice/buildComms.cpp b/project2/ice/buildComms.cpp new file mode 100644 index 0000000..4add6c7 --- /dev/null +++ b/project2/ice/buildComms.cpp @@ -0,0 +1,32 @@ +#include <pch.hpp> +#include "buildComms.h" +#include <logger.h> +#include <misc.h> + +BuildComms::BuildComms(const boost::filesystem::path & slice) : + IceCompile(slice) +{ +} + +void +BuildComms::Build(const boost::filesystem::path & in, const boost::filesystem::path & out) const +{ + const auto slicecmd = stringbf("%s --output-dir %s %s", slice2cpp, out.parent_path(), in); + Logger()->messagebf(LOG_DEBUG, "%s: slice command: %s", __PRETTY_FUNCTION__, slicecmd); + if (system(slicecmd.c_str())) { + throw std::runtime_error("slice2cpp failed"); + } +} + +boost::filesystem::path +BuildComms::InputPath() const +{ + return slice; +} + +boost::filesystem::path +BuildComms::OutputName(const std::string & type) const +{ + return slice.filename().replace_extension(type); +} + diff --git a/project2/ice/buildComms.h b/project2/ice/buildComms.h new file mode 100644 index 0000000..31e7590 --- /dev/null +++ b/project2/ice/buildComms.h @@ -0,0 +1,17 @@ +#ifndef BUILDCOMMS_H +#define BUILDCOMMS_H + +#include "iceCompile.h" +#include <string> + +class BuildComms : public IceCompile { + public: + BuildComms(const boost::filesystem::path & slice); + + void Build(const boost::filesystem::path & in, const boost::filesystem::path & out) const; + boost::filesystem::path InputPath() const; + boost::filesystem::path OutputName(const std::string & type) const; +}; + +#endif + diff --git a/project2/ice/buildDaemon.cpp b/project2/ice/buildDaemon.cpp new file mode 100644 index 0000000..83976b0 --- /dev/null +++ b/project2/ice/buildDaemon.cpp @@ -0,0 +1,36 @@ +#include <pch.hpp> +#include "buildDaemon.h" +#include "slice2Presenter.h" +#include "slice2Daemon.h" +#include "slice2DaemonLoader.h" + +BuildDaemon::BuildDaemon(const boost::filesystem::path & slice, const IceCompile::Deps & dep) : + SliceCompile(slice, dep) +{ +} + +void +BuildDaemon::Headers(FILE * out) const +{ + fprintf(out, "#include <iceModule.h>\n"); +} + +void +BuildDaemon::Body(FILE * out, Slice::UnitPtr u) const +{ + Slice2Presenter presenterBuilder(out); + u->visit(&presenterBuilder, false); + + Slice2Daemon daemonBuilder(out); + u->visit(&daemonBuilder, false); + + Slice2DaemonLoader daemonLoaderBuilder(out); + u->visit(&daemonLoaderBuilder, false); +} + +boost::filesystem::path +BuildDaemon::OutputName(const std::string & type) const +{ + return slice.filename().replace_extension(".daemon" + type); +} + diff --git a/project2/ice/buildDaemon.h b/project2/ice/buildDaemon.h new file mode 100644 index 0000000..8c22ea6 --- /dev/null +++ b/project2/ice/buildDaemon.h @@ -0,0 +1,19 @@ +#ifndef BUILDDAEMON_H +#define BUILDDAEMON_H + +#include "sliceCompile.h" +#include <string> + +class BuildDaemon : public SliceCompile { + public: + BuildDaemon(const boost::filesystem::path & slice, const IceCompile::Deps & dep); + + virtual void Headers(FILE *) const; + virtual void Body(FILE *, Slice::UnitPtr) const; + + boost::filesystem::path OutputName(const std::string & type) const; +}; + +#endif + + diff --git a/project2/ice/buildShared.cpp b/project2/ice/buildShared.cpp new file mode 100644 index 0000000..61450c8 --- /dev/null +++ b/project2/ice/buildShared.cpp @@ -0,0 +1,30 @@ +#include <pch.hpp> +#include "buildShared.h" +#include "slice2Type.h" + +BuildShared::BuildShared(const boost::filesystem::path & slice, const IceCompile::Deps & dep) : + SliceCompile(slice, dep) +{ +} + +void +BuildShared::Headers(FILE * out) const +{ + fprintf(out, "#include <iceConvert.h>\n"); +} + +void +BuildShared::Body(FILE * out, Slice::UnitPtr u) const +{ + Slice2Type typeBuilder(out); + u->visit(&typeBuilder, false); +} + +boost::filesystem::path +BuildShared::OutputName(const std::string & type) const +{ + return slice.filename().replace_extension(".shared" + type); +} + + + diff --git a/project2/ice/buildShared.h b/project2/ice/buildShared.h new file mode 100644 index 0000000..cf0e5d5 --- /dev/null +++ b/project2/ice/buildShared.h @@ -0,0 +1,20 @@ +#ifndef BUILDSHARED_H +#define BUILDSHARED_H + +#include "sliceCompile.h" +#include <string> + +class BuildShared : public SliceCompile { + public: + BuildShared(const boost::filesystem::path & slice, const IceCompile::Deps & dep); + + virtual void Headers(FILE *) const; + virtual void Body(FILE *, Slice::UnitPtr) const; + + boost::filesystem::path OutputName(const std::string & type) const; +}; + +#endif + + + diff --git a/project2/ice/iceClient.cpp b/project2/ice/iceClient.cpp new file mode 100644 index 0000000..3045241 --- /dev/null +++ b/project2/ice/iceClient.cpp @@ -0,0 +1,8 @@ +#include <pch.hpp> +#include "iceClient.h" + +IceClientBase::IceClientBase(ScriptNodePtr p) : + dataSource(p, "datasource"), + objectId(p, "objectId") +{ +} diff --git a/project2/ice/iceClient.h b/project2/ice/iceClient.h new file mode 100644 index 0000000..93042fd --- /dev/null +++ b/project2/ice/iceClient.h @@ -0,0 +1,38 @@ +#ifndef ICECLIENT_H +#define ICECLIENT_H + +#include <variables.h> +#include <commonObjects.h> +#include <Ice/Ice.h> +#include "iceDataSource.h" + +class IceClientBase { + public: + IceClientBase(ScriptNodePtr p); + + protected: + const Variable dataSource; + const Variable objectId; + const IceDataSource * ice; +}; + +template <typename Interface> +class IceClient : public IceClientBase { + public: + IceClient(ScriptNodePtr p) : IceClientBase(p) { } + + void loadComplete(const CommonObjects * co) + { + ice = co->dataSource<IceDataSource>(dataSource(NULL)); + service = ice->GetProxy<Interface>(objectId(NULL), NULL); + if (!service) { + throw std::runtime_error("Invalid service proxy"); + } + } + + protected: + Interface service; +}; + +#endif + diff --git a/project2/ice/iceCompile.cpp b/project2/ice/iceCompile.cpp new file mode 100644 index 0000000..d9287f4 --- /dev/null +++ b/project2/ice/iceCompile.cpp @@ -0,0 +1,115 @@ +#include <pch.hpp> +#include "iceCompile.h" +#include <boost/filesystem/operations.hpp> +#include <logger.h> +#include <misc.h> +#include <dlfcn.h> + +namespace fs = boost::filesystem; + +std::string IceCompile::slice2cpp; +std::string IceCompile::cxx; +std::string IceCompile::linker; +std::string IceCompile::cxxopts; +std::string IceCompile::linkeropts; +fs::path IceCompile::tmpdir; +fs::path IceCompile::headerdir; + +DECLARE_OPTIONS(IceCompile, "ICE Compile Options") +("ice.compile.cxx", Options::value(&cxx, "g++"), + "The C++ compiler to use") +("ice.compile.cxxopts", Options::value(&cxxopts, "-Wall -Werror -std=c++11 -O3 -march=native -fPIC"), + "The extra arguments to pass to the C++ compiler") +("ice.compile.linker", Options::value(&linker, "g++"), + "The linker to use") +("ice.compile.linkeropts", Options::value(&linkeropts, ""), + "The extra arguments to pass to linker") +("ice.compile.slice2cpp", Options::value(&slice2cpp, "slice2cpp"), + "The ICE Slice to CPP processor to use") +("ice.compile.tmpdir", Options::value(&tmpdir, "/tmp/project2.slice"), + "The temporary directory used when compiling") +("ice.compile.headers", Options::value(&headerdir, "/usr/include/project2"), + "The root folder where Project2 header files are found") +END_OPTIONS(IceCompile); + +IceCompile::IceCompile(const boost::filesystem::path & s) : + slice(s) +{ +} + +IceCompile::IceCompile(const boost::filesystem::path & s, const Deps & d) : + slice(s), + deps(d) +{ +} + +void +IceCompile::Update() const +{ + fs::create_directories(IceCompile::tmpdir); + BOOST_FOREACH(const auto & dep, deps) { + dep->Update(); + } + const fs::path cpp(tmpdir / OutputName(".cpp")); + update(InputPath(), cpp, &IceCompile::Build); + const fs::path o(tmpdir / OutputName(".o")); + update(cpp, o, &IceCompile::Compile); + const fs::path so(tmpdir / OutputName(".so")); + update(o, so, &IceCompile::Link); +} + +void +IceCompile::update(const fs::path & in, const fs::path & out, UpdateFunc func) const +{ + if (!fs::exists(out) || std::max(fs::last_write_time(in), fs::last_write_time("/proc/self/exe")) > fs::last_write_time(out)) { + Logger()->messagebf(LOG_DEBUG, "updating %s from %s", out, in); + (this->*func)(in, out); + } + else { + Logger()->messagebf(LOG_DEBUG, "%s already up to date", out); + } +} + +void +IceCompile::Compile(const fs::path & in, const fs::path & out) const +{ + const auto compile = stringbf( + "%s %s -o %s -x c++ -c -I %s -I %s -I ../libmisc/ -I %s -I %s -I %s `pkg-config --cflags glibmm-2.4` %s", + cxx, cxxopts, out, tmpdir, + headerdir / "lib", + headerdir / "common", + headerdir / "ice", + headerdir / "daemon" / "lib", + in); + Logger()->messagebf(LOG_DEBUG, "compile command: %s", compile); + if (system(compile.c_str())) { + throw std::runtime_error("compile failed"); + } +} + +void +IceCompile::Link(const fs::path & in, const fs::path & out) const +{ + auto link = stringbf("%s %s -o %s -shared %s", linker, linkeropts, out, in); + BOOST_FOREACH(const auto & dep, deps) { + link += " " + (tmpdir / dep->OutputName(".so")).string(); + } + Logger()->messagebf(LOG_DEBUG, "link command: %s", link); + if (system(link.c_str())) { + throw std::runtime_error("link failed"); + } +} + +IceCompile::LibHandle +IceCompile::Open() const +{ + void * handle = dlopen((IceCompile::tmpdir / OutputName(".so")).string().c_str(), RTLD_GLOBAL | RTLD_NOW); + if (!handle) { + std::string msg(dlerror()); + Logger()->messagebf(LOG_ERR, "Failed to load compiled module (%s)", msg); + throw std::runtime_error(msg); + } + return LibHandle(handle, &dlclose); +} + + diff --git a/project2/ice/iceCompile.h b/project2/ice/iceCompile.h new file mode 100644 index 0000000..d403d9e --- /dev/null +++ b/project2/ice/iceCompile.h @@ -0,0 +1,51 @@ +#ifndef ICECOMPILE_H +#define ICECOMPILE_H + +#include "options.h" +#include <string> +#include <boost/filesystem/path.hpp> +#include <boost/optional.hpp> + +class IceCompile { + public: + INITOPTIONS; + + typedef std::vector<const IceCompile *> Deps; + + static std::string slice2cpp; + static std::string cxx; + static std::string linker; + static std::string cxxopts; + static std::string linkeropts; + static boost::filesystem::path tmpdir; + static boost::filesystem::path headerdir; + + IceCompile(const boost::filesystem::path & slice); + IceCompile(const boost::filesystem::path & slice, const Deps & deps); + + /// Conditionally execute Build, Compile, Link as required + void Update() const; + /// Source file path (e.g. /some/path/slice.ice) + virtual boost::filesystem::path InputPath() const = 0; + /// File name (no extension) in temporary directory (e.g. clientSlice) + virtual boost::filesystem::path OutputName(const std::string & type) const = 0; + + typedef boost::shared_ptr<void> LibHandle; + LibHandle Open() const; + + protected: + virtual void Build(const boost::filesystem::path & in, const boost::filesystem::path & out) const = 0; + void Compile(const boost::filesystem::path & in, const boost::filesystem::path & out) const; + void Link(const boost::filesystem::path & in, const boost::filesystem::path & out) const; + + typedef void (IceCompile::*UpdateFunc)(const boost::filesystem::path & in, const boost::filesystem::path & out) const; + void update(const boost::filesystem::path & in, const boost::filesystem::path & out, UpdateFunc func) const; + + const boost::filesystem::path slice; + + private: + const Deps deps; +}; + +#endif + diff --git a/project2/ice/iceConvert.cpp b/project2/ice/iceConvert.cpp new file mode 100644 index 0000000..1169aad --- /dev/null +++ b/project2/ice/iceConvert.cpp @@ -0,0 +1,74 @@ +#include <pch.hpp> +#include "iceConvert.h" +#include <boost/numeric/conversion/cast.hpp> + +template<> +VariableType +IceConvert< ::Ice::Short>::ToVariable(const ::Ice::Short & s) +{ + return VariableType(s); +} + +template<> +VariableType +IceConvert< ::Ice::Int>::ToVariable(const ::Ice::Int & i) +{ + return VariableType(i); +} + +template<> +VariableType +IceConvert< ::Ice::Long>::ToVariable(const ::Ice::Long & l) +{ + return VariableType(l); +} + +template<> +VariableType +IceConvert<bool>::ToVariable(const bool & b) +{ + return VariableType(b); +} + +template<> +VariableType +IceConvert< ::std::string>::ToVariable(const ::std::string & s) +{ + return VariableType(s); +} + +template<> +Ice::Short +IceConvert< ::Ice::Short>::FromVariable(const VariableType & s) +{ + return boost::numeric_cast<Ice::Short>(s.as<int64_t>()); +} + +template<> +Ice::Int +IceConvert< ::Ice::Int>::FromVariable(const VariableType & i) +{ + return i; +} + +template<> +Ice::Long +IceConvert< ::Ice::Long>::FromVariable(const VariableType & l) +{ + return l; +} + +template<> +bool +IceConvert<bool>::FromVariable(const VariableType & b) +{ + return b; +} + +template<> +std::string +IceConvert< ::std::string>::FromVariable(const VariableType & s) +{ + return s; +} + diff --git a/project2/ice/iceConvert.h b/project2/ice/iceConvert.h new file mode 100644 index 0000000..86e42d4 --- /dev/null +++ b/project2/ice/iceConvert.h @@ -0,0 +1,47 @@ +#ifndef ICECONVERT_H +#define ICECONVERT_H + +#include <variableType.h> +#include <boost/function.hpp> +#include <Ice/Ice.h> + +template <typename IceType> +class IceConvert { + public: + static IceType FromVariable(const VariableType &); + static VariableType ToVariable(const IceType &); +}; + +template <typename IceOptionalType> +class IceConvert<IceUtil::Optional<IceOptionalType>> { + public: + static IceUtil::Optional<IceOptionalType> FromVariable(const VariableType & v) + { + if (!boost::get<Null>(&v)) { + return IceConvert<IceOptionalType>::FromVariable(v); + } + return IceUtil::Optional<IceOptionalType>(); + } + + static VariableType ToVariable(const IceUtil::Optional<IceOptionalType> & v) + { + if (v) { + return IceConvert<IceOptionalType>::ToVariable(*v); + } + return Null(); + } +}; + +typedef boost::function<void(const std::string &)> IceEachDataMemberName; +typedef boost::function<void(VariableType)> IceEachDataMemberValue; + +template <typename RowType> +class IceType { + public: + static void CreateColumns(const IceEachDataMemberName & func); + static void ForEachDataMember(const IceInternal::Handle< RowType > & ptr, const IceEachDataMemberValue & func); + static void ForEachDataMember(const RowType & ptr, const IceEachDataMemberValue & func); +}; + +#endif + diff --git a/project2/ice/iceDaemon.cpp b/project2/ice/iceDaemon.cpp new file mode 100644 index 0000000..01acb36 --- /dev/null +++ b/project2/ice/iceDaemon.cpp @@ -0,0 +1,161 @@ +#include <pch.hpp> +#include "iceDaemon.h" +#include "buildComms.h" +#include "buildShared.h" +#include "buildDaemon.h" +#include <scriptLoader.h> +#include <options.h> +#include <sys/stat.h> +#include <boost/foreach.hpp> +#include <boost/filesystem.hpp> +#include <boost/lexical_cast.hpp> +#include <commonObjects.h> +#include <logger.h> +#include <checkHost.h> +#include <flatView.h> +#include <taskHost.h> +#include <execContext.h> +#include <misc.h> +#include <exceptions.h> + +std::string IceDaemon::adapterName; +std::string IceDaemon::adapterEndpoint; +std::string IceDaemon::interface; +std::string IceDaemon::slice; +std::string IceDaemon::viewRoot; +std::string IceDaemon::taskRoot; + +DECLARE_GENERIC_LOADER("ice", DaemonLoader, IceDaemon); +DECLARE_OPTIONS(IceDaemon, "ICE Daemon Options") +("ice.daemon.viewRoot", Options::value(&viewRoot, "views"), + "The folder in which to find view scripts") +("ice.daemon.taskRoot", Options::value(&taskRoot, "tasks"), + "The folder in which to find task scripts") +("ice.daemon.adapterName", Options::value(&adapterName, "DefaultAdapter"), + "The name of the ICE adapter created") +("ice.daemon.adapterEndpoint", Options::value(&adapterEndpoint), + "The ICE endpoint string for the ICE adapter") +("ice.daemon.slice", Options::value(&slice), + "The ICE Slice file to compile") +("ice.daemon.interface", Options::value(&interface), + "The ICE interface to wrap") +END_OPTIONS(IceDaemon); + +IceDaemon::IceDaemon(int & argc, char ** argv) : + ic(Ice::initialize(argc, argv)) +{ +} + +IceDaemon::~IceDaemon() +{ + ic->destroy(); +} + +void +IceDaemon::shutdown() const +{ + ic->shutdown(); +} + +void +IceDaemon::run() const +{ + Logger()->messagebf(LOG_INFO, ">>> %s compiling slice '%s'...", __PRETTY_FUNCTION__, slice); + + BuildComms bc(slice); + BuildShared bds(slice, { &bc }); + BuildDaemon bd(slice, { &bds }); + bd.Update(); + + auto library = bd.Open(); + + Logger()->messagebf(LOG_INFO, " %s starting...", __PRETTY_FUNCTION__); + Ice::ObjectAdapterPtr adapter = ic->createObjectAdapterWithEndpoints(adapterName, adapterEndpoint); + IceDaemonAdapterHandlerPtr interfacePtr = IceDaemonAdapterHandlerLoader::createNew(interface); + interfacePtr->add(adapter, this, ic); + adapter->activate(); + Logger()->messagebf(LOG_INFO, " %s running...", __PRETTY_FUNCTION__); + interfacePtr->remove(adapter, ic); + ic->waitForShutdown(); + Logger()->messagebf(LOG_INFO, " %s stopped...", __PRETTY_FUNCTION__); + + Logger()->messagebf(LOG_INFO, "<<< %s", __PRETTY_FUNCTION__); +} + +class IceDaemonFlatViewHost : public virtual CommonObjects, public virtual CheckHost { + public: + IceDaemonFlatViewHost(ScriptNodePtr s) : + CommonObjects(s), + CheckHost(s) + { + s->script->loader.addLoadTarget(s, Storer::into<ElementLoader>(&view)); + } + void executeView(RowSetPresenterPtr presenter, ExecContext * ec) const + { + loadScriptComponents(); + view->execute(presenter.get(), ec); + // Caches might open transactions + BOOST_FOREACH(const CommonObjects::DataSources::value_type & ds, CommonObjects::datasources) { + ds.second->commit(); + } + } + private: + typedef boost::intrusive_ptr<FlatView> ViewPtr; + ViewPtr view; +}; + +class IceCallContext : public ExecContext { + public: + IceCallContext(const ParamMap & p) : + params(p) + { + } + + VariableType getParameter(const VariableType & key) const + { + return safeMapLookup<ParamNotFound>(params, key); + } + + SessionPtr getSession() const + { + // There's no way to tell clients apart + throw NotSupported(__FUNCTION__); + } + + private: + const ParamMap & params; +}; + +void +IceDaemon::executeView(const std::string & name, RowSetPresenterPtr p, const ParamMap & pm) const +{ + ScriptNodePtr s = ScriptReader::resolveScript(IceDaemon::viewRoot, name, false)->root(); + IceDaemonFlatViewHost f(s); + IceCallContext icc(pm); + f.executeView(p, &icc); +} + +class IceDaemonTaskHost : public TaskHost { + public: + IceDaemonTaskHost(ScriptNodePtr s) : + SourceObject(s), + CheckHost(s), + TaskHost(s) + { + } + void executeTask(ExecContext * ec) const + { + runChecks(ec); + execute(ec); + } +}; + +void +IceDaemon::executeTask(const std::string & name, const ParamMap & pm) const +{ + ScriptNodePtr s = ScriptReader::resolveScript(IceDaemon::taskRoot, name, false)->root(); + IceDaemonTaskHost t(s); + IceCallContext icc(pm); + t.executeTask(&icc); +} + diff --git a/project2/ice/iceDaemon.h b/project2/ice/iceDaemon.h new file mode 100644 index 0000000..49af50b --- /dev/null +++ b/project2/ice/iceDaemon.h @@ -0,0 +1,30 @@ +#ifndef ICEDAEMON_H +#define ICEDAEMON_H + +#include <daemon.h> +#include "iceModule.h" + +class IceDaemon : public Daemon { + public: + IceDaemon(int & argc, char ** argv); + virtual ~IceDaemon(); + + void run() const; + void shutdown() const; + + void executeTask(const std::string & name, const ParamMap & params) const; + void executeView(const std::string & name, RowSetPresenterPtr p, const ParamMap & params) const; + + INITOPTIONS; + static std::string adapterName; + static std::string adapterEndpoint; + static std::string interface; + static std::string slice; + static std::string viewRoot; + static std::string taskRoot; + + private: + Ice::CommunicatorPtr ic; +}; + +#endif diff --git a/project2/ice/iceDataSource.cpp b/project2/ice/iceDataSource.cpp new file mode 100644 index 0000000..5cfd5b1 --- /dev/null +++ b/project2/ice/iceDataSource.cpp @@ -0,0 +1,43 @@ +#include <pch.hpp> +#include "iceDataSource.h" +#include "buildComms.h" +#include "buildShared.h" +#include "buildClient.h" +#include <Ice/Ice.h> + +IceDataSource::Libs IceDataSource::libs; +IceDataSource::Proxies IceDataSource::proxies; + +DECLARE_OPTIONS(IceDataSource, "ICE Data Source") +("ice.client.slice", Options::functions(boost::bind(&IceDataSource::SetSlice, _1), boost::bind(&IceDataSource::ClearSlice)), + "The ICE Slice file(s) to compile") +END_OPTIONS(IceDataSource); + +int dummy = 0; +IceDataSource::IceDataSource(ScriptNodePtr p) : + DataSource(p), + endpoint(p, "endpoint"), + ic(Ice::initialize(dummy, NULL)) +{ +} + +void +IceDataSource::SetSlice(const VariableType & vslice) +{ + auto slice = vslice.as<std::string>(); + BuildComms bc(slice); + BuildShared bcs(slice, { &bc }); + BuildClient bcl(slice, { &bcs }); + bcl.Update(); + libs.insert({ slice, bcl.Open() }); +} + +void +IceDataSource::ClearSlice() +{ + libs.clear(); + proxies.clear(); +} + +DECLARE_LOADER("icedatasource", IceDataSource); + diff --git a/project2/ice/iceDataSource.h b/project2/ice/iceDataSource.h new file mode 100644 index 0000000..e80a3fc --- /dev/null +++ b/project2/ice/iceDataSource.h @@ -0,0 +1,43 @@ +#ifndef ICEDATASOURCE_H +#define ICEDATASOURCE_H + +#include <dataSource.h> +#include <options.h> +#include <variables.h> +#include "iceCompile.h" +#include <Ice/Communicator.h> + +class IceDataSource : public DataSource { + public: + INITOPTIONS; + static std::string slice; + + IceDataSource(ScriptNodePtr p); + + template <typename Interface> + Interface GetProxy(const std::string object, ExecContext * ec) const + { + auto existingProxy = proxies.find(object); + if (existingProxy == proxies.end()) { + auto prx = Interface::checkedCast(ic->stringToProxy(object + ":" + endpoint(ec).as<std::string>())); + existingProxy = proxies.insert({ object, prx }).first; + return prx; + } + return Interface::checkedCast(existingProxy->second); + } + + private: + static void SetSlice(const VariableType &); + static void ClearSlice(); + typedef std::map<std::string, IceCompile::LibHandle> Libs; + static Libs libs; + + const Variable endpoint; + + const Ice::CommunicatorPtr ic; + typedef std::map<std::string, Ice::ObjectPrx> Proxies; + static Proxies proxies; +}; + +#endif + diff --git a/project2/ice/iceModule.cpp b/project2/ice/iceModule.cpp new file mode 100644 index 0000000..1738bef --- /dev/null +++ b/project2/ice/iceModule.cpp @@ -0,0 +1,22 @@ +#include <pch.hpp> +#include "iceModule.h" +#include "iceDaemon.h" +#include "instanceStore.impl.h" + +IceDaemonModule::IceDaemonModule(const IceDaemon * id) : + iceDaemon(id) +{ +} + +void +IceDaemonModule::executeView(const std::string & name, RowSetPresenterPtr p, const ParamMap & params) const { + iceDaemon->executeView(name, p, params); +} + +void +IceDaemonModule::executeTask(const std::string & name, const ParamMap & params) const { + iceDaemon->executeTask(name, params); +} + +INSTANTIATESTORE(std::string, IceDaemonAdapterHandlerLoader); + diff --git a/project2/ice/iceModule.h b/project2/ice/iceModule.h new file mode 100644 index 0000000..246c9b8 --- /dev/null +++ b/project2/ice/iceModule.h @@ -0,0 +1,70 @@ +#ifndef ICEMODULE_H +#define ICEMODULE_H + +#include <map> +#include <variableType.h> +#include <Ice/Ice.h> +#include <presenter.h> +#include <safeMapFind.h> +#include <boost/function.hpp> + +typedef std::map<std::string, VariableType> ParamMap; +class IceDaemon; + +class IceDaemonModule { + protected: + IceDaemonModule(const IceDaemon *); + + void executeTask(const std::string & name, const ParamMap & params) const; + void executeView(const std::string & name, RowSetPresenterPtr p, const ParamMap & params) const; + + private: + const IceDaemon * const iceDaemon; +}; + +class IceDaemonAdapterHandler : public IntrusivePtrBase { + public: + virtual void add(Ice::ObjectAdapterPtr, const IceDaemon *, Ice::CommunicatorPtr) const = 0; + virtual void remove(Ice::ObjectAdapterPtr, Ice::CommunicatorPtr) const = 0; +}; + +typedef boost::intrusive_ptr<IceDaemonAdapterHandler> IceDaemonAdapterHandlerPtr; +typedef GenLoader<IceDaemonAdapterHandler, std::string> IceDaemonAdapterHandlerLoader; + +template <typename IC> +class IcePresenter : public RowSetPresenter { + public: + typedef boost::function<void (typename IC::value_type *, const VariableType &)> TargetAssigner; + typedef std::map<Glib::ustring, TargetAssigner> MemberTargets; + SimpleMessageException(NoSuchMember); + + IcePresenter(IC & t); + virtual void addNamedValue(const Glib::ustring & member, const VariableType & value) const + { + safeMapLookup<NoSuchMember>(memberTargets, member)(&*current, value); + } + virtual void addNewRow(const Glib::ustring&) const + { + target.push_back(typename IC::value_type()); + } + virtual void finishRow() const + { + current = target.end(); + } + // The target array already exists, so these need not do anything + virtual void addNewArray(const Glib::ustring&, bool) const { } + virtual void finishArray(bool) const { } + virtual void init() { } + private: + IC & target; + mutable typename IC::iterator current; + const MemberTargets memberTargets; + + template <typename T, typename M> static void memberAssign(T * t, M T::*m, const VariableType & v) { + t->*m = v.as<M>(); + } +}; + + +#endif + diff --git a/project2/ice/iceRows.h b/project2/ice/iceRows.h new file mode 100644 index 0000000..654de50 --- /dev/null +++ b/project2/ice/iceRows.h @@ -0,0 +1,87 @@ +#ifndef ICEVIEW_H +#define ICEVIEW_H + +#include <rowSet.h> +#include "iceConvert.h" +#include "iceClient.h" + +template <typename Type> +class IceRowState : public RowState { + public: + IceRowState() + { + unsigned int idx = 0; + IceType<Type>::CreateColumns(boost::bind(&IceRowState::AddColumn, this, boost::ref(idx), _1)); + fields.resize(columns.size()); + } + + void AddColumn(unsigned int & c, const std::string & name) + { + columns.insert(new Column(c++, name)); + } + + const Columns & getColumns() const { return columns; } + + void IterateOver(const Type & record, const RowProcessorCallback & rp) { + auto field = fields.begin(); + IceType<Type>::ForEachDataMember(record, boost::bind(&IceRowState::AssignFieldValue, this, boost::ref(field), _1)); + this->process(rp); + } + + void AssignFieldValue(FieldValues::iterator & field, const VariableType & vt) + { + *field++ = vt; + } + + Columns columns; +}; + +template <typename Type> +class IceRowState<std::vector<Type> > : public RowState { + public: + typedef std::vector<Type> RangeType; + IceRowState() + { + unsigned int idx = 0; + IceType<Type>::CreateColumns(boost::bind(&IceRowState::AddColumn, this, boost::ref(idx), _1)); + fields.resize(columns.size()); + } + + void AddColumn(unsigned int & c, const std::string & name) + { + columns.insert(new Column(c++, name)); + } + + const Columns & getColumns() const { return columns; } + + void IterateOver(const RangeType & records, const RowProcessorCallback & rp) { + BOOST_FOREACH(const auto & record, records) { + auto field = fields.begin(); + IceType<Type>::ForEachDataMember(record, boost::bind(&IceRowState::AssignFieldValue, this, boost::ref(field), _1)); + this->process(rp); + } + } + + void AssignFieldValue(FieldValues::iterator & field, const VariableType & vt) + { + *field++ = vt; + } + + Columns columns; +}; + +template <typename Interface> +class IceRows : public RowSet, public IceClient<Interface> { + public: + IceRows(ScriptNodePtr p) : + RowSet(p), + IceClient<Interface>(p) + { + } + void loadComplete(const CommonObjects * co) { + IceClient<Interface>::loadComplete(co); + } +}; + +#endif + diff --git a/project2/ice/iceTask.h b/project2/ice/iceTask.h new file mode 100644 index 0000000..2d71818 --- /dev/null +++ b/project2/ice/iceTask.h @@ -0,0 +1,22 @@ +#ifndef ICETASK_H +#define ICETASK_H + +#include <task.h> +#include <logger.h> +#include "iceClient.h" + +template <typename Interface> +class IceTask : public Task, public IceClient<Interface> { + public: + IceTask(ScriptNodePtr p) : + SourceObject(p), + Task(p), + IceClient<Interface>(p) + { + } + + void loadComplete(const CommonObjects * co) { IceClient<Interface>::loadComplete(co); } +}; + +#endif + diff --git a/project2/ice/pch.hpp b/project2/ice/pch.hpp new file mode 100644 index 0000000..c74eebf --- /dev/null +++ b/project2/ice/pch.hpp @@ -0,0 +1,21 @@ +#ifdef BOOST_BUILD_PCH_ENABLED +#ifndef CGI_PCH +#define CGI_PCH + +#include <Ice/Ice.h> +#include <boost/filesystem.hpp> +#include <boost/foreach.hpp> +#include <boost/function.hpp> +#include <boost/optional.hpp> +#include <commonObjects.h> +#include <exceptions.h> +#include <logger.h> +#include <map> +#include <options.h> +#include <Slice/Parser.h> +#include <string> +#include <variables.h> + +#endif +#endif + diff --git a/project2/ice/slice2Daemon.cpp b/project2/ice/slice2Daemon.cpp new file mode 100644 index 0000000..6a8e5fa --- /dev/null +++ b/project2/ice/slice2Daemon.cpp @@ -0,0 +1,86 @@ +#include <pch.hpp> +#include "slice2Daemon.h" +#include <boost/foreach.hpp> +#include <Slice/CPlusPlusUtil.h> + +Slice2Daemon::Slice2Daemon(FILE * c) : + code(c) +{ +} + +bool +Slice2Daemon::visitModuleStart(const Slice::ModulePtr & m) +{ + module = m->name(); + fprintf(code, "namespace %s {\n", m->name().c_str()); + return true; +} + +bool +Slice2Daemon::visitClassDefStart(const Slice::ClassDefPtr & c) +{ + interface = c->name(); + fprintf(code, "\tclass %sImpl : public IceDaemonModule, public %s {\n", c->name().c_str(), c->name().c_str()); + fprintf(code, "\t\tpublic:\n"); + fprintf(code, "\t\t\t%sImpl(const IceDaemon * id) :\n", c->name().c_str()); + fprintf(code, "\t\t\t\tIceDaemonModule(id)\n"); + fprintf(code, "\t\t\t{\n\t\t\t}\n\n"); + return true; +} + +void +Slice2Daemon::visitOperation(const Slice::OperationPtr & o) +{ + if (o->returnType()) { + fprintf(code, "\t\t\t%s %s(", returnTypeToString(o->returnType(), o->returnIsOptional()).c_str(), o->name().c_str()); + } + else { + fprintf(code, "\t\t\tvoid %s(", o->name().c_str()); + } + BOOST_FOREACH(const auto & p, o->parameters()) { + fprintf(code, "%s %s, ", inputTypeToString(p->type(), p->optional(), p->getMetaData(), 0).c_str(), p->name().c_str()); + } + fprintf(code, "const ::Ice::Current &) {\n"); + visitParameterMap(o); + if (o->returnType()) { + fprintf(code, "\t\t\t\t%s rtn;\n", o->returnType()->typeId().c_str()); + fprintf(code, "\t\t\t\tRowSetPresenterPtr ipp = new IcePresenter< %s >(rtn);\n", o->returnType()->typeId().c_str()); + fprintf(code, "\t\t\t\texecuteView(\"%s/%s/%s\", ipp, params);\n", module.c_str(), interface.c_str(), o->name().c_str()); + fprintf(code, "\t\t\t\treturn rtn;\n"); + } + else { + fprintf(code, "\t\t\t\texecuteTask(\"%s/%s/%s\", params);\n", module.c_str(), interface.c_str(), o->name().c_str()); + } + fprintf(code, "\t\t\t}\n\n"); +} + +void +Slice2Daemon::visitClassDefEnd(const Slice::ClassDefPtr & c) +{ + fprintf(code, "\t}; // class %sImpl\n\n", c->name().c_str()); +} + +void +Slice2Daemon::visitModuleEnd(const Slice::ModulePtr & m) +{ + fprintf(code, "}; // namespace %s\n\n", m->name().c_str()); +} + +void +Slice2Daemon::visitParameterMap(const Slice::OperationPtr & o) +{ + fprintf(code, "\t\t\t\tParamMap params {\n"); + BOOST_FOREACH(const auto & p, o->parameters()) { + Slice::StructPtr s = dynamic_cast<Slice::Struct *>(p->type().get()); + if (s) { + BOOST_FOREACH(const auto & m, s->dataMembers()) { + fprintf(code, "\t\t\t\t\t\t{\"%s.%s\", %s.%s},\n", p->name().c_str(), m->name().c_str(), p->name().c_str(), m->name().c_str()); + } + } + else { + fprintf(code, "\t\t\t\t\t\t{\"%s\", %s},\n", p->name().c_str(), p->name().c_str()); + } + } + fprintf(code, "\t\t\t\t\t};\n"); +} + diff --git a/project2/ice/slice2Daemon.h b/project2/ice/slice2Daemon.h new file mode 100644 index 0000000..4487f9b --- /dev/null +++ b/project2/ice/slice2Daemon.h @@ -0,0 +1,24 @@ +#ifndef ICEBUILDDAEMON_H +#define ICEBUILDDAEMON_H + +#include <Slice/Parser.h> + +class Slice2Daemon : public Slice::ParserVisitor { + public: + Slice2Daemon(FILE * c); + + virtual bool visitModuleStart(const Slice::ModulePtr & m); + virtual bool visitClassDefStart(const Slice::ClassDefPtr & c); + virtual void visitOperation(const Slice::OperationPtr & o); + virtual void visitClassDefEnd(const Slice::ClassDefPtr & c); + virtual void visitModuleEnd(const Slice::ModulePtr & m); + + private: + void visitParameterMap(const Slice::OperationPtr & o); + FILE * code; + std::string interface; + std::string module; +}; + +#endif + diff --git a/project2/ice/slice2DaemonLoader.cpp b/project2/ice/slice2DaemonLoader.cpp new file mode 100644 index 0000000..81fd501 --- /dev/null +++ b/project2/ice/slice2DaemonLoader.cpp @@ -0,0 +1,46 @@ +#include <pch.hpp> +#include "slice2DaemonLoader.h" +#include <boost/foreach.hpp> + +Slice2DaemonLoader::Slice2DaemonLoader(FILE * c) : + code(c) +{ +} + +bool +Slice2DaemonLoader::visitModuleStart(const Slice::ModulePtr & m) +{ + module = m->name(); + fprintf(code, "// Loader for %s\n", m->name().c_str()); + fprintf(code, "class %sIceDaemonAdapterHandler : public IceDaemonAdapterHandler {\n", m->name().c_str()); + fprintf(code, "\tpublic:\n"); + return true; +} + +bool +Slice2DaemonLoader::visitClassDefStart(const Slice::ClassDefPtr & c) +{ + interfaces.push_back(c->name()); + return false; +} + +void +Slice2DaemonLoader::visitModuleEnd(const Slice::ModulePtr & m) +{ + fprintf(code, "\t\tvoid add(Ice::ObjectAdapterPtr adapter, const IceDaemon * id, Ice::CommunicatorPtr ic) const {\n"); + BOOST_FOREACH(const auto & i, interfaces) { + fprintf(code, "\t\t\tadapter->add(new %s::%sImpl(id), ic->stringToIdentity(\"%s%s\"));\n", + module.c_str(), i.c_str(), module.c_str(), i.c_str()); + } + fprintf(code, "\t\t}\n\n"); + fprintf(code, "\t\tvoid remove(Ice::ObjectAdapterPtr adapter, Ice::CommunicatorPtr ic) const {\n"); + BOOST_FOREACH(const auto & i, interfaces) { + fprintf(code, "\t\t\tadapter->remove(ic->stringToIdentity(\"%s%s\"));\n", + module.c_str(), i.c_str()); + } + fprintf(code, "\t\t}\n\n"); + fprintf(code, "};\n"); + fprintf(code, "DECLARE_GENERIC_LOADER(\"%s\", IceDaemonAdapterHandlerLoader, %sIceDaemonAdapterHandler);\n", m->name().c_str(), m->name().c_str()); + fprintf(code, "// End loader for%s\n\n", m->name().c_str()); +} + diff --git a/project2/ice/slice2DaemonLoader.h b/project2/ice/slice2DaemonLoader.h new file mode 100644 index 0000000..3c1fd5f --- /dev/null +++ b/project2/ice/slice2DaemonLoader.h @@ -0,0 +1,21 @@ +#ifndef ICEBUILDLOADER_H +#define ICEBUILDLOADER_H + +#include <Slice/Parser.h> + +class Slice2DaemonLoader : public Slice::ParserVisitor { + public: + Slice2DaemonLoader(FILE * c); + + virtual bool visitModuleStart(const Slice::ModulePtr & m); + virtual bool visitClassDefStart(const Slice::ClassDefPtr & c); + virtual void visitModuleEnd(const Slice::ModulePtr & m); + + private: + FILE * code; + std::string module; + std::vector<std::string> interfaces; +}; + +#endif + diff --git a/project2/ice/slice2Presenter.cpp b/project2/ice/slice2Presenter.cpp new file mode 100644 index 0000000..3cfb422 --- /dev/null +++ b/project2/ice/slice2Presenter.cpp @@ -0,0 +1,60 @@ +#include <pch.hpp> +#include "slice2Presenter.h" +#include <Slice/CPlusPlusUtil.h> + +Slice2Presenter::Slice2Presenter(FILE * c) : + code(c) +{ +} + +bool +Slice2Presenter::visitModuleStart(const Slice::ModulePtr & m) +{ + module = m->name(); + fprintf(code, "// Specialized functions for IcePresenters in module %s\n\n", module.c_str()); + return true; +} + +void +Slice2Presenter::visitModuleEnd(const Slice::ModulePtr &) +{ + fprintf(code, "// End Specialized functions for IcePresenters in module %s\n\n", module.c_str()); + module.clear(); +} + +bool +Slice2Presenter::visitStructStart(const Slice::StructPtr & s) +{ + strct = s->name(); + fprintf(code, "template <>\nIcePresenter<std::vector< %s::%s >>::IcePresenter(std::vector< %s::%s > & t) :\n", + module.c_str(), s->name().c_str(), + module.c_str(), s->name().c_str()); + fprintf(code, "\ttarget(t),\n\tcurrent(target.end()),\n"); + fprintf(code, "\tmemberTargets({\n"); + return true; +} + +void +Slice2Presenter::visitDataMember(const Slice::DataMemberPtr & m) +{ + fprintf(code, "\t\t{\"%s\", boost::bind(&IcePresenter<std::vector< %s::%s >>::memberAssign< %s::%s, %s >, _1, &%s::%s::%s, _2)},\n", + m->name().c_str(), + module.c_str(), strct.c_str(), + module.c_str(), strct.c_str(), + typeToString(m->type()).c_str(), + module.c_str(), strct.c_str(), m->name().c_str() + + ); +} + +void +Slice2Presenter::visitStructEnd(const Slice::StructPtr&) +{ + fprintf(code, "\t})\n{\n"); + + //fprintf(code, "boost::bind(&IcePresenter<std::vector<P2TV::Recording>>::memberAssign<P2TV::Recording, int>, NULL, &P2TV::Recording::recordingId, 1);\n"); + + fprintf(code, "}\n\n"); + strct.clear(); +} + diff --git a/project2/ice/slice2Presenter.h b/project2/ice/slice2Presenter.h new file mode 100644 index 0000000..892f2c1 --- /dev/null +++ b/project2/ice/slice2Presenter.h @@ -0,0 +1,23 @@ +#ifndef ICEBUILDPRESENTER_H +#define ICEBUILDPRESENTER_H + +#include <Slice/Parser.h> + +class Slice2Presenter : public Slice::ParserVisitor { + public: + Slice2Presenter(FILE * c); + virtual bool visitModuleStart(const Slice::ModulePtr & m); + virtual void visitModuleEnd(const Slice::ModulePtr & m); + virtual bool visitStructStart(const Slice::StructPtr&); + virtual void visitStructEnd(const Slice::StructPtr&); + virtual void visitDataMember(const Slice::DataMemberPtr&); + + private: + FILE * code; + std::string module; + std::string strct; +}; + +#endif + + diff --git a/project2/ice/slice2Rows.cpp b/project2/ice/slice2Rows.cpp new file mode 100644 index 0000000..9646f17 --- /dev/null +++ b/project2/ice/slice2Rows.cpp @@ -0,0 +1,94 @@ +#include <pch.hpp> +#include "slice2Rows.h" +#include <boost/foreach.hpp> +#include <Slice/CPlusPlusUtil.h> + +Slice2Rows::Slice2Rows(FILE * c) : + code(c) +{ +} + +bool +Slice2Rows::visitModuleStart(const Slice::ModulePtr & m) +{ + module = m->name(); + fprintf(code, "namespace IceRowsWrappers {\n"); + fprintf(code, "\tnamespace %s {\n", m->name().c_str()); + return true; +} + +bool +Slice2Rows::visitClassDefStart(const Slice::ClassDefPtr & c) +{ + interface = c->name(); + fprintf(code, "\t\tnamespace %s {\n", c->name().c_str()); + return true; +} + +void +Slice2Rows::visitOperation(const Slice::OperationPtr & o) +{ + if (o->hasMetaData("project2:rows")) { + fprintf(code, "\t\t\tclass %s : public IceRows< ::%s::%sPrx > {\n", o->name().c_str(), module.c_str(), interface.c_str()); + fprintf(code, "\t\t\t\tpublic:\n"); + // Constructor + fprintf(code, "\t\t\t\t\t%s(ScriptNodePtr p) :\n", o->name().c_str()); + fprintf(code, "\t\t\t\t\t\tIceRows< ::%s::%sPrx >(p)", module.c_str(), interface.c_str()); + BOOST_FOREACH(const auto & p, o->parameters()) { + fprintf(code, ",\n\t\t\t\t\t\t%s(p, \"%s\")", p->name().c_str(), p->name().c_str()); + } + fprintf(code, "\n\t\t\t\t\t{\n"); + fprintf(code, "\t\t\t\t\t}\n\n"); + // Execute + fprintf(code, "\t\t\t\t\tvoid execute(const Glib::ustring &, const RowProcessorCallback & rp, ExecContext * ec) const\n"); + fprintf(code, "\t\t\t\t\t{\n"); + fprintf(code, "\t\t\t\t\t\tLogger()->messagebf(LOG_DEBUG, \"%%s: "); + BOOST_FOREACH(const auto & p, o->parameters()) { + fprintf(code, "%s = %%s, ", p->name().c_str()); + } + fprintf(code, "ice @ %%p\", \n"); + fprintf(code, "\t\t\t\t\t\t\t\t__PRETTY_FUNCTION__, "); + BOOST_FOREACH(const auto & p, o->parameters()) { + fprintf(code, "%s(ec).as<std::string>(), ", p->name().c_str()); + } + fprintf(code, "ice);\n"); + fprintf(code, "\t\t\t\t\t\tIce::Context ctx;\n"); + BOOST_FOREACH(const auto & p, o->parameters()) { + fprintf(code, "\t\t\t\t\t\tauto _%s = IceConvert< %s >::FromVariable(%s(ec));\n", + p->name().c_str(), + Slice::typeToString(p->type()).c_str(), + p->name().c_str()); + } + fprintf(code, "\t\t\t\t\t\tIceRowState<decltype(service->%s(", o->name().c_str()); + BOOST_FOREACH(const auto & p, o->parameters()) { + fprintf(code, "_%s, ", p->name().c_str()); + } + fprintf(code, "ctx))> irs;\n"); + fprintf(code, "\t\t\t\t\t\tirs.IterateOver(service->%s(", o->name().c_str()); + BOOST_FOREACH(const auto & p, o->parameters()) { + fprintf(code, "_%s, ", p->name().c_str()); + } + fprintf(code, "ctx), rp);\n"); + fprintf(code, "\t\t\t\t\t}\n\n"); + // Parameter variables + BOOST_FOREACH(const auto & p, o->parameters()) { + fprintf(code, "\t\t\t\t\tconst Variable %s;\n", p->name().c_str()); + } + fprintf(code, "\t\t\t};\n"); + fprintf(code, "\t\t\tDECLARE_LOADER(\"%s-%s-%s\", %s);\n\n", module.c_str(), interface.c_str(), o->name().c_str(), o->name().c_str()); + } +} + +void +Slice2Rows::visitClassDefEnd(const Slice::ClassDefPtr & c) +{ + fprintf(code, "\t\t} // namespace %s\n\n", c->name().c_str()); +} + +void +Slice2Rows::visitModuleEnd(const Slice::ModulePtr & m) +{ + fprintf(code, "\t}; // namespace %s\n", m->name().c_str()); + fprintf(code, "}; // namespace IceRowsWrappers\n\n"); +} + diff --git a/project2/ice/slice2Rows.h b/project2/ice/slice2Rows.h new file mode 100644 index 0000000..b97f009 --- /dev/null +++ b/project2/ice/slice2Rows.h @@ -0,0 +1,24 @@ +#ifndef ICEBUILDVIEW_H +#define ICEBUILDVIEW_H + +#include <Slice/Parser.h> + +class Slice2Rows : public Slice::ParserVisitor { + public: + Slice2Rows(FILE * c); + virtual bool visitModuleStart(const Slice::ModulePtr & m); + virtual bool visitClassDefStart(const Slice::ClassDefPtr & c); + virtual void visitOperation(const Slice::OperationPtr & o); + virtual void visitClassDefEnd(const Slice::ClassDefPtr & c); + virtual void visitModuleEnd(const Slice::ModulePtr & m); + + private: + FILE * code; + std::string interface; + std::string module; +}; + +#endif + + + diff --git a/project2/ice/slice2Task.cpp b/project2/ice/slice2Task.cpp new file mode 100644 index 0000000..53ad8b4 --- /dev/null +++ b/project2/ice/slice2Task.cpp @@ -0,0 +1,86 @@ +#include <pch.hpp> +#include "slice2Task.h" +#include <boost/foreach.hpp> +#include <Slice/CPlusPlusUtil.h> + +Slice2Task::Slice2Task(FILE * c) : + code(c) +{ +} + +bool +Slice2Task::visitModuleStart(const Slice::ModulePtr & m) +{ + module = m->name(); + fprintf(code, "namespace IceTaskWrappers {\n"); + fprintf(code, "\tnamespace %s {\n", m->name().c_str()); + return true; +} + +bool +Slice2Task::visitClassDefStart(const Slice::ClassDefPtr & c) +{ + interface = c->name(); + fprintf(code, "\t\tnamespace %s {\n", c->name().c_str()); + return true; +} + +void +Slice2Task::visitOperation(const Slice::OperationPtr & o) +{ + if (o->hasMetaData("project2:task")) { + fprintf(code, "\t\t\tclass %s : public IceTask< ::%s::%sPrx > {\n", o->name().c_str(), module.c_str(), interface.c_str()); + fprintf(code, "\t\t\t\tpublic:\n"); + // Constructor + fprintf(code, "\t\t\t\t\t%s(ScriptNodePtr p) :\n", o->name().c_str()); + fprintf(code, "\t\t\t\t\t\tSourceObject(p),\n"); + fprintf(code, "\t\t\t\t\t\tIceTask< ::%s::%sPrx >(p)", module.c_str(), interface.c_str()); + BOOST_FOREACH(const auto & p, o->parameters()) { + fprintf(code, ",\n\t\t\t\t\t\t%s(p, \"%s\")", p->name().c_str(), p->name().c_str()); + } + fprintf(code, "\n\t\t\t\t\t{\n"); + fprintf(code, "\t\t\t\t\t}\n\n"); + // Execute + fprintf(code, "\t\t\t\t\tvoid execute(ExecContext * ec) const\n"); + fprintf(code, "\t\t\t\t\t{\n"); + fprintf(code, "\t\t\t\t\t\tLogger()->messagebf(LOG_DEBUG, \"%%s: "); + BOOST_FOREACH(const auto & p, o->parameters()) { + fprintf(code, "%s = %%s, ", p->name().c_str()); + } + fprintf(code, "ice @ %%p\", \n"); + fprintf(code, "\t\t\t\t\t\t\t\t__PRETTY_FUNCTION__, "); + BOOST_FOREACH(const auto & p, o->parameters()) { + fprintf(code, "%s(ec).as<std::string>(), ", p->name().c_str()); + } + fprintf(code, "ice);\n"); + fprintf(code, "\t\t\t\t\t\tIce::Context ctx;\n"); + fprintf(code, "\t\t\t\t\t\tservice->%s(", o->name().c_str()); + BOOST_FOREACH(const auto & p, o->parameters()) { + fprintf(code, "IceConvert< %s >::ToVariable(%s(ec)), ", + Slice::typeToString(p->type()).c_str(), + p->name().c_str()); + } + fprintf(code, "ctx);\n"); + fprintf(code, "\t\t\t\t\t}\n\n"); + // Parameter variables + BOOST_FOREACH(const auto & p, o->parameters()) { + fprintf(code, "\t\t\t\t\tconst Variable %s;\n", p->name().c_str()); + } + fprintf(code, "\t\t\t};\n"); + fprintf(code, "\t\t\tDECLARE_LOADER(\"%s-%s-%s\", %s);\n\n", module.c_str(), interface.c_str(), o->name().c_str(), o->name().c_str()); + } +} + +void +Slice2Task::visitClassDefEnd(const Slice::ClassDefPtr & c) +{ + fprintf(code, "\t\t} // namespace %s\n\n", c->name().c_str()); +} + +void +Slice2Task::visitModuleEnd(const Slice::ModulePtr & m) +{ + fprintf(code, "\t}; // namespace %s\n", m->name().c_str()); + fprintf(code, "}; // namespace IceTaskWrappers\n\n"); +} + diff --git a/project2/ice/slice2Task.h b/project2/ice/slice2Task.h new file mode 100644 index 0000000..d3bd0fe --- /dev/null +++ b/project2/ice/slice2Task.h @@ -0,0 +1,24 @@ +#ifndef SLICE2TASK_H +#define SLICE2TASK_H + +#include <Slice/Parser.h> + +class Slice2Task : public Slice::ParserVisitor { + public: + Slice2Task(FILE * c); + + virtual bool visitModuleStart(const Slice::ModulePtr & m); + virtual bool visitClassDefStart(const Slice::ClassDefPtr & c); + virtual void visitOperation(const Slice::OperationPtr & o); + virtual void visitClassDefEnd(const Slice::ClassDefPtr & c); + virtual void visitModuleEnd(const Slice::ModulePtr & m); + + private: + FILE * code; + std::string interface; + std::string module; +}; + +#endif + + diff --git a/project2/ice/slice2Type.cpp b/project2/ice/slice2Type.cpp new file mode 100644 index 0000000..9c3404e --- /dev/null +++ b/project2/ice/slice2Type.cpp @@ -0,0 +1,110 @@ +#include <pch.hpp> +#include "slice2Type.h" +#include <Slice/CPlusPlusUtil.h> +#include <boost/foreach.hpp> + +Slice2Type::Slice2Type(FILE * c) : + code(c) +{ +} + +bool +Slice2Type::visitModuleStart(const Slice::ModulePtr & m) +{ + module = m->name(); + return true; +} + +void +Slice2Type::visitModuleEnd(const Slice::ModulePtr &) +{ + module.clear(); +} + +void +Slice2Type::visitClassDecl(const Slice::ClassDeclPtr&) +{ +} + +bool +Slice2Type::visitExceptionStart(const Slice::ExceptionPtr & e) +{ + if (e->hasMetaData("project2:type")) { + fprintf(code, "template <>\nvoid IceType< %s::%s >::ForEachDataMember(const %s::%s & obj, const IceEachDataMemberValue & func)\n{\n", + module.c_str(), e->name().c_str(), + module.c_str(), e->name().c_str()); + membersToVariables(e->dataMembers(), "obj."); + fprintf(code, "}\n\n"); + + fprintf(code, "template <>\nvoid IceType< %s::%s >::CreateColumns(const IceEachDataMemberName & func)\n{\n", + module.c_str(), e->name().c_str()); + membersToColumns(e->dataMembers()); + fprintf(code, "}\n\n"); + } + return false; +} + +bool +Slice2Type::visitClassDefStart(const Slice::ClassDefPtr & c) +{ + if (c->hasMetaData("project2:type")) { + fprintf(code, "template <>\nvoid IceType< IceInternal::Handle< %s::%s > >::ForEachDataMember(const IceInternal::Handle< %s::%s > & ptr, const IceEachDataMemberValue & func)\n{\n", + module.c_str(), c->name().c_str(), + module.c_str(), c->name().c_str()); + membersToVariables(c->dataMembers(), "ptr->"); + fprintf(code, "}\n\n"); + + fprintf(code, "template <>\nvoid IceType< IceInternal::Handle< %s::%s > >::CreateColumns(const IceEachDataMemberName & func)\n{\n", + module.c_str(), c->name().c_str()); + membersToColumns(c->dataMembers()); + fprintf(code, "}\n\n"); + } + return false; +} + +bool +Slice2Type::visitStructStart(const Slice::StructPtr & s) +{ + if (s->hasMetaData("project2:type")) { + fprintf(code, "template <>\nvoid IceType< %s::%s >::ForEachDataMember(const %s::%s & obj, const IceEachDataMemberValue & func)\n{\n", + module.c_str(), s->name().c_str(), + module.c_str(), s->name().c_str()); + membersToVariables(s->dataMembers(), "obj."); + fprintf(code, "}\n\n"); + + fprintf(code, "template <>\nvoid IceType< %s::%s >::CreateColumns(const IceEachDataMemberName & func)\n{\n", + module.c_str(), s->name().c_str()); + membersToColumns(s->dataMembers()); + fprintf(code, "}\n\n"); + } + return false; +} + +void +Slice2Type::membersToVariables(const Slice::DataMemberList & members, const std::string & access) const +{ + BOOST_FOREACH(const auto & m, members) { + if (m->optional()) { + fprintf(code, "\tfunc(IceConvert< IceUtil::Optional< %s> >::ToVariable(%s%s));\n", + Slice::typeToString(m->type()).c_str(), + access.c_str(), + m->name().c_str()); + } + else { + fprintf(code, "\tfunc(IceConvert< %s >::ToVariable(%s%s));\n", + Slice::typeToString(m->type()).c_str(), + access.c_str(), + m->name().c_str()); + } + } +} + +void +Slice2Type::membersToColumns(const Slice::DataMemberList & members) const +{ + BOOST_FOREACH(const auto & m, members) { + fprintf(code, "\tfunc(\"%s\");\n", + m->name().c_str()); + } +} + diff --git a/project2/ice/slice2Type.h b/project2/ice/slice2Type.h new file mode 100644 index 0000000..e2b94fc --- /dev/null +++ b/project2/ice/slice2Type.h @@ -0,0 +1,25 @@ +#ifndef ICEBUILDPRESENTER_H +#define ICEBUILDPRESENTER_H + +#include <Slice/Parser.h> + +class Slice2Type : public Slice::ParserVisitor { + public: + Slice2Type(FILE * c); + virtual bool visitModuleStart(const Slice::ModulePtr & m); + virtual void visitModuleEnd(const Slice::ModulePtr & m); + virtual void visitClassDecl(const Slice::ClassDeclPtr&); + virtual bool visitExceptionStart(const Slice::ExceptionPtr&); + virtual bool visitClassDefStart(const Slice::ClassDefPtr&); + virtual bool visitStructStart(const Slice::StructPtr&); + + private: + void membersToVariables(const Slice::DataMemberList &, const std::string &) const; + void membersToColumns(const Slice::DataMemberList &) const; + FILE * code; + std::string module; +}; + +#endif + + diff --git a/project2/ice/sliceCompile.cpp b/project2/ice/sliceCompile.cpp new file mode 100644 index 0000000..f98ecde --- /dev/null +++ b/project2/ice/sliceCompile.cpp @@ -0,0 +1,59 @@ +#include <pch.hpp> +#include "sliceCompile.h" +#include <scopeObject.h> + +SliceCompile::SliceCompile(const boost::filesystem::path & slice, const IceCompile::Deps & dep) : + IceCompile(slice, dep) +{ +} + +void +SliceCompile::Build(const boost::filesystem::path & in, const boost::filesystem::path & outpath) const +{ + std::vector<std::string> cppArgs; + Slice::PreprocessorPtr icecpp = Slice::Preprocessor::create("slice2project2", in.string(), cppArgs); + FILE * cppHandle = icecpp->preprocess(false); + + if (cppHandle == NULL) { + throw std::runtime_error("preprocess failed"); + } + + Slice::UnitPtr u = Slice::Unit::createUnit(false, false, false, false); + ScopeObject uDestroy(boost::bind(&Slice::Unit::destroy, u.get())); + + int parseStatus = u->parse(in.string(), cppHandle, false); + + if (!icecpp->close()) { + throw std::runtime_error("preprocess close failed"); + } + + if (parseStatus == EXIT_FAILURE) { + throw std::runtime_error("unit parse failed"); + } + + FILE * out = fopen(outpath.string().c_str(), "w"); + if (!out) { + throw std::runtime_error("failed to open target"); + } + + fprintf(out, "#include <%s>\n", (in.filename().replace_extension(".h")).string().c_str()); + Headers(out); + fprintf(out, "\n"); + Body(out, u); + + if (fclose(out)) { + throw std::runtime_error("failed to close target"); + } +} + +void +SliceCompile::Headers(FILE *) const +{ +} + +boost::filesystem::path +SliceCompile::InputPath() const +{ + return slice; +} + diff --git a/project2/ice/sliceCompile.h b/project2/ice/sliceCompile.h new file mode 100644 index 0000000..5f11c88 --- /dev/null +++ b/project2/ice/sliceCompile.h @@ -0,0 +1,21 @@ +#ifndef SLICECOMPILE_H +#define SLICECOMPILE_H + +#include "iceCompile.h" +#include <string> +#include <Slice/Parser.h> +#include <Slice/Preprocessor.h> + +class SliceCompile : public IceCompile { + public: + SliceCompile(const boost::filesystem::path & slice, const IceCompile::Deps & dep); + + void Build(const boost::filesystem::path & in, const boost::filesystem::path & out) const; + virtual void Headers(FILE *) const; + virtual void Body(FILE *, Slice::UnitPtr) const = 0; + + boost::filesystem::path InputPath() const; +}; + +#endif + |