File indexing completed on 2024-04-28 15:15:37

0001 // SPDX-FileCopyrightText: 2009 Jens-Michael Hoffmann <jmho@c-xx.com>
0002 //
0003 // SPDX-License-Identifier: LGPL-2.1-or-later
0004 
0005 #ifndef MARBLE_DOWNLOADQUEUESET_H
0006 #define MARBLE_DOWNLOADQUEUESET_H
0007 
0008 #include <QList>
0009 #include <QQueue>
0010 #include <QObject>
0011 #include <QSet>
0012 #include <QStack>
0013 
0014 #include "DownloadPolicy.h"
0015 
0016 class QUrl;
0017 
0018 namespace Marble
0019 {
0020 
0021 class HttpJob;
0022 
0023 /**
0024    Life of a HttpJob
0025    =================
0026    - Job is added to the QueueSet (by calling addJob() )
0027      the HttpJob is put into the m_jobQueue where it waits for "activation"
0028      signal jobAdded is emitted
0029    - Job is activated
0030      Job is moved from m_jobQueue to m_activeJobs and signals of the job
0031      are connected to slots (local or HttpDownloadManager)
0032      Job is executed by calling the jobs execute() method
0033 
0034    now there are different possibilities:
0035    1) Job emits jobDone (some error occurred, or canceled (kio))
0036       Job is disconnected
0037       signal jobRemoved is emitted
0038       Job is either moved from m_activeJobs to m_retryQueue
0039         or destroyed and blacklisted
0040 
0041    2) Job emits redirected
0042       Job is removed from m_activeJobs, disconnected and destroyed
0043       signal jobRemoved is emitted
0044       (HttpDownloadManager creates new Job with new source url)
0045 
0046    3) Job emits dataReceived
0047       Job is removed from m_activeJobs, disconnected and destroyed
0048       signal jobRemoved is emitted
0049 
0050    so we can conclude following rules:
0051    - Job is only connected to signals when in "active" state
0052 
0053 
0054    questions:
0055    - update of initiatorId needed?
0056      "We update the initiatorId as the previous initiator
0057       likely doesn't exist anymore"
0058    - blacklist or black list?
0059 
0060  */
0061 
0062 class DownloadQueueSet: public QObject
0063 {
0064     Q_OBJECT
0065 
0066  public:
0067     explicit DownloadQueueSet( QObject * const parent = nullptr );
0068     explicit DownloadQueueSet( const DownloadPolicy& policy, QObject * const parent = nullptr );
0069     ~DownloadQueueSet() override;
0070 
0071     DownloadPolicy downloadPolicy() const;
0072     void setDownloadPolicy( const DownloadPolicy& );
0073 
0074     bool canAcceptJob( const QUrl& sourceUrl,
0075                        const QString& destinationFileName ) const;
0076     void addJob( HttpJob * const job );
0077 
0078     void activateJobs();
0079     void retryJobs();
0080     void purgeJobs();
0081 
0082  Q_SIGNALS:
0083     void jobAdded();
0084     void jobRemoved();
0085     void jobRetry();
0086     void jobFinished( const QByteArray& data, const QString& destinationFileName,
0087                       const QString& id );
0088     void jobRedirected( const QUrl& newSourceUrl, const QString& destinationFileName,
0089                         const QString& id, DownloadUsage );
0090     void progressChanged( int active, int queued );
0091 
0092  private Q_SLOTS:
0093     void finishJob( HttpJob * job, const QByteArray& data );
0094     void redirectJob( HttpJob * job, const QUrl& newSourceUrl );
0095     void retryOrBlacklistJob( HttpJob * job, const int errorCode );
0096 
0097  private:
0098     void activateJob( HttpJob * const job );
0099     void deactivateJob( HttpJob * const job );
0100     bool jobIsActive( const QString& destinationFileName ) const;
0101     bool jobIsQueued( const QString& destinationFileName ) const;
0102     bool jobIsWaitingForRetry( const QString& destinationFileName ) const;
0103     bool jobIsBlackListed( const QUrl& sourceUrl ) const;
0104 
0105     DownloadPolicy m_downloadPolicy;
0106 
0107     /** This is the first stage a job enters, from this queue it will get
0108      *  into the activatedJobs container.
0109      */
0110     class JobStack
0111     {
0112     public:
0113         bool contains( const QString& destinationFileName ) const;
0114         int count() const;
0115         bool isEmpty() const;
0116         HttpJob * pop();
0117         void push( HttpJob * const );
0118     private:
0119         QStack<HttpJob*> m_jobs;
0120         QSet<QString> m_jobsContent;
0121     };
0122     JobStack m_jobs;
0123 
0124     /// Contains the jobs which are currently being downloaded.
0125     QList<HttpJob*> m_activeJobs;
0126 
0127     /** Contains jobs which failed to download and which are scheduled for
0128      *  retry according to retry settings.
0129      */
0130     QQueue<HttpJob*> m_retryQueue;
0131 
0132     /// Contains the blacklisted source urls
0133     QSet<QString> m_jobBlackList;
0134 };
0135 
0136 }
0137 
0138 #endif