changeset 678:948271d124ac

Make more (though still not entirely) robust in the face of running out of disc space
author Chris Cannam
date Thu, 14 Apr 2011 15:20:27 +0100
parents ce73529405e4
children c8badbd4c005
files data/fft/FFTDataServer.cpp data/fft/FFTDataServer.h data/fileio/FileSource.cpp data/fileio/FileSource.h data/model/FFTModel.h transform/FeatureExtractionModelTransformer.cpp
diffstat 6 files changed, 222 insertions(+), 98 deletions(-) [+]
line wrap: on
line diff
--- a/data/fft/FFTDataServer.cpp	Thu Apr 07 15:20:35 2011 +0100
+++ b/data/fft/FFTDataServer.cpp	Thu Apr 14 15:20:27 2011 +0100
@@ -814,13 +814,15 @@
 
             success = true;
 
-        } catch (std::exception e) {
+        } catch (std::exception &e) {
 
             delete cb->fileCacheWriter;
             cb->fileCacheWriter = 0;
             
             std::cerr << "ERROR: Failed to construct disc cache for FFT data: "
                       << e.what() << std::endl;
+
+            throw;
         }
     }
 
@@ -851,7 +853,7 @@
         
         cb->fileCacheReader[me] = new FFTFileCacheReader(cb->fileCacheWriter);
 
-    } catch (std::exception e) {
+    } catch (std::exception &e) {
 
         delete cb->fileCacheReader[me];
         cb->fileCacheReader.erase(me);
@@ -889,20 +891,29 @@
 
     if (x >= m_width || y >= m_height) return 0;
 
-    size_t col;
-    FFTCacheReader *cache = getCacheReader(x, col);
-    if (!cache) return 0;
+    float val = 0;
 
-    //!!! n.b. can throw
-    if (!cache->haveSetColumnAt(col)) {
-        Profiler profiler("FFTDataServer::getMagnitudeAt: filling");
+    try {
+        size_t col;
+        FFTCacheReader *cache = getCacheReader(x, col);
+        if (!cache) return 0;
+
+        if (!cache->haveSetColumnAt(col)) {
+            Profiler profiler("FFTDataServer::getMagnitudeAt: filling");
 #ifdef DEBUG_FFT_SERVER
-        std::cerr << "FFTDataServer::getMagnitudeAt: calling fillColumn(" 
+            std::cerr << "FFTDataServer::getMagnitudeAt: calling fillColumn(" 
                   << x << ")" << std::endl;
 #endif
-        fillColumn(x);
+            fillColumn(x);
+        }
+
+        val = cache->getMagnitudeAt(col, y);
+
+    } catch (std::exception &e) {
+        m_error = e.what();
     }
-    return cache->getMagnitudeAt(col, y);
+
+    return val;
 }
 
 bool
@@ -918,18 +929,23 @@
         count = (m_height - minbin) / step;
     }
 
-    size_t col;
-    FFTCacheReader *cache = getCacheReader(x, col);
-    if (!cache) return false;
+    try {
+        size_t col;
+        FFTCacheReader *cache = getCacheReader(x, col);
+        if (!cache) return false;
 
-    //!!! n.b. can throw
-    if (!cache->haveSetColumnAt(col)) {
-        Profiler profiler("FFTDataServer::getMagnitudesAt: filling");
-        fillColumn(x);
+        if (!cache->haveSetColumnAt(col)) {
+            Profiler profiler("FFTDataServer::getMagnitudesAt: filling");
+            fillColumn(x);
+        }
+
+        cache->getMagnitudesAt(col, values, minbin, count, step);
+
+    } catch (std::exception &e) {
+        m_error = e.what();
+        return false;
     }
 
-    cache->getMagnitudesAt(col, values, minbin, count, step);
-
     return true;
 }
 
@@ -940,16 +956,25 @@
 
     if (x >= m_width || y >= m_height) return 0;
 
-    size_t col;
-    FFTCacheReader *cache = getCacheReader(x, col);
-    if (!cache) return 0;
+    float val = 0;
 
-    //!!! n.b. can throw
-    if (!cache->haveSetColumnAt(col)) {
-        Profiler profiler("FFTDataServer::getNormalizedMagnitudeAt: filling");
-        fillColumn(x);
+    try {
+
+        size_t col;
+        FFTCacheReader *cache = getCacheReader(x, col);
+        if (!cache) return 0;
+
+        if (!cache->haveSetColumnAt(col)) {
+            Profiler profiler("FFTDataServer::getNormalizedMagnitudeAt: filling");
+            fillColumn(x);
+        }
+        val = cache->getNormalizedMagnitudeAt(col, y);
+
+    } catch (std::exception &e) {
+        m_error = e.what();
     }
-    return cache->getNormalizedMagnitudeAt(col, y);
+
+    return val;
 }
 
 bool
@@ -965,18 +990,24 @@
         count = (m_height - minbin) / step;
     }
 
-    size_t col;
-    FFTCacheReader *cache = getCacheReader(x, col);
-    if (!cache) return false;
+    try {
 
-    //!!! n.b. can throw
-    if (!cache->haveSetColumnAt(col)) {
-        Profiler profiler("FFTDataServer::getNormalizedMagnitudesAt: filling");
-        fillColumn(x);
-    }
+        size_t col;
+        FFTCacheReader *cache = getCacheReader(x, col);
+        if (!cache) return false;
 
-    for (size_t i = 0; i < count; ++i) {
-        values[i] = cache->getNormalizedMagnitudeAt(col, i * step + minbin);
+        if (!cache->haveSetColumnAt(col)) {
+            Profiler profiler("FFTDataServer::getNormalizedMagnitudesAt: filling");
+            fillColumn(x);
+        }
+        
+        for (size_t i = 0; i < count; ++i) {
+            values[i] = cache->getNormalizedMagnitudeAt(col, i * step + minbin);
+        }
+        
+    } catch (std::exception &e) {
+        m_error = e.what();
+        return false;
     }
 
     return true;
@@ -989,16 +1020,25 @@
 
     if (x >= m_width) return 0;
 
-    size_t col;
-    FFTCacheReader *cache = getCacheReader(x, col);
-    if (!cache) return 0;
+    float val = 0;
 
-    //!!! n.b. can throw
-    if (!cache->haveSetColumnAt(col)) {
-        Profiler profiler("FFTDataServer::getMaximumMagnitudeAt: filling");
-        fillColumn(x);
+    try {
+
+        size_t col;
+        FFTCacheReader *cache = getCacheReader(x, col);
+        if (!cache) return 0;
+
+        if (!cache->haveSetColumnAt(col)) {
+            Profiler profiler("FFTDataServer::getMaximumMagnitudeAt: filling");
+            fillColumn(x);
+        }
+        val = cache->getMaximumMagnitudeAt(col);
+
+    } catch (std::exception &e) {
+        m_error = e.what();
     }
-    return cache->getMaximumMagnitudeAt(col);
+
+    return val;
 }
 
 float
@@ -1008,16 +1048,25 @@
 
     if (x >= m_width || y >= m_height) return 0;
 
-    size_t col;
-    FFTCacheReader *cache = getCacheReader(x, col);
-    if (!cache) return 0;
+    float val = 0;
 
-    //!!! n.b. can throw
-    if (!cache->haveSetColumnAt(col)) {
-        Profiler profiler("FFTDataServer::getPhaseAt: filling");
-        fillColumn(x);
+    try {
+
+        size_t col;
+        FFTCacheReader *cache = getCacheReader(x, col);
+        if (!cache) return 0;
+
+        if (!cache->haveSetColumnAt(col)) {
+            Profiler profiler("FFTDataServer::getPhaseAt: filling");
+            fillColumn(x);
+        }
+        val = cache->getPhaseAt(col, y);
+
+    } catch (std::exception &e) {
+        m_error = e.what();
     }
-    return cache->getPhaseAt(col, y);
+
+    return val;
 }
 
 bool
@@ -1033,18 +1082,24 @@
         count = (m_height - minbin) / step;
     }
 
-    size_t col;
-    FFTCacheReader *cache = getCacheReader(x, col);
-    if (!cache) return false;
+    try {
 
-    //!!! n.b. can throw
-    if (!cache->haveSetColumnAt(col)) {
-        Profiler profiler("FFTDataServer::getPhasesAt: filling");
-        fillColumn(x);
-    }
+        size_t col;
+        FFTCacheReader *cache = getCacheReader(x, col);
+        if (!cache) return false;
 
-    for (size_t i = 0; i < count; ++i) {
-        values[i] = cache->getPhaseAt(col, i * step + minbin);
+        if (!cache->haveSetColumnAt(col)) {
+            Profiler profiler("FFTDataServer::getPhasesAt: filling");
+            fillColumn(x);
+        }
+        
+        for (size_t i = 0; i < count; ++i) {
+            values[i] = cache->getPhaseAt(col, i * step + minbin);
+        }
+
+    } catch (std::exception &e) {
+        m_error = e.what();
+        return false;
     }
 
     return true;
@@ -1061,25 +1116,30 @@
         return;
     }
 
-    size_t col;
-    FFTCacheReader *cache = getCacheReader(x, col);
+    try {
 
-    if (!cache) {
-        real = 0;
-        imaginary = 0;
-        return;
+        size_t col;
+        FFTCacheReader *cache = getCacheReader(x, col);
+
+        if (!cache) {
+            real = 0;
+            imaginary = 0;
+            return;
+        }
+
+        if (!cache->haveSetColumnAt(col)) {
+            Profiler profiler("FFTDataServer::getValuesAt: filling");
+#ifdef DEBUG_FFT_SERVER
+            std::cerr << "FFTDataServer::getValuesAt(" << x << ", " << y << "): filling" << std::endl;
+#endif
+            fillColumn(x);
+        }        
+
+        cache->getValuesAt(col, y, real, imaginary);
+
+    } catch (std::exception &e) {
+        m_error = e.what();
     }
-
-    //!!! n.b. can throw
-    if (!cache->haveSetColumnAt(col)) {
-        Profiler profiler("FFTDataServer::getValuesAt: filling");
-#ifdef DEBUG_FFT_SERVER
-        std::cerr << "FFTDataServer::getValuesAt(" << x << ", " << y << "): filling" << std::endl;
-#endif
-        fillColumn(x);
-    }        
-
-    cache->getValuesAt(col, y, real, imaginary);
 }
 
 bool
@@ -1095,18 +1155,24 @@
         count = (m_height - minbin) / step;
     }
 
-    size_t col;
-    FFTCacheReader *cache = getCacheReader(x, col);
-    if (!cache) return false;
+    try {
 
-    //!!! n.b. can throw
-    if (!cache->haveSetColumnAt(col)) {
-        Profiler profiler("FFTDataServer::getValuesAt: filling");
-        fillColumn(x);
-    }
+        size_t col;
+        FFTCacheReader *cache = getCacheReader(x, col);
+        if (!cache) return false;
 
-    for (size_t i = 0; i < count; ++i) {
-        cache->getValuesAt(col, i * step + minbin, reals[i], imaginaries[i]);
+        if (!cache->haveSetColumnAt(col)) {
+            Profiler profiler("FFTDataServer::getValuesAt: filling");
+            fillColumn(x);
+        }
+
+        for (size_t i = 0; i < count; ++i) {
+            cache->getValuesAt(col, i * step + minbin, reals[i], imaginaries[i]);
+        }
+
+    } catch (std::exception &e) {
+        m_error = e.what();
+        return false;
     }
 
     return true;
@@ -1132,12 +1198,18 @@
         return false;
     }
 
-    size_t col;
-    FFTCacheReader *cache = getCacheReader(x, col);
-    if (!cache) return true;
+    try {
 
-    //!!! n.b. can throw
-    return cache->haveSetColumnAt(col);
+        size_t col;
+        FFTCacheReader *cache = getCacheReader(x, col);
+        if (!cache) return true;
+
+        return cache->haveSetColumnAt(col);
+
+    } catch (std::exception &e) {
+        m_error = e.what();
+        return false;
+    }
 }    
 
 void
@@ -1307,6 +1379,7 @@
 FFTDataServer::fillComplete()
 {
     for (int i = 0; i < int(m_caches.size()); ++i) {
+        if (!m_caches[i]) continue;
         if (m_caches[i]->memoryCache) {
             m_caches[i]->memoryCache->allColumnsWritten();
         }
@@ -1316,6 +1389,14 @@
     }
 }
 
+QString
+FFTDataServer::getError() const
+{
+    if (m_error != "") return m_error;
+    else if (m_fillThread) return m_fillThread->getError();
+    else return "";
+}
+
 size_t
 FFTDataServer::getFillCompletion() const 
 {
@@ -1392,7 +1473,16 @@
 
         for (size_t f = m_fillFrom; f < end; f += m_server.m_windowIncrement) {
 	    
-            m_server.fillColumn(int((f - start) / m_server.m_windowIncrement));
+            try {
+                m_server.fillColumn(int((f - start) / m_server.m_windowIncrement));
+            } catch (std::exception &e) {
+                std::cerr << "FFTDataServer::FillThread::run: exception: " << e.what() << std::endl;
+                m_error = e.what();
+                m_server.fillComplete();
+                m_completion = 100;
+                m_extent = end;
+                return;
+            }
 
             if (m_server.m_exiting) return;
 
@@ -1432,7 +1522,16 @@
 
     for (size_t f = start; f < remainingEnd; f += m_server.m_windowIncrement) {
 
-        m_server.fillColumn(int((f - start) / m_server.m_windowIncrement));
+        try {
+            m_server.fillColumn(int((f - start) / m_server.m_windowIncrement));
+        } catch (std::exception &e) {
+            std::cerr << "FFTDataServer::FillThread::run: exception: " << e.what() << std::endl;
+            m_error = e.what();
+            m_server.fillComplete();
+            m_completion = 100;
+            m_extent = end;
+            return;
+        }
 
         if (m_server.m_exiting) return;
 
--- a/data/fft/FFTDataServer.h	Thu Apr 07 15:20:35 2011 +0100
+++ b/data/fft/FFTDataServer.h	Thu Apr 14 15:20:27 2011 +0100
@@ -106,6 +106,7 @@
         return getMagnitudeAt(x, y) > threshold;
     }
 
+    QString getError() const;
     size_t getFillCompletion() const;
     size_t getFillExtent() const;
 
@@ -246,6 +247,7 @@
 
         size_t getExtent() const { return m_extent; }
         size_t getCompletion() const { return m_completion ? m_completion : 1; }
+        QString getError() const { return m_error; }
         virtual void run();
 
     protected:
@@ -253,11 +255,13 @@
         size_t m_extent;
         size_t m_completion;
         size_t m_fillFrom;
+        QString m_error;
     };
 
     bool m_exiting;
     bool m_suspended;
     FillThread *m_fillThread;
+    QString m_error;
 
     void deleteProcessingData();
     void fillColumn(size_t x);
--- a/data/fileio/FileSource.cpp	Thu Apr 07 15:20:35 2011 +0100
+++ b/data/fileio/FileSource.cpp	Thu Apr 14 15:20:27 2011 +0100
@@ -590,6 +590,12 @@
 }
 
 QString
+FileSource::getBasename() const
+{
+    return QFileInfo(m_localFilename).fileName();
+}
+
+QString
 FileSource::getContentType() const
 {
     return m_contentType;
--- a/data/fileio/FileSource.h	Thu Apr 07 15:20:35 2011 +0100
+++ b/data/fileio/FileSource.h	Thu Apr 14 15:20:27 2011 +0100
@@ -143,6 +143,12 @@
     QString getLocalFilename() const;
 
     /**
+     * Return the base name, i.e. the final path element (including
+     * extension, if any) of the location.
+     */
+    QString getBasename() const;
+
+    /**
      * Return the MIME content type of this file, if known.
      */
     QString getContentType() const;
--- a/data/model/FFTModel.h	Thu Apr 07 15:20:35 2011 +0100
+++ b/data/model/FFTModel.h	Thu Apr 14 15:20:27 2011 +0100
@@ -177,6 +177,7 @@
                                        size_t ymin = 0, size_t ymax = 0);
 
     virtual int getCompletion() const { return m_server->getFillCompletion(); }
+    virtual QString getError() const { return m_server->getError(); }
 
     virtual Model *clone() const;
 
--- a/transform/FeatureExtractionModelTransformer.cpp	Thu Apr 07 15:20:35 2011 +0100
+++ b/transform/FeatureExtractionModelTransformer.cpp	Thu Apr 14 15:20:27 2011 +0100
@@ -487,6 +487,8 @@
         imaginaries = new float[blockSize/2 + 1];
     }
 
+    QString error = "";
+
     while (!m_abandoned) {
 
         if (frequencyDomain) {
@@ -515,6 +517,12 @@
                     buffers[ch][i*2] = reals[i];
                     buffers[ch][i*2+1] = imaginaries[i];
                 }
+                error = fftModels[ch]->getError();
+                if (error != "") {
+                    std::cerr << "FeatureExtractionModelTransformer::run: Abandoning, error is " << error << std::endl;
+                    m_abandoned = true;
+                    m_message = error;
+                }
             }
         } else {
             getFrames(channelCount, blockFrame, blockSize, buffers);