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

akonadi

  • sources
  • kde-4.12
  • 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  {
42  Idle,
43  Running,
44  WaitingForSubjobs,
45  RollingBack,
46  Committing
47  };
48 
49  Q_DECLARE_PUBLIC( TransactionSequence )
50 
51  TransactionState mState;
52  QSet<KJob*> mIgnoredErrorJobs;
53  bool mAutoCommit;
54 
55  void commitResult( KJob *job )
56  {
57  Q_Q( TransactionSequence );
58 
59  if ( job->error() ) {
60  q->setError( job->error() );
61  q->setErrorText( job->errorText() );
62  }
63  q->emitResult();
64  }
65 
66  void rollbackResult( KJob *job )
67  {
68  Q_Q( TransactionSequence );
69 
70  Q_UNUSED( job );
71  q->emitResult();
72  }
73 };
74 
75 TransactionSequence::TransactionSequence( QObject * parent )
76  : Job( new TransactionSequencePrivate( this ), parent )
77 {
78 }
79 
80 TransactionSequence::~TransactionSequence()
81 {
82 }
83 
84 bool TransactionSequence::addSubjob(KJob * job)
85 {
86  Q_D( TransactionSequence );
87 
88  // TODO KDE5: remove property hack once SpecialCollectionsRequestJob has been fixed
89  if ( d->mState == TransactionSequencePrivate::Idle && !property( "transactionsDisabled" ).toBool() ) {
90  d->mState = TransactionSequencePrivate::Running; // needs to be set before creating the transaction job to avoid infinite recursion
91  new TransactionBeginJob( this );
92  } else {
93  d->mState = TransactionSequencePrivate::Running;
94  }
95  return Job::addSubjob( job );
96 }
97 
98 void TransactionSequence::slotResult(KJob * job)
99 {
100  Q_D( TransactionSequence );
101 
102  if ( !job->error() || d->mIgnoredErrorJobs.contains( job ) ) {
103  // If we have an error but want to ignore it, we can't call Job::slotResult
104  // because it would confuse the subjob queue processing logic. Just removing
105  // the subjob instead is fine.
106  if ( !job->error() )
107  Job::slotResult( job );
108  else
109  Job::removeSubjob( job );
110 
111  if ( !hasSubjobs() && d->mState == TransactionSequencePrivate::WaitingForSubjobs ) {
112  if ( property( "transactionsDisabled" ).toBool() ) {
113  emitResult();
114  return;
115  }
116  d->mState = TransactionSequencePrivate::Committing;
117  TransactionCommitJob *job = new TransactionCommitJob( this );
118  connect( job, SIGNAL(result(KJob*)), SLOT(commitResult(KJob*)) );
119  }
120  } else {
121  setError( job->error() );
122  setErrorText( job->errorText() );
123  removeSubjob( job );
124 
125  // cancel all subjobs in case someone else is listening (such as ItemSync), but without notifying ourselves again
126  foreach ( KJob* job, subjobs() ) {
127  disconnect( job, SIGNAL(result(KJob*)), this, SLOT(slotResult(KJob*)) );
128  job->kill( EmitResult );
129  }
130  clearSubjobs();
131 
132  if ( d->mState == TransactionSequencePrivate::Running || d->mState == TransactionSequencePrivate::WaitingForSubjobs ) {
133  if ( property( "transactionsDisabled" ).toBool() ) {
134  emitResult();
135  return;
136  }
137  d->mState = TransactionSequencePrivate::RollingBack;
138  TransactionRollbackJob *job = new TransactionRollbackJob( this );
139  connect( job, SIGNAL(result(KJob*)), SLOT(rollbackResult(KJob*)) );
140  }
141  }
142 }
143 
144 void TransactionSequence::commit()
145 {
146  Q_D( TransactionSequence );
147 
148  if ( d->mState == TransactionSequencePrivate::Running ) {
149  d->mState = TransactionSequencePrivate::WaitingForSubjobs;
150  } else {
151  // we never got any subjobs, that means we never started a transaction
152  // so we can just quit here
153  if ( d->mState == TransactionSequencePrivate::Idle )
154  emitResult();
155  return;
156  }
157 
158  if ( subjobs().isEmpty() ) {
159  if ( property( "transactionsDisabled" ).toBool() ) {
160  emitResult();
161  return;
162  }
163  if ( !error() ) {
164  d->mState = TransactionSequencePrivate::Committing;
165  TransactionCommitJob *job = new TransactionCommitJob( this );
166  connect( job, SIGNAL(result(KJob*)), SLOT(commitResult(KJob*)) );
167  } else {
168  d->mState = TransactionSequencePrivate::RollingBack;
169  TransactionRollbackJob *job = new TransactionRollbackJob( this );
170  connect( job, SIGNAL(result(KJob*)), SLOT(rollbackResult(KJob*)) );
171  }
172  }
173 }
174 
175 void TransactionSequence::setIgnoreJobFailure( KJob *job )
176 {
177  Q_D( TransactionSequence );
178 
179  // make sure this is one of our sub jobs
180  Q_ASSERT( subjobs().contains( job ) );
181 
182  d->mIgnoredErrorJobs.insert( job );
183 }
184 
185 void TransactionSequence::doStart()
186 {
187  Q_D( TransactionSequence );
188 
189  if ( d->mAutoCommit ) {
190  if ( d->mState == TransactionSequencePrivate::Idle )
191  emitResult();
192  else
193  commit();
194  }
195 }
196 
197 void TransactionSequence::setAutomaticCommittingEnabled(bool enable)
198 {
199  Q_D( TransactionSequence );
200  d->mAutoCommit = enable;
201 }
202 
203 void TransactionSequence::rollback()
204 {
205  Q_D( TransactionSequence );
206 
207  setError( UserCanceled );
208  // we never really started
209  if ( d->mState == TransactionSequencePrivate::Idle ) {
210  emitResult();
211  return;
212  }
213 
214  // TODO cancel not yet executed sub-jobs here
215 
216  d->mState = TransactionSequencePrivate::RollingBack;
217  TransactionRollbackJob *job = new TransactionRollbackJob( this );
218  connect( job, SIGNAL(result(KJob*)), SLOT(rollbackResult(KJob*)) );
219 }
220 
221 #include "moc_transactionsequence.cpp"
Akonadi::TransactionSequence::rollback
void rollback()
Rolls back the current transaction as soon as possible.
Definition: transactionsequence.cpp:203
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:75
Akonadi::TransactionSequence::setAutomaticCommittingEnabled
void setAutomaticCommittingEnabled(bool enable)
Disable automatic committing.
Definition: transactionsequence.cpp:197
Akonadi::TransactionSequence::~TransactionSequence
~TransactionSequence()
Destroys the transaction sequence.
Definition: transactionsequence.cpp:80
Akonadi::TransactionSequence::addSubjob
bool addSubjob(KJob *job)
Adds the given job as a subjob to this job.
Definition: transactionsequence.cpp:84
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:318
Akonadi::TransactionSequence::setIgnoreJobFailure
void setIgnoreJobFailure(KJob *job)
Sets which job of the sequence might fail without rolling back the complete transaction.
Definition: transactionsequence.cpp:175
Akonadi::TransactionSequence::commit
void commit()
Commits the transaction as soon as all pending sub-jobs finished successfully.
Definition: transactionsequence.cpp:144
Akonadi::TransactionSequence::doStart
void doStart()
This method must be reimplemented in the concrete jobs.
Definition: transactionsequence.cpp:185
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:328
Akonadi::Job::UserCanceled
The user canceld this job.
Definition: job.h:108
Akonadi::TransactionBeginJob
Job that begins a session-global transaction.
Definition: transactionjobs.h:46
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 23:00:28 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
  • kldap
  • kmbox
  • kmime
  • kpimidentities
  • kpimtextedit
  • kresources
  • ktnef
  • kxmlrpcclient
  • microblog

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