File indexing completed on 2024-05-12 05:26:03

0001 /*
0002  * Copyright (C) 2014 Aaron Seigo <aseigo@kde.org>
0003  *
0004  * This library is free software; you can redistribute it and/or
0005  * modify it under the terms of the GNU Lesser General Public
0006  * License as published by the Free Software Foundation; either
0007  * version 2.1 of the License, or (at your option) version 3, or any
0008  * later version accepted by the membership of KDE e.V. (or its
0009  * successor approved by the membership of KDE e.V.), which shall
0010  * act as a proxy defined in Section 6 of version 3 of the license.
0011  *
0012  * This library is distributed in the hope that it will be useful,
0013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015  * Lesser General Public License for more details.
0016  *
0017  * You should have received a copy of the GNU Lesser General Public
0018  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
0019  */
0020 
0021 #pragma once
0022 
0023 #include "sink_export.h"
0024 #include <QLocalSocket>
0025 #include <QObject>
0026 #include <QTimer>
0027 
0028 #include <KAsync/Async>
0029 
0030 #include <flatbuffers/flatbuffers.h>
0031 #include "notification.h"
0032 #include "flush.h"
0033 #include "query.h"
0034 #include "log.h"
0035 
0036 namespace Sink {
0037 
0038 struct QueuedCommand;
0039 
0040 class SINK_EXPORT ResourceAccessInterface : public QObject
0041 {
0042     Q_OBJECT
0043 public:
0044     typedef QSharedPointer<ResourceAccessInterface> Ptr;
0045 
0046     ResourceAccessInterface()
0047         : QObject()
0048     {
0049     }
0050     virtual ~ResourceAccessInterface()
0051     {
0052     }
0053     virtual KAsync::Job<void> sendCommand(int commandId) = 0;
0054     virtual KAsync::Job<void> sendCommand(int commandId, flatbuffers::FlatBufferBuilder &fbb) = 0;
0055     virtual KAsync::Job<void> synchronizeResource(const Sink::QueryBase &filter) = 0;
0056 
0057     virtual KAsync::Job<void> sendCreateCommand(const QByteArray &uid, const QByteArray &resourceBufferType, const QByteArray &buffer)
0058     {
0059         return KAsync::null<void>();
0060     };
0061     virtual KAsync::Job<void> sendModifyCommand(const QByteArray &uid, qint64 revision, const QByteArray &resourceBufferType, const QByteArrayList &deletedProperties, const QByteArray &buffer, const QByteArrayList &changedProperties, const QByteArray &newResource, bool remove)
0062     {
0063         return KAsync::null<void>();
0064     };
0065     virtual KAsync::Job<void> sendDeleteCommand(const QByteArray &uid, qint64 revision, const QByteArray &resourceBufferType)
0066     {
0067         return KAsync::null<void>();
0068     };
0069     virtual KAsync::Job<void> sendRevisionReplayedCommand(qint64 revision)
0070     {
0071         return KAsync::null<void>();
0072     };
0073     virtual KAsync::Job<void>
0074     sendInspectionCommand(int inspectionType, const QByteArray &inspectionId, const QByteArray &domainType, const QByteArray &entityId, const QByteArray &property, const QVariant &expecedValue)
0075     {
0076         return KAsync::null<void>();
0077     };
0078 
0079     virtual KAsync::Job<void> sendFlushCommand(int flushType, const QByteArray &flushId)
0080     {
0081         return KAsync::null<void>();
0082     }
0083 
0084     virtual KAsync::Job<void> sendSecret(const QString &secret)
0085     {
0086         return KAsync::null<void>();
0087     }
0088 
0089     virtual KAsync::Job<void> shutdown()
0090     {
0091         return KAsync::null<void>();
0092     }
0093 
0094     int getResourceStatus() const
0095     {
0096         return mResourceStatus;
0097     }
0098 
0099 signals:
0100     void ready(bool isReady);
0101     void revisionChanged(qint64 revision);
0102     void notification(Notification notification);
0103 
0104 public slots:
0105     virtual void open() = 0;
0106     virtual void close() = 0;
0107 
0108 protected:
0109     int mResourceStatus;
0110 };
0111 
0112 class SINK_EXPORT ResourceAccess : public ResourceAccessInterface
0113 {
0114     Q_OBJECT
0115 public:
0116     typedef QSharedPointer<ResourceAccess> Ptr;
0117 
0118     ResourceAccess(const QByteArray &resourceInstanceIdentifier, const QByteArray &resourceType);
0119     virtual ~ResourceAccess() Q_DECL_OVERRIDE;
0120 
0121     QByteArray resourceName() const;
0122     bool isReady() const;
0123 
0124     KAsync::Job<void> sendCommand(int commandId) Q_DECL_OVERRIDE;
0125     KAsync::Job<void> sendCommand(int commandId, flatbuffers::FlatBufferBuilder &fbb) Q_DECL_OVERRIDE;
0126     KAsync::Job<void> synchronizeResource(const Sink::QueryBase &filter) Q_DECL_OVERRIDE;
0127     KAsync::Job<void> sendCreateCommand(const QByteArray &uid, const QByteArray &resourceBufferType, const QByteArray &buffer) Q_DECL_OVERRIDE;
0128     KAsync::Job<void>
0129     sendModifyCommand(const QByteArray &uid, qint64 revision, const QByteArray &resourceBufferType, const QByteArrayList &deletedProperties, const QByteArray &buffer, const QByteArrayList &changedProperties, const QByteArray &newResource, bool remove) Q_DECL_OVERRIDE;
0130     KAsync::Job<void> sendDeleteCommand(const QByteArray &uid, qint64 revision, const QByteArray &resourceBufferType) Q_DECL_OVERRIDE;
0131     KAsync::Job<void> sendRevisionReplayedCommand(qint64 revision) Q_DECL_OVERRIDE;
0132     KAsync::Job<void>
0133     sendInspectionCommand(int inspectionType,const QByteArray &inspectionId, const QByteArray &domainType, const QByteArray &entityId, const QByteArray &property, const QVariant &expecedValue) Q_DECL_OVERRIDE;
0134     KAsync::Job<void> sendFlushCommand(int flushType, const QByteArray &flushId) Q_DECL_OVERRIDE;
0135     KAsync::Job<void> sendSecret(const QString &secret) Q_DECL_OVERRIDE;
0136     KAsync::Job<void> shutdown() Q_DECL_OVERRIDE;
0137     /**
0138      * Tries to connect to server, and returns a connected socket on success.
0139      */
0140     static KAsync::Job<QSharedPointer<QLocalSocket>> connectToServer(const QByteArray &identifier);
0141 
0142 public slots:
0143     void open() Q_DECL_OVERRIDE;
0144     void close() Q_DECL_OVERRIDE;
0145 
0146 private slots:
0147     // TODO: move these to the Private class
0148     void disconnected();
0149     void connectionError(QLocalSocket::LocalSocketError error);
0150     void readResourceMessage();
0151     bool processMessageBuffer();
0152 
0153 private:
0154     void abort();
0155     void connected();
0156     void registerCallback(uint messageId, const std::function<void(int error, const QString &)> &callback);
0157 
0158     void sendCommand(const QSharedPointer<QueuedCommand> &command);
0159     void processCommandQueue();
0160     void processPendingCommandQueue();
0161     void enqueueCommand(const QSharedPointer<QueuedCommand> &command);
0162 
0163     class Private;
0164     Private *const d;
0165 };
0166 
0167 /**
0168  * A factory for resource access instances that caches the instance for some time.
0169  *
0170  * This avoids constantly recreating connections, and should allow a single process to have one connection per resource.
0171  */
0172 class SINK_EXPORT ResourceAccessFactory
0173 {
0174 public:
0175     static ResourceAccessFactory &instance();
0176     Sink::ResourceAccess::Ptr getAccess(const QByteArray &instanceIdentifier, const QByteArray resourceType);
0177 
0178 private:
0179     ResourceAccessFactory();
0180 
0181     QHash<QByteArray, QWeakPointer<Sink::ResourceAccess>> mWeakCache;
0182     QHash<QByteArray, Sink::ResourceAccess::Ptr> mCache;
0183     QHash<QByteArray, QSharedPointer<QTimer>> mTimer;
0184 };
0185 }