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 +  | 
