# HG changeset patch # User Chris Cannam # Date 1163429337 0 # Node ID 2f2d282d45d0006d1d056ea1a40abe680aa28963 # Parent 1d789d688f59d06c7f1ba6e8d23bf0418216cde6 * Somewhat better handling of running out of memory or disc space diff -r 1d789d688f59 -r 2f2d282d45d0 data/fft/FFTDataServer.cpp --- a/data/fft/FFTDataServer.cpp Fri Nov 10 17:45:26 2006 +0000 +++ b/data/fft/FFTDataServer.cpp Mon Nov 13 14:48:57 2006 +0000 @@ -23,8 +23,12 @@ #include "system/System.h" #include "base/StorageAdviser.h" +#include "base/Exceptions.h" #include "base/Profiler.h" +#include +#include + //#define DEBUG_FFT_SERVER 1 //#define DEBUG_FFT_SERVER_FILL 1 @@ -76,19 +80,26 @@ return server; } - m_servers[n] = ServerCountPair - (new FFTDataServer(n, - model, - channel, - windowType, - windowSize, - windowIncrement, - fftSize, - polar, - fillFromColumn), - 1); + try { + server = new FFTDataServer(n, + model, + channel, + windowType, + windowSize, + windowIncrement, + fftSize, + polar, + fillFromColumn); + } catch (InsufficientDiscSpace) { + delete server; + server = 0; + } - return m_servers[n].first; + if (server) { + m_servers[n] = ServerCountPair(server, 1); + } + + return server; } FFTDataServer * @@ -364,9 +375,11 @@ int minimumSize = (cells / 1024) * sizeof(uint16_t); // kb int maximumSize = (cells / 1024) * sizeof(float); // kb - //!!! catch InsufficientDiscSpace + // This can throw InsufficientDiscSpace. We don't catch it here -- we + // haven't allocated anything yet and can safely let the exception out. + // Caller needs to check for it. - StorageAdviser::Recommendation recommendation = + StorageAdviser::Recommendation recommendation = StorageAdviser::recommend(criteria, minimumSize, maximumSize); std::cerr << "Recommendation was: " << recommendation << std::endl; @@ -544,32 +557,46 @@ FFTCache *cache = 0; - if (m_memoryCache) { + try { + + if (m_memoryCache) { - cache = new FFTMemoryCache(); + cache = new FFTMemoryCache(); - } else if (m_compactCache) { + } else if (m_compactCache) { - cache = new FFTFileCache(name, MatrixFile::ReadWrite, - FFTFileCache::Compact); + cache = new FFTFileCache(name, MatrixFile::ReadWrite, + FFTFileCache::Compact); - } else { + } else { - cache = new FFTFileCache(name, MatrixFile::ReadWrite, - m_polar ? FFTFileCache::Polar : - FFTFileCache::Rectangular); + cache = new FFTFileCache(name, MatrixFile::ReadWrite, + m_polar ? FFTFileCache::Polar : + FFTFileCache::Rectangular); + } + + size_t width = m_cacheWidth; + if (c * m_cacheWidth + width > m_width) { + width = m_width - c * m_cacheWidth; + } + + cache->resize(width, m_height); + cache->reset(); + + } catch (std::bad_alloc) { + std::cerr << "ERROR: Memory allocation failed in FFTFileCache::resize:" + << " abandoning this cache" << std::endl; + //!!! Shouldn't be using QtGui here. Need a better way to report this. + QMessageBox::critical + (0, QApplication::tr("FFT cache resize failed"), + QApplication::tr + ("Failed to create or resize an FFT model slice.\n" + "There may be insufficient memory or disc space to continue.")); + delete cache; + m_caches[c] = 0; + return 0; } -// FFTCache *cache = new FFTMemoryCache(); - - size_t width = m_cacheWidth; - if (c * m_cacheWidth + width > m_width) { - width = m_width - c * m_cacheWidth; - } - - cache->resize(width, m_height); - cache->reset(); - m_caches[c] = cache; m_lastUsedCache = c; @@ -583,6 +610,7 @@ size_t col; FFTCache *cache = getCache(x, col); + if (!cache) return 0; if (!cache->haveSetColumnAt(col)) { std::cerr << "FFTDataServer::getMagnitudeAt: calling fillColumn(" @@ -599,6 +627,7 @@ size_t col; FFTCache *cache = getCache(x, col); + if (!cache) return 0; if (!cache->haveSetColumnAt(col)) { fillColumn(x); @@ -613,6 +642,7 @@ size_t col; FFTCache *cache = getCache(x, col); + if (!cache) return 0; if (!cache->haveSetColumnAt(col)) { fillColumn(x); @@ -627,6 +657,7 @@ size_t col; FFTCache *cache = getCache(x, col); + if (!cache) return 0; if (!cache->haveSetColumnAt(col)) { fillColumn(x); @@ -641,6 +672,7 @@ size_t col; FFTCache *cache = getCache(x, col); + if (!cache) { real = 0; imaginary = 0; return; } if (!cache->haveSetColumnAt(col)) { #ifdef DEBUG_FFT_SERVER @@ -672,6 +704,7 @@ size_t col; FFTCache *cache = getCache(x, col); + if (!cache) return true; return cache->haveSetColumnAt(col); } @@ -686,6 +719,7 @@ std::cout << "FFTDataServer::fillColumn(" << x << ")" << std::endl; #endif FFTCache *cache = getCache(x, col); + if (!cache) return; QMutexLocker locker(&m_writeMutex); diff -r 1d789d688f59 -r 2f2d282d45d0 data/model/FFTModel.cpp --- a/data/model/FFTModel.cpp Fri Nov 10 17:45:26 2006 +0000 +++ b/data/model/FFTModel.cpp Mon Nov 13 14:48:57 2006 +0000 @@ -42,6 +42,8 @@ polar, fillFromColumn); + if (!m_server) return; // caller should check isOK() + size_t xratio = windowIncrement / m_server->getWindowIncrement(); size_t yratio = m_server->getFFTSize() / fftSize; @@ -71,7 +73,7 @@ FFTModel::~FFTModel() { - FFTDataServer::releaseInstance(m_server); + if (m_server) FFTDataServer::releaseInstance(m_server); } size_t