Remove the size-limit of items stored in the repository. Items were limited to the...
[kdevelopdvcssupport.git] / language / duchain / repositories / itemrepository.cpp
blob4053ae0a765ffaf422aff2de933603667d85e9e2
1 /*
2 Copyright 2008 David Nolden <david.nolden.kdevelop@art-master.de>
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License version 2 as published by the Free Software Foundation.
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
13 You should have received a copy of the GNU Library General Public License
14 along with this library; see the file COPYING.LIB. If not, write to
15 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 Boston, MA 02110-1301, USA.
19 #include "itemrepository.h"
21 #include <QDataStream>
23 #include <kstandarddirs.h>
24 #include <kcomponentdata.h>
25 #include <klockfile.h>
26 #include <kmessagebox.h>
27 #include <klocale.h>
29 #include <interfaces/icore.h>
31 #include "../duchain.h"
33 namespace KDevelop {
36 uint staticItemRepositoryVersion() {
37 //Increase this to reset incompatible item-repositories
38 return 25;
41 AbstractItemRepository::~AbstractItemRepository() {
44 ItemRepositoryRegistry::ItemRepositoryRegistry(QString openPath, KLockFile::Ptr lock) : m_mutex(QMutex::Recursive) {
45 if(!openPath.isEmpty())
46 open(openPath, false, lock);
49 QAtomicInt& ItemRepositoryRegistry::getCustomCounter(const QString& identity, int initialValue) {
50 if(!m_customCounters.contains(identity))
51 m_customCounters.insert(identity, new QAtomicInt(initialValue));
52 return *m_customCounters[identity];
55 bool processExists(int pid) {
56 ///@todo Find a cross-platform way of doing this!
57 QFileInfo f(QString("/proc/%1").arg(pid));
58 return f.exists();
61 ///The global item-repository registry that is used by default
62 ItemRepositoryRegistry& allocateGlobalItemRepositoryRegistry() {
64 KLockFile::Ptr lock;
65 QString repoPath;
66 KComponentData component("item repositories temp", QByteArray(), KComponentData::SkipMainComponentRegistration);
67 // if(ICore::self()) {
68 ///@todo Use the kde directory again, once we know how to get it in this early stage
69 // QString baseDir = KStandardDirs::locateLocal("data", "kdevduchain");
70 QString baseDir = QDir::homePath() + "/.kdevduchain";
71 KStandardDirs::makeDir(baseDir);
72 //Since each instance of kdevelop needs an own directory, iterate until we find a not-yet-used one
73 for(int a = 0; a < 100; ++a) {
74 QString specificDir = baseDir + QString("/%1").arg(a);
75 KStandardDirs::makeDir(specificDir);
76 kDebug() << "making" << specificDir;
77 lock = new KLockFile(specificDir + "/lock", component);
78 KLockFile::LockResult result = lock->lock(KLockFile::NoBlockFlag | KLockFile::ForceFlag);
80 bool useDir = false;
82 if(result != KLockFile::LockOK) {
83 int pid;
84 QString hostname, appname;
85 if(lock->getLockInfo(pid, hostname, appname)) {
86 if(!processExists(pid)) {
87 kDebug() << "The process holding" << specificDir << "does not exists any more. Re-using the directory.";
88 QFile::remove(specificDir + "/lock");
89 useDir = true;
90 if(lock->lock(KLockFile::NoBlockFlag | KLockFile::ForceFlag) != KLockFile::LockOK) {
91 kWarning() << "Failed to re-establish the lock in" << specificDir;
92 continue;
96 }else{
97 useDir = true;
99 if(useDir) {
100 repoPath = specificDir;
101 if(result == KLockFile::LockStale)
102 kWarning() << "stale lock detected:" << specificDir + "/lock";
103 break;
107 if(repoPath.isEmpty()) {
108 kWarning() << "could not create a directory for the duchain data";
109 }else{
110 kDebug() << "picked duchain directory" << repoPath;
112 // }
114 static ItemRepositoryRegistry global(repoPath, lock);
115 return global;
118 ///The global item-repository registry that is used by default
119 ItemRepositoryRegistry& globalItemRepositoryRegistry() {
121 static ItemRepositoryRegistry& global(allocateGlobalItemRepositoryRegistry());
122 return global;
125 void ItemRepositoryRegistry::registerRepository(AbstractItemRepository* repository) {
126 QMutexLocker lock(&m_mutex);
127 m_repositories << repository;
128 if(!m_path.isEmpty()) {
129 if(!repository->open(m_path)) {
130 deleteDataDirectory();
131 kError() << "failed to open a repository";
132 abort();
137 QString ItemRepositoryRegistry::path() const {
138 QMutexLocker lock(&m_mutex);
139 return m_path;
142 void ItemRepositoryRegistry::lockForWriting() {
143 QMutexLocker lock(&m_mutex);
144 //Create is_writing
145 QFile f(m_path + "/is_writing");
146 f.open(QIODevice::WriteOnly);
147 f.close();
150 void ItemRepositoryRegistry::unlockForWriting() {
151 QMutexLocker lock(&m_mutex);
152 //Delete is_writing
153 QFile::remove(m_path + "/is_writing");
156 void ItemRepositoryRegistry::unRegisterRepository(AbstractItemRepository* repository) {
157 QMutexLocker lock(&m_mutex);
158 Q_ASSERT(m_repositories.contains(repository));
159 repository->close();
160 m_repositories.removeAll(repository);
163 //Recursive delete, copied from a mailing-list
164 //Returns true on success
165 bool removeDirectory(const QDir &aDir)
167 bool has_err = false;
168 if (aDir.exists())//QDir::NoDotAndDotDot
170 QFileInfoList entries = aDir.entryInfoList(QDir::NoDotAndDotDot |
171 QDir::Dirs | QDir::Files);
172 int count = entries.size();
173 for (int idx = 0; ((idx < count) && !has_err); idx++)
175 QFileInfo entryInfo = entries[idx];
176 QString path = entryInfo.absoluteFilePath();
177 if (entryInfo.isDir())
179 has_err = !removeDirectory(QDir(path));
181 else
183 QFile file(path);
184 if (!file.remove())
185 has_err = true;
188 if (!aDir.rmdir(aDir.absolutePath()))
189 has_err = true;
191 return !has_err;
194 void ItemRepositoryRegistry::deleteDataDirectory() {
195 QMutexLocker lock(&m_mutex);
196 QFileInfo pathInfo(m_path);
197 QDir d(m_path);
198 Q_ASSERT(removeDirectory(d));
199 KStandardDirs::makeDir(m_path);
202 bool ItemRepositoryRegistry::open(const QString& path, bool clear, KLockFile::Ptr lock) {
203 QMutexLocker mlock(&m_mutex);
204 if(m_path == path && !clear)
205 return true;
207 QFileInfo wasWriting(path + "/is_writing");
208 if(wasWriting.exists()) {
209 clear = true;
212 m_path = path;
213 if(clear) {
214 kWarning() << QString("The data-repository at %1 has to be cleared. Either the disk format has changed, or KDevelop crashed while writing the repository").arg(m_path);
215 // KMessageBox::information( 0, i18n("The data-repository at %1 has to be cleared. Either the disk format has changed, or KDevelop crashed while writing the repository.", m_path ) );
216 deleteDataDirectory();
219 foreach(AbstractItemRepository* repository, m_repositories) {
220 if(!repository->open(path)) {
221 deleteDataDirectory();
222 kError() << "failed to open a repository";
223 abort();
227 QFile f(path + "/Counters");
228 if(f.open(QIODevice::ReadOnly)) {
229 QDataStream stream(&f);
231 while(!stream.atEnd()) {
232 //Read in all custom counter values
233 QString counterName;
234 stream >> counterName;
235 int counterValue;
236 stream >> counterValue;
237 if(m_customCounters.contains(counterName))
238 *m_customCounters[counterName] = counterValue;
239 else
240 getCustomCounter(counterName, 0) = counterValue;
242 }else{
243 // kDebug() << "Could not open counter file";
246 m_lock = lock;
247 return true;
250 void ItemRepositoryRegistry::store() {
251 QMutexLocker lock(&m_mutex);
252 foreach(AbstractItemRepository* repository, m_repositories)
253 repository->store();
255 //Store all custom counter values
256 QFile f(m_path + "/Counters");
257 if(f.open(QIODevice::WriteOnly)) {
258 f.resize(0);
259 QDataStream stream(&f);
260 for(QMap<QString, QAtomicInt*>::const_iterator it = m_customCounters.begin(); it != m_customCounters.end(); ++it) {
261 stream << it.key();
262 stream << it.value()->fetchAndAddRelaxed(0);
264 }else{
265 kWarning() << "Could not open counter file for writing";
269 void ItemRepositoryRegistry::close() {
271 QMutexLocker lock(&m_mutex);
273 foreach(AbstractItemRepository* repository, m_repositories)
274 repository->close();
276 m_path = QString();
279 ItemRepositoryRegistry::~ItemRepositoryRegistry() {
280 close();
281 QMutexLocker lock(&m_mutex);
282 foreach(QAtomicInt* counter, m_customCounters.values())
283 delete counter;