• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepimlibs API Reference
  • KDE Home
  • Contact Us
 

akonadi

  • sources
  • kde-4.14
  • kdepimlibs
  • akonadi
transactionsequence.cpp
1 /*
2  Copyright (c) 2006-2008 Volker Krause <vkrause@kde.org>
3 
4  This library is free software; you can redistribute it and/or modify it
5  under the terms of the GNU Library General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or (at your
7  option) any later version.
8 
9  This library is distributed in the hope that it will be useful, but WITHOUT
10  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12  License for more details.
13 
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB. If not, write to the
16  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  02110-1301, USA.
18 */
19 
20 #include "transactionsequence.h"
21 #include "transactionjobs.h"
22 
23 #include "job_p.h"
24 
25 #include <QtCore/QSet>
26 #include <QtCore/QVariant>
27 
28 using namespace Akonadi;
29 
30 class Akonadi::TransactionSequencePrivate : public JobPrivate
31 {
32 public:
33  TransactionSequencePrivate(TransactionSequence *parent)
34  : JobPrivate(parent)
35  , mState(Idle)
36  , mAutoCommit(true)
37  {
38  }
39 
40  enum TransactionState {
41  Idle,
42  Running,
43  WaitingForSubjobs,
44  RollingBack,
45  Committing
46  };
47 
48  Q_DECLARE_PUBLIC(TransactionSequence)
49 
50  TransactionState mState;
51  QSet<KJob *> mIgnoredErrorJobs;
52  bool mAutoCommit;
53 
54  void commitResult(KJob *job)
55  {
56  Q_Q(TransactionSequence);
57 
58  if (job->error()) {
59  q->setError(job->error());
60  q->setErrorText(job->errorText());
61  }
62  q->emitResult();
63  }
64 
65  void rollbackResult(KJob *job)
66  {
67  Q_Q(TransactionSequence);
68 
69  Q_UNUSED(job);
70  q->emitResult();
71  }
72 };
73 
74 TransactionSequence::TransactionSequence(QObject *parent)
75  : Job(new TransactionSequencePrivate(this), parent)
76 {
77 }
78 
79 TransactionSequence::~TransactionSequence()
80 {
81 }
82 
83 bool TransactionSequence::addSubjob(KJob *job)
84 {
85  Q_D(TransactionSequence);
86 
87  //Don't abort the rollback job, while keeping the state set.
88  if (d->mState == TransactionSequencePrivate::RollingBack) {
89  return Job::addSubjob(job);
90  }
91 
92  if (error()) {
93  //This can happen if a rollback is in progress, so make sure we don't set the state back to running.
94  job->kill(EmitResult);
95  return false;
96  }
97  // TODO KDE5: remove property hack once SpecialCollectionsRequestJob has been fixed
98  if (d->mState == TransactionSequencePrivate::Idle && !property("transactionsDisabled").toBool()) {
99  d->mState = TransactionSequencePrivate::Running; // needs to be set before creating the transaction job to avoid infinite recursion
100  new TransactionBeginJob(this);
101  } else {
102  d->mState = TransactionSequencePrivate::Running;
103  }
104  return Job::addSubjob(job);
105 }
106 
107 void TransactionSequence::slotResult(KJob *job)
108 {
109  Q_D(TransactionSequence);
110 
111  if (!job->error() || d->mIgnoredErrorJobs.contains(job)) {
112  // If we have an error but want to ignore it, we can't call Job::slotResult
113  // because it would confuse the subjob queue processing logic. Just removing
114  // the subjob instead is fine.
115  if (!job->error()) {
116  Job::slotResult(job);
117  } else {
118  Job::removeSubjob(job);
119  }
120 
121  if (!hasSubjobs() && d->mState == TransactionSequencePrivate::WaitingForSubjobs) {
122  if (property("transactionsDisabled").toBool()) {
123  emitResult();
124  return;
125  }
126  d->mState = TransactionSequencePrivate::Committing;
127  TransactionCommitJob *job = new TransactionCommitJob(this);
128  connect(job, SIGNAL(result(KJob*)), SLOT(commitResult(KJob*)));
129  }
130  } else {
131  setError(job->error());
132  setErrorText(job->errorText());
133  removeSubjob(job);
134 
135  // cancel all subjobs in case someone else is listening (such as ItemSync), but without notifying ourselves again
136  foreach (KJob *job, subjobs()) {
137  disconnect(job, SIGNAL(result(KJob*)), this, SLOT(slotResult(KJob*)));
138  job->kill(EmitResult);
139  }
140  clearSubjobs();
141 
142  if (d->mState == TransactionSequencePrivate::Running || d->mState == TransactionSequencePrivate::WaitingForSubjobs) {
143  if (property("transactionsDisabled").toBool()) {
144  emitResult();
145  return;
146  }
147  d->mState = TransactionSequencePrivate::RollingBack;
148  TransactionRollbackJob *job = new TransactionRollbackJob(this);
149  connect(job, SIGNAL(result(KJob*)), SLOT(rollbackResult(KJob*)));
150  }
151  }
152 }
153 
154 void TransactionSequence::commit()
155 {
156  Q_D(TransactionSequence);
157 
158  if (d->mState == TransactionSequencePrivate::Running) {
159  d->mState = TransactionSequencePrivate::WaitingForSubjobs;
160  } else {
161  // we never got any subjobs, that means we never started a transaction
162  // so we can just quit here
163  if (d->mState == TransactionSequencePrivate::Idle) {
164  emitResult();
165  }
166  return;
167  }
168 
169  if (subjobs().isEmpty()) {
170  if (property("transactionsDisabled").toBool()) {
171  emitResult();
172  return;
173  }
174  if (!error()) {
175  d->mState = TransactionSequencePrivate::Committing;
176  TransactionCommitJob *job = new TransactionCommitJob(this);
177  connect(job, SIGNAL(result(KJob*)), SLOT(commitResult(KJob*)));
178  } else {
179  d->mState = TransactionSequencePrivate::RollingBack;
180  TransactionRollbackJob *job = new TransactionRollbackJob(this);
181  connect(job, SIGNAL(result(KJob*)), SLOT(rollbackResult(KJob*)));
182  }
183  }
184 }
185 
186 void TransactionSequence::setIgnoreJobFailure(KJob *job)
187 {
188  Q_D(TransactionSequence);
189 
190  // make sure this is one of our sub jobs
191  Q_ASSERT(subjobs().contains(job));
192 
193  d->mIgnoredErrorJobs.insert(job);
194 }
195 
196 void TransactionSequence::doStart()
197 {
198  Q_D(TransactionSequence);
199 
200  if (d->mAutoCommit) {
201  if (d->mState == TransactionSequencePrivate::Idle) {
202  emitResult();
203  } else {
204  commit();
205  }
206  }
207 }
208 
209 void TransactionSequence::setAutomaticCommittingEnabled(bool enable)
210 {
211  Q_D(TransactionSequence);
212  d->mAutoCommit = enable;
213 }
214 
215 void TransactionSequence::rollback()
216 {
217  Q_D(TransactionSequence);
218 
219  setError(UserCanceled);
220  // we never really started
221  if (d->mState == TransactionSequencePrivate::Idle) {
222  emitResult();
223  return;
224  }
225 
226  // TODO cancel not yet executed sub-jobs here
227 
228  d->mState = TransactionSequencePrivate::RollingBack;
229  TransactionRollbackJob *job = new TransactionRollbackJob(this);
230  connect(job, SIGNAL(result(KJob*)), SLOT(rollbackResult(KJob*)));
231 }
232 
233 #include "moc_transactionsequence.cpp"
Akonadi::TransactionSequence::rollback
void rollback()
Rolls back the current transaction as soon as possible.
Definition: transactionsequence.cpp:215
Akonadi::TransactionCommitJob
Job that commits a session-global transaction.
Definition: transactionjobs.h:113
Akonadi::Job
Base class for all actions in the Akonadi storage.
Definition: job.h:86
Akonadi::TransactionSequence::TransactionSequence
TransactionSequence(QObject *parent=0)
Creates a new transaction sequence.
Definition: transactionsequence.cpp:74
Akonadi::TransactionSequence::setAutomaticCommittingEnabled
void setAutomaticCommittingEnabled(bool enable)
Disable automatic committing.
Definition: transactionsequence.cpp:209
Akonadi::TransactionSequence::~TransactionSequence
~TransactionSequence()
Destroys the transaction sequence.
Definition: transactionsequence.cpp:79
Akonadi::TransactionSequence::addSubjob
bool addSubjob(KJob *job)
Adds the given job as a subjob to this job.
Definition: transactionsequence.cpp:83
Akonadi::TransactionRollbackJob
Job that aborts a session-global transaction.
Definition: transactionjobs.h:81
Akonadi::Job::addSubjob
virtual bool addSubjob(KJob *job)
Adds the given job as a subjob to this job.
Definition: job.cpp:328
QObject
Akonadi::TransactionSequence::setIgnoreJobFailure
void setIgnoreJobFailure(KJob *job)
Sets which job of the sequence might fail without rolling back the complete transaction.
Definition: transactionsequence.cpp:186
Akonadi::TransactionSequence::commit
void commit()
Commits the transaction as soon as all pending sub-jobs finished successfully.
Definition: transactionsequence.cpp:154
QSet
Definition: itemfetchscope.h:29
Akonadi::TransactionSequence::doStart
void doStart()
This method must be reimplemented in the concrete jobs.
Definition: transactionsequence.cpp:196
Akonadi::TransactionSequence
Base class for jobs that need to run a sequence of sub-jobs in a transaction.
Definition: transactionsequence.h:69
Akonadi::JobPrivate
Definition: job_p.h:31
Akonadi::Job::removeSubjob
virtual bool removeSubjob(KJob *job)
Removes the given subjob of this job.
Definition: job.cpp:338
Akonadi::Job::UserCanceled
The user canceld this job.
Definition: job.h:107
Akonadi::TransactionBeginJob
Job that begins a session-global transaction.
Definition: transactionjobs.h:46
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:38:03 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

akonadi

Skip menu "akonadi"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • Modules
  • Related Pages

kdepimlibs API Reference

Skip menu "kdepimlibs API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal