Files
encfs/encfs/Context.cpp
Ben RUBSON 618db2374c Get idle counters at once (#294)
to avoid a race with usage==0 & openCount>0
2017-03-10 08:47:04 +01:00

132 lines
3.4 KiB
C++

/*****************************************************************************
* Author: Valient Gough <vgough@pobox.com>
*
*****************************************************************************
* Copyright (c) 2007, Valient Gough
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "internal/easylogging++.h"
#include <utility>
#include "Context.h"
#include "DirNode.h"
#include "Error.h"
#include "Mutex.h"
namespace encfs {
EncFS_Context::EncFS_Context() {
pthread_cond_init(&wakeupCond, 0);
pthread_mutex_init(&wakeupMutex, 0);
pthread_mutex_init(&contextMutex, 0);
usageCount = 0;
}
EncFS_Context::~EncFS_Context() {
pthread_mutex_destroy(&contextMutex);
pthread_mutex_destroy(&wakeupMutex);
pthread_cond_destroy(&wakeupCond);
// release all entries from map
openFiles.clear();
}
std::shared_ptr<DirNode> EncFS_Context::getRoot(int *errCode) {
std::shared_ptr<DirNode> ret;
do {
{
Lock lock(contextMutex);
ret = root;
++usageCount;
}
if (!ret) {
int res = remountFS(this);
if (res != 0) {
*errCode = res;
break;
}
}
} while (!ret);
return ret;
}
void EncFS_Context::setRoot(const std::shared_ptr<DirNode> &r) {
Lock lock(contextMutex);
root = r;
if (r) rootCipherDir = r->rootDirectory();
}
bool EncFS_Context::isMounted() { return root.get() != nullptr; }
void EncFS_Context::getAndResetUsageCounter(int *usage, int *openCount) {
Lock lock(contextMutex);
*usage = usageCount;
usageCount = 0;
*openCount = openFiles.size();
}
std::shared_ptr<FileNode> EncFS_Context::lookupNode(const char *path) {
Lock lock(contextMutex);
FileMap::iterator it = openFiles.find(std::string(path));
if (it != openFiles.end()) {
// all the items in the set point to the same node.. so just use the
// first
return it->second.front();
}
return std::shared_ptr<FileNode>();
}
void EncFS_Context::renameNode(const char *from, const char *to) {
Lock lock(contextMutex);
FileMap::iterator it = openFiles.find(std::string(from));
if (it != openFiles.end()) {
auto val = it->second;
openFiles.erase(it);
openFiles[std::string(to)] = val;
}
}
FileNode *EncFS_Context::putNode(const char *path,
std::shared_ptr<FileNode> &&node) {
Lock lock(contextMutex);
auto &list = openFiles[std::string(path)];
list.push_front(std::move(node));
return list.front().get();
}
void EncFS_Context::eraseNode(const char *path, FileNode *pl) {
Lock lock(contextMutex);
FileMap::iterator it = openFiles.find(std::string(path));
rAssert(it != openFiles.end());
it->second.pop_front();
// if no more references to this file, remove the record all together
if (it->second.empty()) {
openFiles.erase(it);
}
}
} // namespace encfs