Ejemplo n.º 1
0
void Listener::checkConnections()
{
    if (m_connections.isEmpty()) {
        m_server->close();
        emit noClients();
    }
}
Ejemplo n.º 2
0
Listener::Listener(const QString &resourceName, QObject *parent)
    : QObject(parent),
      m_server(new QLocalServer(this)),
      m_resourceName(resourceName),
      m_resource(0),
      m_pipeline(new Akonadi2::Pipeline(resourceName, parent)),
      m_clientBufferProcessesTimer(new QTimer(this)),
      m_messageId(0)
{
    connect(m_pipeline, &Akonadi2::Pipeline::revisionUpdated,
            this, &Listener::refreshRevision);
    connect(m_server, &QLocalServer::newConnection,
             this, &Listener::acceptConnection);
    log(QString("Trying to open %1").arg(resourceName));
    if (!m_server->listen(resourceName)) {
        // FIXME: multiple starts need to be handled here
        m_server->removeServer(resourceName);
        if (!m_server->listen(resourceName)) {
            log("Utter failure to start server");
            exit(-1);
        }
    }

    if (m_server->isListening()) {
        log(QString("Listening on %1").arg(m_server->serverName()));
    }

    m_checkConnectionsTimer = new QTimer;
    m_checkConnectionsTimer->setSingleShot(true);
    m_checkConnectionsTimer->setInterval(1000);
    connect(m_checkConnectionsTimer, &QTimer::timeout, [this]() {
        if (m_connections.isEmpty()) {
            log(QString("No connections, shutting down."));
            m_server->close();
            emit noClients();
        }
    });

    //TODO: experiment with different timeouts
    //      or even just drop down to invoking the method queued? => invoke queued unless we need throttling
    m_clientBufferProcessesTimer->setInterval(0);
    m_clientBufferProcessesTimer->setSingleShot(true);
    connect(m_clientBufferProcessesTimer, &QTimer::timeout,
            this, &Listener::processClientBuffers);
}
Ejemplo n.º 3
0
void Listener::processCommand(int commandId, uint messageId, Client &client, uint size, const std::function<void()> &callback)
{
    switch (commandId) {
        case Akonadi2::Commands::HandshakeCommand: {
            flatbuffers::Verifier verifier((const uint8_t *)client.commandBuffer.constData(), size);
            if (Akonadi2::VerifyHandshakeBuffer(verifier)) {
                auto buffer = Akonadi2::GetHandshake(client.commandBuffer.constData());
                client.name = buffer->name()->c_str();
                sendCurrentRevision(client);
            } else {
                qWarning() << "received invalid command";
            }
            break;
        }
        case Akonadi2::Commands::SynchronizeCommand: {
            flatbuffers::Verifier verifier((const uint8_t *)client.commandBuffer.constData(), size);
            if (Akonadi2::VerifySynchronizeBuffer(verifier)) {
                auto buffer = Akonadi2::GetSynchronize(client.commandBuffer.constData());
                log(QString("\tSynchronize request (id %1) from %2").arg(messageId).arg(client.name));
                loadResource();
                if (!m_resource) {
                    qWarning() << "No resource loaded";
                    break;
                }
                //TODO a more elegant composition of jobs should be possible
                if (buffer->sourceSync()) {
                    bool localSync = buffer->localSync();
                    m_resource->synchronizeWithSource(m_pipeline).then<void>([callback, localSync, this](Async::Future<void> &f){
                        if (localSync) {
                            m_resource->processAllMessages().then<void>([callback](Async::Future<void> &f){
                                callback();
                                f.setFinished();
                            }).exec();
                        } else {
                            callback();
                            f.setFinished();
                        }
                    }).exec();
                } else if (buffer->localSync()) {
                    m_resource->processAllMessages().then<void>([callback](Async::Future<void> &f){
                        callback();
                        f.setFinished();
                    }).exec();
                }
                return;
            } else {
                qWarning() << "received invalid command";
            }
            break;
        }
        case Akonadi2::Commands::FetchEntityCommand:
        case Akonadi2::Commands::DeleteEntityCommand:
        case Akonadi2::Commands::ModifyEntityCommand:
        case Akonadi2::Commands::CreateEntityCommand:
            log(QString("\tCommand id %1 of type %2 from %3").arg(messageId).arg(commandId).arg(client.name));
            loadResource();
            if (m_resource) {
                m_resource->processCommand(commandId, client.commandBuffer, size, m_pipeline);
            }
            break;
        case Akonadi2::Commands::ShutdownCommand:
            log(QString("\tReceived shutdown command from %1").arg(client.name));
            callback();
            m_server->close();
            emit noClients();
            return;
        default:
            if (commandId > Akonadi2::Commands::CustomCommand) {
                loadResource();
                if (m_resource) {
                    m_resource->processCommand(commandId, client.commandBuffer, size, m_pipeline);
                }
            } else {
                //TODO: handle error: we don't know wtf this command is
            }
            break;
    }
    callback();
}