void Project::onFileModified(const Path &file) { const uint32_t fileId = Location::fileId(file); warning() << file << "was modified" << fileId << mModifiedFiles.contains(fileId); if (!fileId || !mModifiedFiles.insert(fileId)) { return; } if (mModifiedFiles.size() == 1 && file.isSource()) { startDirtyJobs(); } else { mModifiedFilesTimer.start(shared_from_this(), ModifiedFilesTimeout, SingleShot, ModifiedFiles); } }
void Project::timerEvent(TimerEvent *e) { if (e->userData() == Save) { save(); } else if (e->userData() == Sync) { const int syncTime = syncDB(); error() << "Jobs took" << (static_cast<double>(mTimer.elapsed()) / 1000.0) << "secs, syncing took" << (static_cast<double>(syncTime) / 1000.0) << " secs, using" << MemoryMonitor::usage() / (1024.0 * 1024.0) << "mb of memory"; mSaveTimer.start(shared_from_this(), SaveTimeout, SingleShot, Save); mJobCounter = 0; } else if (e->userData() == ModifiedFiles) { startDirtyJobs(); } else { assert(0 && "Unexpected timer event in Project"); e->stop(); } }
int Project::reindex(const Match &match) { Set<uint32_t> dirty; { MutexLocker lock(&mMutex); const DependencyMap::const_iterator end = mDependencies.end(); for (DependencyMap::const_iterator it = mDependencies.begin(); it != end; ++it) { if (match.isEmpty() || match.match(Location::path(it->first))) { dirty.insert(it->first); } } if (dirty.isEmpty()) return 0; mModifiedFiles += dirty; } startDirtyJobs(); return dirty.size(); }
bool Project::restore() { StopWatch timer; Path path = mPath; RTags::encodePath(path); const Path p = Server::instance()->options().dataDir + path; bool restoreError = false; FILE *f = fopen(p.constData(), "r"); if (!f) return false; Deserializer in(f); int version; in >> version; if (version != Server::DatabaseVersion) { error("Wrong database version. Expected %d, got %d for %s. Removing.", Server::DatabaseVersion, version, p.constData()); restoreError = true; goto end; } { int fs; in >> fs; if (fs != Rct::fileSize(f)) { error("%s seems to be corrupted, refusing to restore %s", p.constData(), mPath.constData()); restoreError = true; goto end; } } { { Scope<SymbolMap &> scope = lockSymbolsForWrite(); in >> scope.data(); } { Scope<SymbolNameMap &> scope = lockSymbolNamesForWrite(); in >> scope.data(); } { Scope<UsrMap &> scope = lockUsrForWrite(); in >> scope.data(); } in >> mDependencies >> mSources >> mVisitedFiles; DependencyMap reversedDependencies; // these dependencies are in the form of: // Path.cpp: Path.h, String.h ... // mDependencies are like this: // Path.h: Path.cpp, Server.cpp ... for (DependencyMap::const_iterator it = mDependencies.begin(); it != mDependencies.end(); ++it) { const Path dir = Location::path(it->first).parentDir(); if (dir.isEmpty()) { error() << "File busted" << it->first << Location::path(it->first); continue; } if (mWatchedPaths.insert(dir)) mWatcher.watch(dir); for (Set<uint32_t>::const_iterator s = it->second.begin(); s != it->second.end(); ++s) { reversedDependencies[*s].insert(it->first); } } SourceInformationMap::iterator it = mSources.begin(); while (it != mSources.end()) { if (!it->second.sourceFile.isFile()) { error() << it->second.sourceFile << "seems to have disappeared"; mSources.erase(it++); mModifiedFiles.insert(it->first); } else { const time_t parsed = it->second.parsed; // error() << "parsed" << String::formatTime(parsed, String::DateTime) << parsed; assert(mDependencies.value(it->first).contains(it->first)); assert(mDependencies.contains(it->first)); const Set<uint32_t> &deps = reversedDependencies[it->first]; for (Set<uint32_t>::const_iterator d = deps.begin(); d != deps.end(); ++d) { if (!mModifiedFiles.contains(*d) && Location::path(*d).lastModified() > parsed) mModifiedFiles.insert(*d); } ++it; } } if (!mModifiedFiles.isEmpty()) startDirtyJobs(); } end: fclose(f); if (restoreError) { Path::rm(p); return false; } else { error() << "Restored project" << mPath << "in" << timer.elapsed() << "ms"; } return true; }