Akonadi

cachecleaner.cpp
1 /*
2  Copyright (c) 2007 Volker Krause <[email protected]>
3  Copyright (C) 2014 Daniel Vrátil <[email protected]>
4 
5  This library is free software; you can redistribute it and/or modify it
6  under the terms of the GNU Library General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or (at your
8  option) any later version.
9 
10  This library is distributed in the hope that it will be useful, but WITHOUT
11  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13  License for more details.
14 
15  You should have received a copy of the GNU Library General Public License
16  along with this library; see the file COPYING.LIB. If not, write to the
17  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  02110-1301, USA.
19 */
20 
21 #include "cachecleaner.h"
22 #include "storage/parthelper.h"
23 #include "storage/datastore.h"
24 #include "storage/selectquerybuilder.h"
25 #include "storage/entity.h"
26 #include "akonadi.h"
27 #include "akonadiserver_debug.h"
28 
29 #include <private/protocol_p.h>
30 
31 #include <QDateTime>
32 
33 using namespace Akonadi::Server;
34 
35 QMutex CacheCleanerInhibitor::sLock;
36 int CacheCleanerInhibitor::sInhibitCount = 0;
37 
38 CacheCleanerInhibitor::CacheCleanerInhibitor(AkonadiServer &akonadi, bool doInhibit)
39  : mCleaner(akonadi.cacheCleaner())
40 {
41  if (doInhibit) {
42  inhibit();
43  }
44 }
45 
46 CacheCleanerInhibitor::~CacheCleanerInhibitor()
47 {
48  if (mInhibited) {
49  uninhibit();
50  }
51 }
52 
53 void CacheCleanerInhibitor::inhibit()
54 {
55  if (mInhibited) {
56  qCCritical(AKONADISERVER_LOG) << "Cannot recursively inhibit an inhibitor";
57  return;
58  }
59 
60  sLock.lock();
61  if (++sInhibitCount == 1) {
62  if (mCleaner) {
63  mCleaner->inhibit(true);
64  }
65  }
66  sLock.unlock();
67  mInhibited = true;
68 }
69 
70 void CacheCleanerInhibitor::uninhibit()
71 {
72  if (!mInhibited) {
73  qCCritical(AKONADISERVER_LOG) << "Cannot uninhibit an uninhibited inhibitor"; // aaaw yeah
74  return;
75  }
76  mInhibited = false;
77 
78  sLock.lock();
79  Q_ASSERT(sInhibitCount > 0);
80  if (--sInhibitCount == 0) {
81  if (mCleaner) {
82  mCleaner->inhibit(false);
83  }
84  }
85  sLock.unlock();
86 }
87 
88 CacheCleaner::CacheCleaner(QObject *parent)
89  : CollectionScheduler(QStringLiteral("CacheCleaner"), QThread::IdlePriority, parent)
90 {
91  setMinimumInterval(5);
92 }
93 
94 CacheCleaner::~CacheCleaner()
95 {
96  quitThread();
97 }
98 
99 int CacheCleaner::collectionScheduleInterval(const Collection &collection)
100 {
101  return collection.cachePolicyCacheTimeout();
102 }
103 
104 bool CacheCleaner::hasChanged(const Collection &collection, const Collection &changed)
105 {
106  return collection.cachePolicyLocalParts() != changed.cachePolicyLocalParts()
107  || collection.cachePolicyCacheTimeout() != changed.cachePolicyCacheTimeout()
108  || collection.cachePolicyInherit() != changed.cachePolicyInherit();
109 }
110 
111 bool CacheCleaner::shouldScheduleCollection(const Collection &collection)
112 {
113  return collection.cachePolicyLocalParts() != QLatin1String("ALL")
114  && collection.cachePolicyCacheTimeout() >= 0
115  && (collection.enabled() || (collection.displayPref() == Collection::True) || (collection.syncPref() == Collection::True) || (collection.indexPref() == Collection::True))
116  && collection.resourceId() > 0;
117 }
118 
119 void CacheCleaner::collectionExpired(const Collection &collection)
120 {
122  qb.addJoin(QueryBuilder::InnerJoin, PimItem::tableName(), Part::pimItemIdColumn(), PimItem::idFullColumnName());
123  qb.addJoin(QueryBuilder::InnerJoin, PartType::tableName(), Part::partTypeIdFullColumnName(), PartType::idFullColumnName());
124  qb.addValueCondition(PimItem::collectionIdFullColumnName(), Query::Equals, collection.id());
125  qb.addValueCondition(PimItem::atimeFullColumnName(), Query::Less, QDateTime::currentDateTimeUtc().addSecs(-60 * collection.cachePolicyCacheTimeout()));
126  qb.addValueCondition(Part::dataFullColumnName(), Query::IsNot, QVariant());
127  qb.addValueCondition(PartType::nsFullColumnName(), Query::Equals, QLatin1String("PLD"));
128  qb.addValueCondition(PimItem::dirtyFullColumnName(), Query::Equals, false);
129 
130  const QStringList partNames = collection.cachePolicyLocalParts().split(QLatin1Char(' '));
131  for (QString partName : partNames) {
132  if (partName.startsWith(QLatin1String(AKONADI_PARAM_PLD))) {
133  partName.remove(0, 4);
134  }
135  qb.addValueCondition(PartType::nameFullColumnName(), Query::NotEquals, partName);
136  }
137  if (qb.exec()) {
138  const Part::List parts = qb.result();
139  if (!parts.isEmpty()) {
140  qCInfo(AKONADISERVER_LOG) << "CacheCleaner found" << parts.count() << "item parts to expire in collection" << collection.name();
141  // clear data field
142  for (Part part : parts) {
143  try {
144  if (!PartHelper::truncate(part)) {
145  qCWarning(AKONADISERVER_LOG) << "CacheCleaner failed to expire item part" << part.id();
146  }
147  } catch (const PartHelperException &e) {
148  qCCritical(AKONADISERVER_LOG) << e.type() << e.what();
149  }
150  }
151  }
152  }
153 }
void addValueCondition(const QString &column, Query::CompareOperator op, const QVariant &value, ConditionType type=WhereCondition)
Add a WHERE or HAVING condition which compares a column with a given value.
QStringList split(const QString &sep, QString::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
int cachePolicyCacheTimeout() const
Returns the value of the cachePolicyCacheTimeout column of this record.
Definition: entities.cpp:1546
Collection::Tristate indexPref() const
Returns the value of the indexPref column of this record.
Definition: entities.cpp:1507
NOTE: only supported for UPDATE and SELECT queries.
Definition: querybuilder.h:62
void addJoin(JoinType joinType, const QString &table, const Query::Condition &condition)
Join a table to the query.
qint64 resourceId() const
Returns the value of the resourceId column of this record.
Definition: entities.cpp:1455
Representation of a record in the Part table.
Definition: entities.h:1970
bool truncate(Part &part)
Truncate the payload of part and update filesystem/database accordingly.
Definition: parthelper.cpp:166
static QString tableName()
Returns the name of the SQL table.
Definition: entities.cpp:4116
QVector< T > result()
Returns the result of this SELECT query.
Helper class for creating and executing database SELECT queries.
Definition: item.h:44
QString name() const
Returns the value of the name column of this record.
bool isEmpty() const const
bool cachePolicyInherit() const
Returns the value of the cachePolicyInherit column of this record.
Definition: entities.cpp:1520
Collection::Tristate syncPref() const
Returns the value of the syncPref column of this record.
Definition: entities.cpp:1481
int count(const T &value) const const
bool enabled() const
Returns the value of the enabled column of this record.
Collection::Tristate displayPref() const
Returns the value of the displayPref column of this record.
Definition: entities.cpp:1494
QDateTime currentDateTimeUtc()
QString cachePolicyLocalParts() const
Returns the value of the cachePolicyLocalParts column of this record.
Definition: entities.cpp:1572
static QString tableName()
Returns the name of the SQL table.
Definition: entities.cpp:5740
bool exec()
Executes the query, returns true on success.
Representation of a record in the Collection table.
Definition: entities.h:451
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon May 25 2020 22:46:08 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.