//# TableCache.cc: Cache of open tables //# Copyright (C) 1994,1995,1997,1999 //# Associated Universities, Inc. Washington DC, USA. //# //# This library is free software; you can redistribute it and/or modify it //# under the terms of the GNU Library General Public License as published by //# the Free Software Foundation; either version 2 of the License, or (at your //# option) any later version. //# //# This library 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 Library General Public //# License for more details. //# //# You should have received a copy of the GNU Library General Public License //# along with this library; if not, write to the Free Software Foundation, //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. //# //# Correspondence concerning AIPS++ should be addressed as follows: //# Internet email: aips2-request@nrao.edu. //# Postal address: AIPS++ Project Office //# National Radio Astronomy Observatory //# 520 Edgemont Road //# Charlottesville, VA 22903-2475 USA //# //# $Id$ #include #include #include #include #include #include namespace casacore { //# NAMESPACE CASACORE - BEGIN TableCache::TableCache() {} TableCache::~TableCache() {} PlainTable* TableCache::operator() (const String& tableName) const { std::lock_guard sc(itsMutex); return getTable (tableName); } PlainTable* TableCache::getTable (const String& tableName) const { std::map::const_iterator iter = tableMap_p.find (tableName); if (iter == tableMap_p.end()) { return 0; } return static_cast(iter->second); } void TableCache::define (const String& tableName, PlainTable* tab) { std::lock_guard sc(itsMutex); tableMap_p.insert (std::make_pair(tableName, tab)); } void TableCache::remove (const String& tableName) { // For static Table objects it is possible that the cache is // deleted before the Table. // Therefore do not delete if the map is already empty // (otherwise an exception is thrown). std::lock_guard sc(itsMutex); if (tableMap_p.size() > 0) { try { tableMap_p.erase (tableName); } catch (std::exception&) { // Something strange has happened. // Throwing an exception causes an immediate crash (probably by // Table destructors). // So write a message on stderr; std::cerr << "Cannot remove table " << tableName << " from the table cache; suggest restarting" << std::endl; } } } void TableCache::rename (const String& newName, const String& oldName) { std::lock_guard sc(itsMutex); if (tableMap_p.find (oldName) != tableMap_p.end()) { void* ptr = tableMap_p.at(oldName); tableMap_p.erase (oldName); tableMap_p.insert (std::make_pair(newName, ptr)); } } uInt TableCache::nAutoLocks() { std::lock_guard sc(itsMutex); uInt n=0; for (const auto& x : tableMap_p) { PlainTable& table = *static_cast(x.second); if (table.lockOptions().option() == TableLock::AutoLocking) { //# Having a read lock is enough. if (table.hasLock (FileLocker::Read)) { n++; } } } return n; } void TableCache::relinquishAutoLocks (Bool all) { std::lock_guard sc(itsMutex); for (const auto& x : tableMap_p) { PlainTable& table = *static_cast(x.second); if (table.lockOptions().option() == TableLock::AutoLocking) { //# Having a read lock is enough. if (table.hasLock (FileLocker::Read)) { if (all) { table.unlock(); }else{ table.autoReleaseLock (True); } } } } } Vector TableCache::getTableNames() const { std::lock_guard sc(itsMutex); uInt ntab = tableMap_p.size(); Vector names(ntab); ntab = 0; for (const auto& x : tableMap_p) { PlainTable& table = *static_cast(x.second); names[ntab++] = table.tableName(); } return names; } Vector TableCache::getLockedTables (FileLocker::LockType lockType, int lockOption) { std::lock_guard sc(itsMutex); vector names; for (const auto& x : tableMap_p) { PlainTable& table = *static_cast(x.second); if (lockOption < 0 || table.lockOptions().option() == lockOption) { if (table.hasLock (lockType)) { names.push_back (table.tableName()); } } } return Vector(names); } void TableCache::flushTable (const String& name, Bool fsync, Bool recursive) { std::lock_guard sc(itsMutex); PlainTable* tab = getTable(name); if (tab) { tab->flush (fsync, recursive); } } PlainTable* TableCache::lookCache (const String& name, int tableOption, const TableLock& lockOptions) { //# Exit if table is not in cache yet. PlainTable* btp = this->operator()(name); if (btp == 0) { return btp; } //# Check if option matches. It does if equal. //# Otherwise it does if option in cached table is "more". //# Note that class PlainTable already throws an exception if //# a new table is created with the same name as an open table. int cachedTableOption = btp->tableOption(); if ((tableOption == cachedTableOption) || ((cachedTableOption == Table::New || cachedTableOption == Table::NewNoReplace || cachedTableOption == Table::Update) && (tableOption == Table::Update || tableOption == Table::Old))) { btp->mergeLock (lockOptions); return btp; } if (cachedTableOption == Table::Old && tableOption == Table::Update) { btp->mergeLock (lockOptions); btp->reopenRW(); return btp; } throw (TableInvOper ("Table " + name + " cannot be opened/created (already in cache)")); } } //# NAMESPACE CASACORE - END