From 9e761ea6eb78cdd84bc05cbd77185823b010d96f Mon Sep 17 00:00:00 2001 From: Ramin Yaghoubzadeh <ryaghoub@techfak.uni-bielefeld.de> Date: Fri, 13 Apr 2012 00:20:17 +0200 Subject: [PATCH] C++: user space handlers work fine --- cpp/src/ipaaca-test-main.cc | 14 ++++-- cpp/src/ipaaca.cc | 98 ++++++++++++++++++++++++++++++++++--- cpp/src/ipaaca.h | 62 +++++++++++++++++++++-- 3 files changed, 158 insertions(+), 16 deletions(-) diff --git a/cpp/src/ipaaca-test-main.cc b/cpp/src/ipaaca-test-main.cc index 4000a09..c6acfcf 100644 --- a/cpp/src/ipaaca-test-main.cc +++ b/cpp/src/ipaaca-test-main.cc @@ -12,12 +12,16 @@ using namespace ipaaca; #ifdef MAKE_RECEIVER +void my_first_iu_handler(IUInterface::ptr iu, IUEventType type, bool local) +{ + std::cout << "[32m" << iu_event_type_to_str(type) << "[m" << std::endl; +} int main() { try{ initialize_ipaaca_rsb(); - InputBuffer ib("Tester", "testcategory"); - + InputBuffer::ptr ib = InputBuffer::create("Tester", "testcategory"); + ib->register_handler(my_first_iu_handler); while (true) { sleep(1); @@ -34,11 +38,11 @@ int main() { initialize_ipaaca_rsb(); - OutputBuffer ob("Tester"); - std::cout << "Buffer: " << ob.unique_name() << std::endl; + OutputBuffer::ptr ob = OutputBuffer::create("Tester"); + std::cout << "Buffer: " << ob->unique_name() << std::endl; IU::ref iu = IU::create("testcategory"); - ob.add(iu); + ob->add(iu); std::cout << "_payload.get(\"TEST\") = \"" << iu->_payload.get("TEST") << "\"" << std::endl; std::cout << "_payload[\"TEST\"] = \"" << (std::string) iu->_payload["TEST"] << "\"" << std::endl; diff --git a/cpp/src/ipaaca.cc b/cpp/src/ipaaca.cc index 10c6cfc..ffc0ddf 100644 --- a/cpp/src/ipaaca.cc +++ b/cpp/src/ipaaca.cc @@ -176,6 +176,36 @@ void SmartLinkMap::_replace_links(const LinkMap& links) } //}}} +// IUEventHandler//{{{ +IUEventHandler::IUEventHandler(IUEventHandlerFunction function, IUEventType event_mask, const std::string& category) +: _function(function), _event_mask(event_mask), _for_all_categories(false) +{ + if (category=="") { + _for_all_categories = true; + } else { + _categories.insert(category); + } +} +IUEventHandler::IUEventHandler(IUEventHandlerFunction function, IUEventType event_mask, const std::set<std::string>& categories) +: _function(function), _event_mask(event_mask), _for_all_categories(false) +{ + if (categories.size()==0) { + _for_all_categories = true; + } else { + _categories = categories; + } +} +void IUEventHandler::call(Buffer* buffer, boost::shared_ptr<IUInterface> iu, bool local, IUEventType event_type, const std::string& category) +{ + if (_condition_met(event_type, category)) { + //IUInterface::ptr iu = buffer->get(uid); + //if (iu) { + _function(iu, event_type, local); + //} + } +} +//}}} + // Buffer//{{{ void Buffer::_allocate_unique_name(const std::string& basename, const std::string& function) { std::string uuid = ipaaca::generate_uuid_string(); @@ -183,6 +213,16 @@ void Buffer::_allocate_unique_name(const std::string& basename, const std::strin _uuid = uuid.substr(0,8); _unique_name = basename + "ID" + _uuid + "/" + function; } +void Buffer::register_handler(IUEventHandlerFunction function, IUEventType event_mask, const std::set<std::string>& categories) +{ + IUEventHandler::ptr handler = IUEventHandler::ptr(new IUEventHandler(function, event_mask, categories)); + _event_handlers.push_back(handler); +} +void Buffer::register_handler(IUEventHandlerFunction function, IUEventType event_mask, const std::string& category) +{ + IUEventHandler::ptr handler = IUEventHandler::ptr(new IUEventHandler(function, event_mask, category)); + _event_handlers.push_back(handler); +} //}}} // OutputBuffer//{{{ @@ -192,6 +232,16 @@ OutputBuffer::OutputBuffer(const std::string& basename) { _id_prefix = _basename + "-" + _uuid + "-IU-"; } +OutputBuffer::ptr OutputBuffer::create(const std::string& basename) +{ + return OutputBuffer::ptr(new OutputBuffer(basename)); +} +IUInterface::ptr OutputBuffer::get(const std::string& iu_uid) +{ + IUStore::iterator it = _iu_store.find(iu_uid); + if (it==_iu_store.end()) return IUInterface::ptr(); + return it->second; +} void OutputBuffer::_send_iu_link_update(IUInterface* iu, bool is_delta, revision_t revision, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name) { @@ -363,6 +413,36 @@ InputBuffer::InputBuffer(const std::string& basename, const std::string& categor _create_category_listener_if_needed(category_interest4); } + +InputBuffer::ptr InputBuffer::create(const std::string& basename, const std::vector<std::string>& category_interests) +{ + return InputBuffer::ptr(new InputBuffer(basename, category_interests)); +} +InputBuffer::ptr InputBuffer::create(const std::string& basename, const std::string& category_interest1) +{ + return InputBuffer::ptr(new InputBuffer(basename, category_interest1)); +} +InputBuffer::ptr InputBuffer::create(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2) +{ + return InputBuffer::ptr(new InputBuffer(basename, category_interest1, category_interest2)); +} +InputBuffer::ptr InputBuffer::create(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2, const std::string& category_interest3) +{ + return InputBuffer::ptr(new InputBuffer(basename, category_interest1, category_interest2, category_interest3)); +} +InputBuffer::ptr InputBuffer::create(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2, const std::string& category_interest3, const std::string& category_interest4) +{ + return InputBuffer::ptr(new InputBuffer(basename, category_interest1, category_interest2, category_interest3, category_interest4)); +} + +IUInterface::ptr InputBuffer::get(const std::string& iu_uid) +{ + RemotePushIUStore::iterator it = _iu_store.find(iu_uid); // TODO genericize + if (it==_iu_store.end()) return IUInterface::ptr(); + return it->second; +} + + RemoteServerPtr InputBuffer::_get_remote_server(boost::shared_ptr<IU> iu) { IPAACA_IMPLEMENT_ME @@ -397,9 +477,15 @@ ListenerPtr InputBuffer::_create_category_listener_if_needed(const std::string& return cat_listener */ } -void InputBuffer::call_iu_event_handlers(const std::string& uid, bool local, IUEventType event_type, const std::string& category) +void InputBuffer::call_iu_event_handlers(boost::shared_ptr<IUInterface> iu, bool local, IUEventType event_type, const std::string& category) { - IPAACA_INFO("handling an event " << ipaaca::iu_event_type_to_str(event_type) << " for IU " << uid) + IPAACA_INFO("handling an event " << ipaaca::iu_event_type_to_str(event_type) << " for IU " << iu->uid()) + //IUInterface::ptr iu = buffer->get(uid); + //if (iu) { + for (std::vector<IUEventHandler::ptr>::iterator it = _event_handlers.begin(); it != _event_handlers.end(); ++it) { + (*it)->call(this, iu, local, event_type, category); + } + //} } void InputBuffer::_handle_iu_events(EventPtr event) { @@ -411,7 +497,7 @@ void InputBuffer::_handle_iu_events(EventPtr event) } else { _iu_store[iu->uid()] = iu; iu->_set_buffer(this); - call_iu_event_handlers(iu->uid(), false, IU_ADDED, iu->category() ); + call_iu_event_handlers(iu, false, IU_ADDED, iu->category() ); } IPAACA_INFO( "New RemotePushIU state: " << (*iu) ) } else { @@ -429,7 +515,7 @@ void InputBuffer::_handle_iu_events(EventPtr event) } // it->second->_apply_update(update); - call_iu_event_handlers(it->second->uid(), false, IU_UPDATED, it->second->category() ); + call_iu_event_handlers(it->second, false, IU_UPDATED, it->second->category() ); // // } else if (type == "ipaaca::IULinkUpdate") { @@ -445,7 +531,7 @@ void InputBuffer::_handle_iu_events(EventPtr event) } // it->second->_apply_link_update(update); - call_iu_event_handlers(it->second->uid(), false, IU_LINKSUPDATED, it->second->category() ); + call_iu_event_handlers(it->second, false, IU_LINKSUPDATED, it->second->category() ); // // } else if (type == "ipaaca::protobuf::IUCommission") { @@ -462,7 +548,7 @@ void InputBuffer::_handle_iu_events(EventPtr event) // it->second->_apply_commission(); it->second->_revision = update->revision(); - call_iu_event_handlers(it->second->uid(), false, IU_COMMITTED, it->second->category() ); + call_iu_event_handlers(it->second, false, IU_COMMITTED, it->second->category() ); // // } else { diff --git a/cpp/src/ipaaca.h b/cpp/src/ipaaca.h index 29dffbe..e49385d 100644 --- a/cpp/src/ipaaca.h +++ b/cpp/src/ipaaca.h @@ -46,6 +46,18 @@ namespace ipaaca { typedef uint32_t revision_t; +typedef uint32_t IUEventType; + +#define IU_ADDED 1 +#define IU_COMMITTED 2 +#define IU_DELETED 4 +#define IU_RETRACTED 8 +#define IU_UPDATED 16 +#define IU_LINKSUPDATED 32 +// +#define IU_ALL_EVENTS 63 + +/* enum IUEventType { IU_ADDED, IU_COMMITTED, @@ -54,6 +66,8 @@ enum IUEventType { IU_UPDATED, IU_LINKSUPDATED }; +*/ + inline std::string iu_event_type_to_str(IUEventType type) { switch(type) { @@ -63,7 +77,7 @@ inline std::string iu_event_type_to_str(IUEventType type) case IU_RETRACTED: return "RETRACTED"; case IU_UPDATED: return "UPDATED"; case IU_LINKSUPDATED: return "LINKSUPDATED"; - default: return "(IU_EVENT_TYPE_UNKNOWN)"; + default: return "(NOT A KNOWN SINGLE IU EVENT TYPE)"; } } @@ -90,7 +104,6 @@ class IUPayloadUpdate; class IUPayloadUpdateConverter; class IUStore; class FrozenIUStore; -class IUEventHandler; class Buffer; class InputBuffer; class OutputBuffer; @@ -148,6 +161,28 @@ class SmartLinkMap { const LinkSet EMPTY_LINK_SET; //const std::set<std::string> EMPTY_LINK_SET; +//typedef boost::function<void (const std::string&, bool, IUEventType, const std::string&)> IUEventHandlerFunction; +typedef boost::function<void (boost::shared_ptr<IUInterface>, IUEventType, bool)> IUEventHandlerFunction; + +class IUEventHandler { + protected: + IUEventHandlerFunction _function; + IUEventType _event_mask; + bool _for_all_categories; + std::set<std::string> _categories; + protected: + inline bool _condition_met(IUEventType event_type, const std::string& category) + { + return ((_event_mask&event_type)!=0) && (_for_all_categories || (_categories.count(category)>0)); + } + public: + IUEventHandler(IUEventHandlerFunction function, IUEventType event_mask, const std::string& category); + IUEventHandler(IUEventHandlerFunction function, IUEventType event_mask, const std::set<std::string>& categories); + //void call(Buffer* buffer, const std::string& uid, bool local, IUEventType event_type, const std::string& category); + void call(Buffer* buffer, boost::shared_ptr<IUInterface> iu, bool local, IUEventType event_type, const std::string& category); + typedef boost::shared_ptr<IUEventHandler> ptr; +}; + class Buffer { //: public boost::enable_shared_from_this<Buffer> {//{{{ friend class IU; friend class RemotePushIU; @@ -156,6 +191,7 @@ class Buffer { //: public boost::enable_shared_from_this<Buffer> {//{{{ std::string _basename; std::string _unique_name; std::string _id_prefix; + std::vector<IUEventHandler::ptr> _event_handlers; protected: _IPAACA_ABSTRACT_ virtual void _send_iu_link_update(IUInterface* iu, bool is_delta, revision_t revision, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name="undef") = 0; _IPAACA_ABSTRACT_ virtual void _send_iu_payload_update(IUInterface* iu, bool is_delta, revision_t revision, const std::map<std::string, std::string>& new_items, const std::vector<std::string>& keys_to_remove, const std::string& writer_name="undef") = 0; @@ -167,7 +203,10 @@ class Buffer { //: public boost::enable_shared_from_this<Buffer> {//{{{ public: virtual inline ~Buffer() { } inline const std::string& unique_name() { return _unique_name; } + void register_handler(IUEventHandlerFunction function, IUEventType event_mask, const std::set<std::string>& categories); + void register_handler(IUEventHandlerFunction function, IUEventType event_mask = IU_ALL_EVENTS, const std::string& category=""); //_IPAACA_ABSTRACT_ virtual void add(boost::shared_ptr<IUInterface> iu) = 0; + _IPAACA_ABSTRACT_ virtual boost::shared_ptr<IUInterface> get(const std::string& iu_uid) = 0; }; //}}} @@ -191,14 +230,18 @@ class OutputBuffer: public Buffer { //, public boost::enable_shared_from_this<Ou void _publish_iu(boost::shared_ptr<IU> iu); void _retract_iu(boost::shared_ptr<IU> iu); Informer<AnyType>::Ptr _get_informer(const std::string& category); - public: + protected: OutputBuffer(const std::string& basename); + public: + static boost::shared_ptr<OutputBuffer> create(const std::string& basename); ~OutputBuffer() { IPAACA_IMPLEMENT_ME } void add(boost::shared_ptr<IU> iu); boost::shared_ptr<IU> remove(const std::string& iu_uid); boost::shared_ptr<IU> remove(boost::shared_ptr<IU> iu); + boost::shared_ptr<IUInterface> get(const std::string& iu_uid); + typedef boost::shared_ptr<OutputBuffer> ptr; }; //}}} @@ -225,20 +268,28 @@ class InputBuffer: public Buffer { //, public boost::enable_shared_from_this<Inp RemoteServerPtr _get_remote_server(boost::shared_ptr<IU> iu); ListenerPtr _create_category_listener_if_needed(const std::string& category); void _handle_iu_events(EventPtr event); - void call_iu_event_handlers(const std::string& uid, bool local, IUEventType event_type, const std::string& category); - public: + void call_iu_event_handlers(boost::shared_ptr<IUInterface> iu, bool local, IUEventType event_type, const std::string& category); + protected: InputBuffer(const std::string& basename, const std::vector<std::string>& category_interests); InputBuffer(const std::string& basename, const std::string& category_interest1); InputBuffer(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2); InputBuffer(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2, const std::string& category_interest3); InputBuffer(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2, const std::string& category_interest3, const std::string& category_interest4); + public: + static boost::shared_ptr<InputBuffer> create(const std::string& basename, const std::vector<std::string>& category_interests); + static boost::shared_ptr<InputBuffer> create(const std::string& basename, const std::string& category_interest1); + static boost::shared_ptr<InputBuffer> create(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2); + static boost::shared_ptr<InputBuffer> create(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2, const std::string& category_interest3); + static boost::shared_ptr<InputBuffer> create(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2, const std::string& category_interest3, const std::string& category_interest4); ~InputBuffer() { IPAACA_IMPLEMENT_ME } + boost::shared_ptr<IUInterface> get(const std::string& iu_uid); //inline void add(boost::shared_ptr<IU> iu) //{ // IPAACA_IMPLEMENT_ME //} + typedef boost::shared_ptr<InputBuffer> ptr; }; //}}} @@ -391,6 +442,7 @@ class IUInterface {//{{{ // (with cpp specific convenience functions:) void add_link(const std::string& type, const std::string& target, const std::string& writer_name = ""); void remove_link(const std::string& type, const std::string& target, const std::string& writer_name = ""); + typedef boost::shared_ptr<IUInterface> ptr; };//}}} class IU: public IUInterface {//{{{ -- GitLab