Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issues with the use of multiple plugins for publishing and subscribing #1144

Open
HBing110 opened this issue Oct 11, 2023 · 1 comment
Open

Comments

@HBing110
Copy link

HBing110 commented Oct 11, 2023

I want to achieve nested message sending for three plugins through a publish-subscribe mechanism.

I have three plugins: BlogManager, BlogEventHandler and BlogManager1:

  1. BlogManager first send a topic of event to BlogEventHandler by eventAdmin->publishSignal ;

  2. BlogEventHandler receive the topic of event by eventAdmin->subscribeSlot , and send a topic of event to BlogManager1 by eventAdmin->publishSignal

  3. BlogManager1 receive the topic of event by eventAdmin->subscribeSlot


When sending a message from the second step to the third step, a timeout error is returned.
print result and error ['due to timeout']:


BlogEventHandlerActivator::start
BlogEventHandlerActivator::start
BlogEventHandlerActivator::start
BlogManagerActivator::start
BlogManagerActivator::start
BlogEventHandler start ...
BlogManager start ...
BlogManager1 start ...
·***************
BlackList Value Is Empty!!!
BlogManager::publishBlog
start run: 0x526c
QFuture run: 0x4984
BlogEventHandler::handleEvent 1
EventHandler received : title: "CTK Event Admin7771" 0x2624
run over!
10 10 18:10:33 2023 Warning: Blacklisting ServiceReference [1 | Plugin(org.commontk.eventadmin)] due to timeout!
in ctkEABlacklistingHandlerTasks<class ctkEACleanBlackList,class ctkEACacheTopicHandlerFilters<class ctkEALeastRecentlyUsedCacheMap<class QString,class QString> >,class ctkEACacheFilters<class ctkEALeastRecentlyUsedCacheMap<class QString,class ctkLDAPSearchFilter> > >::blackListRef, E:\CodeDevelopment\CTK\CTK-master\Plugins\org.commontk.eventadmin\handler\ctkEABlacklistingHandlerTasks.tpp:104
BlogEventHandler::handleEvent737
EventHandler received777 : title: "blog.title" content: "blog.content" 0x490c


I want to use synchronization to achieve this. Is there any other solution?


plugin --BlogEventHandler code:


blog_even_thandler_activator.h:

#ifndef BLOGEVENTHANDLERACTIVATOR_H
#define BLOGEVENTHANDLERACTIVATOR_H

#include <QObject>
#include "ctkPluginActivator.h"
#include "blog_event_handler.h"
class BlogEventHandlerActivator : public QObject,public ctkPluginActivator
{
    Q_OBJECT
    Q_INTERFACES(ctkPluginActivator)
    Q_PLUGIN_METADATA(IID "BLOG_EVENT_HANDLER")

public:
    void start(ctkPluginContext* context);
    void stop(ctkPluginContext* context);

private:
    BlogEventHandler* pEventHandler;

};

#endif // BLOGEVENTHANDLERACTIVATOR_H

blog_even_thandler_activator.cpp

#include "blog_even_thandler_activator.h"
#include "service/event/ctkEventConstants.h"
void BlogEventHandlerActivator::start(ctkPluginContext* context)
{
    qDebug()<<"BlogEventHandlerActivator::start";

    pEventHandler = new BlogEventHandler();
   pEventHandler->m_pContext = context;
   pEventHandler->init();

    ctkDictionary props;
    props[ctkEventConstants::EVENT_TOPIC] = "liborg/commontk/bloggenerator/published";
    ctkServiceReference ref = context->getServiceReference<ctkEventAdmin>();
    if (ref) {
     ctkEventAdmin* eventAdmin = context->getService<ctkEventAdmin>(ref);
     eventAdmin->subscribeSlot(pEventHandler, SLOT(onBlogPublished(ctkEvent)),
                               props,Qt::DirectConnection);
    }

}

void BlogEventHandlerActivator::stop(ctkPluginContext* context)
{
    Q_UNUSED(context)
    qDebug()<<"BlogEventHandlerActivator::stop";

    delete pEventHandler;
}

blog_event_handler.h

#ifndef BLOG_EVENT_HANDLER_H
#define BLOG_EVENT_HANDLER_H

#include <QObject>
#include <QThread>
#include <service/event/ctkEventHandler.h>
#include <service/event/ctkEventAdmin.h>

#include <ctkPluginContext.h>


class BlogEventHandler : public QObject, public ctkEventHandler
{
    Q_OBJECT
    Q_INTERFACES(ctkEventHandler)

public:
    ctkPluginContext* m_pContext;
    void init()
    {
        ctkServiceReference ref = m_pContext->getServiceReference<ctkEventAdmin>();
        if (ref) {
            ctkEventAdmin* eventAdmin = m_pContext->getService<ctkEventAdmin>(ref);
            eventAdmin->publishSignal(this, SIGNAL(blogPublished(ctkDictionary)),
                "liborg/commontk/bloggenerator/published1",Qt::DirectConnection);
        }
    }

    void handleEvent(const ctkEvent& event) Q_DECL_OVERRIDE
    {
        static int i =0;
        i++;
        qDebug()<<"BlogEventHandler::handleEvent1"<< i;

        if(i==2)
        {
            i=0;
            return;
        }

        QString title = event.getProperty("title").toString();
        QString content = event.getProperty("content").toString();
        QString author = event.getProperty("author").toString();

        qDebug() << "EventHandler received1 :" << "title:" << title  <<QThread::currentThreadId();

        ctkServiceReference ref = m_pContext->getServiceReference<ctkEventAdmin>();
        if (ref) {
            ctkEventAdmin* eventAdmin = m_pContext->getService<ctkEventAdmin>(ref);

            ctkDictionary props;
            props["title"] = "blog.title";
            props["content"] = "blog.content";
            props["author"] = "blog.author";

            blogPublished(props);
        }
    }

 public slots:
    // 处理事件
    void onBlogPublished(const ctkEvent& event)
    {
        static int i =0;
        i++;
        qDebug()<<"BlogEventHandler::handleEvent"<< i;

        if(i==2)
        {
            i=0;
            return;
        }

        QThread::msleep(500);
        QString title = event.getProperty("title").toString();
        QString content = event.getProperty("content").toString();
        QString author = event.getProperty("author").toString();

        qDebug() << "EventHandler received :" << "title:" << title  <<QThread::currentThreadId();

        ctkServiceReference ref = m_pContext->getServiceReference<ctkEventAdmin>();
        if (ref) {
            ctkEventAdmin* eventAdmin = m_pContext->getService<ctkEventAdmin>(ref);

            ctkDictionary props;
            props["title"] = "blog.title";
            props["content"] = "blog.content";
            props["author"] = "blog.author";

            blogPublished(props);
        }
    }

signals:
    void blogPublished(const ctkDictionary&);
};

#endif // BLOG_EVENT_HANDLER_H


plugin --BlogManager code:


blog_manager.h


#ifndef BLOG_MANAGER_H
#define BLOG_MANAGER_H

#include <QObject>
#include <ctkPluginContext.h>
#include <QThread>
#include <service/event/ctkEventHandler.h>

typedef struct Blog_Info {
    QString title;
    QString author;
    QString content;
} Blog;
 
class BlogManager: public QObject, public ctkEventHandler
{
    Q_OBJECT
    Q_INTERFACES(ctkEventHandler)

public:
    BlogManager(ctkPluginContext* context); 
    void publishBlog(const Blog& blog); 
    void handleEvent(const ctkEvent& event) Q_DECL_OVERRIDE ;

private:
    ctkPluginContext* m_pContext;

signals:
 void blogPublished(const ctkDictionary&);
};

#endif // BLOG_MANAGER_H

blog_manager.cpp


#include "blog_manager.h"
#include <service/event/ctkEventAdmin.h>
#include <QtDebug>
#include <QtConcurrent/QtConcurrent>

BlogManager::BlogManager(ctkPluginContext* context)
    : m_pContext(context)
{
    ctkServiceReference ref = context->getServiceReference<ctkEventAdmin>();
     if (ref) {
     ctkEventAdmin* eventAdmin = context->getService<ctkEventAdmin>(ref);
     eventAdmin->publishSignal(this, SIGNAL(blogPublished(ctkDictionary)),
                               "liborg/commontk/bloggenerator/published",Qt::DirectConnection);
     }

}
 
void BlogManager::publishBlog(const Blog& blog)
{
    qDebug()<<"BlogManager::publishBlog";

    ctkServiceReference ref = m_pContext->getServiceReference<ctkEventAdmin>();
    if (ref) {
        ctkEventAdmin* eventAdmin = m_pContext->getService<ctkEventAdmin>(ref);

        ctkDictionary props;
        props["title"] = blog.title+"7771";
        props["content"] = blog.content;
        props["author"] = blog.author;
        ctkEvent event("liborg/commontk/bloggenerator/published", props);


        qDebug() << "start run:" <<QThread::currentThreadId();
        QFuture<void> future = QtConcurrent::run([=]() {
            qDebug() << "QFuture run:" <<QThread::currentThreadId();
            emit blogPublished(props);
        });
        future.waitForFinished();
        qDebug()<<"run over!";
    }
    else
    {
        qDebug()<<"error service";
    }
}

void BlogManager::handleEvent(const ctkEvent& event)
{
    qDebug()<<"BlogEventHandler::handleEvent757";

    QString title = event.getProperty("title").toString();
    QString content = event.getProperty("content").toString();
    QString author = event.getProperty("author").toString();

    qDebug() << "EventHandler received777 :" << "title:" << title << "content:" << content  <<QThread::currentThreadId();
}

blog_manager_activator.h


#ifndef BLOG_MANAGER_ACTIVATOR_H
#define BLOG_MANAGER_ACTIVATOR_H

#include <ctkPluginActivator.h>
//#include "blog_ann_handler.h"


class BlogManager;

class BlogManagerActivator : public QObject, public ctkPluginActivator
{
    Q_OBJECT
    Q_INTERFACES(ctkPluginActivator)
    Q_PLUGIN_METADATA(IID "BLOG_MANAGER")

public:
    void start(ctkPluginContext* context);
    void stop(ctkPluginContext* context);

private:
    BlogManager *m_pBlogManager;
};

#endif // BLOG_MANAGER_ACTIVATOR_H


blog_manager_activator.cpp


#include "blog_manager.h"
#include "blog_manager_activator.h"
#include <QtDebug>
#include <QTimer>
void BlogManagerActivator::start(ctkPluginContext* context)
{


    qDebug()<<"BlogManagerActivator::start";

    m_pBlogManager = new BlogManager(context);


    QTimer* _timer = new QTimer(this);
    _timer->setSingleShot(true);
    connect(_timer, &QTimer::timeout,  [=]()
    {
        Blog blog;
        blog.title = "CTK Event Admin";
        blog.content = "This is a simple blog";
        blog.author = "HBing110";
        m_pBlogManager->publishBlog(blog);
    });
    _timer->start(1000);
}

void BlogManagerActivator::stop(ctkPluginContext* context)
{

    qDebug()<<"BlogManagerActivator::stop";

    Q_UNUSED(context)

    delete m_pBlogManager;
}



plugin --BlogManager1 code:


blog_manager.h


#ifndef BLOG_MANAGER_H
#define BLOG_MANAGER_H

#include <QObject>
#include <ctkPluginContext.h>
#include <QThread>
#include <service/event/ctkEventHandler.h>

typedef struct Blog_Info {
    QString title;
    QString author;
    QString content;
} Blog;
 
class BlogManager: public QObject
{
    Q_OBJECT

public:
    BlogManager(ctkPluginContext* context);

public slots: 
    void onBlogPublished(const ctkEvent& event);
private:
    ctkPluginContext* m_pContext;
};

#endif // BLOG_MANAGER_H

blog_manager.cpp


#include "blog_manager.h"
#include <service/event/ctkEventAdmin.h>
#include <QtDebug> 
#include "service/event/ctkEventConstants.h"
BlogManager::BlogManager(ctkPluginContext* context)
    : m_pContext(context)
{
    ctkDictionary props;
    props[ctkEventConstants::EVENT_TOPIC] = "liborg/commontk/bloggenerator/published1";
    ctkServiceReference ref = context->getServiceReference<ctkEventAdmin>();
    if (ref) {
        ctkEventAdmin* eventAdmin = context->getService<ctkEventAdmin>(ref);
        eventAdmin->subscribeSlot(this, SLOT(onBlogPublished(ctkEvent)),
                                  props,Qt::DirectConnection);
    }
}
 
void BlogManager::onBlogPublished(const ctkEvent& event)
{
    qDebug() << "BlogEventHandler::handleEvent737";

    QString title = event.getProperty("title").toString();
    QString content = event.getProperty("content").toString();
    QString author = event.getProperty("author").toString();

    qDebug() << "EventHandler received777 :" << "title:" << title << "content:" << content << QThread::currentThreadId();

}

blog_manager_activator.h

#ifndef BLOG_MANAGER_ACTIVATOR_H
#define BLOG_MANAGER_ACTIVATOR_H

#include <ctkPluginActivator.h>
//#include "blog_ann_handler.h"


class BlogManager;

class BlogManagerActivator : public QObject, public ctkPluginActivator
{
    Q_OBJECT
    Q_INTERFACES(ctkPluginActivator)
    Q_PLUGIN_METADATA(IID "BLOG_MANAGER11")

public:
    void start(ctkPluginContext* context);
    void stop(ctkPluginContext* context);

private:
    BlogManager *m_pBlogManager;
};

#endif // BLOG_MANAGER_ACTIVATOR_H

blog_manager_activator.cpp

#include "blog_manager.h"
#include "blog_manager_activator.h"
#include <QtDebug>
#include <QTimer>
void BlogManagerActivator::start(ctkPluginContext* context)
{


    qDebug()<<"BlogManagerActivator::start";

    m_pBlogManager = new BlogManager(context);

}

void BlogManagerActivator::stop(ctkPluginContext* context)
{

    qDebug()<<"BlogManagerActivator::stop";

    Q_UNUSED(context)

    delete m_pBlogManager;
}


test program

main.cpp


#include <QCoreApplication>
#include "ctkPluginException.h"
#include "ctkPluginContext.h"
#include <QDirIterator>
#include <QDebug>
#include "ctkPluginFrameworkLauncher.h"

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);

    QString path = QCoreApplication::applicationDirPath() + "/plugins";

    ctkPluginFrameworkLauncher::addSearchPath("./../ctk-0.1/plugins");
 
    ctkPluginFrameworkLauncher::start("org.commontk.eventadmin"); 
    ctkPluginContext* context = ctkPluginFrameworkLauncher::getPluginContext();

 
    try {
        QSharedPointer<ctkPlugin> plugin = context->installPlugin(QUrl::fromLocalFile(path + "/BlogEventHandler.dll"));
        plugin->start();
        qDebug() << "BlogEventHandler start ...";
    } catch (const ctkPluginException &e) {
        qDebug() << "Failed to start BlogEventHandler" << e.what();
    }

    try {
        QSharedPointer<ctkPlugin> plugin = context->installPlugin(QUrl::fromLocalFile(path + "/BlogManager.dll"));
        plugin->start();

        qDebug() << "BlogManager start ...";
    } catch (const ctkPluginException &e) {
        qDebug() << "Failed to start BlogManager" << e.what();
    }

 
   try {
       QSharedPointer<ctkPlugin> plugin = context->installPlugin(QUrl::fromLocalFile(path + "/BlogManager1.dll"));
       plugin->start();

       qDebug() << "BlogManager1 start ...";
   } catch (const ctkPluginException &e) {
       qDebug() << "Failed to start BlogManager1" << e.what();
   }

    qDebug() << "***************";



    return app.exec();
    return 1;
}

@jcfr
Copy link
Member

jcfr commented Oct 25, 2023

Thanks for the report

To help the community better understand the problem and answer your question, could you create a standalone project on GitHub allowing to reproduce the issue ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants