comparison data/fft/FFTDataServer.cpp @ 200:2f2d282d45d0

* Somewhat better handling of running out of memory or disc space
author Chris Cannam
date Mon, 13 Nov 2006 14:48:57 +0000
parents c92a605f6b59
children 91fdc752e540
comparison
equal deleted inserted replaced
199:1d789d688f59 200:2f2d282d45d0
21 #include "model/DenseTimeValueModel.h" 21 #include "model/DenseTimeValueModel.h"
22 22
23 #include "system/System.h" 23 #include "system/System.h"
24 24
25 #include "base/StorageAdviser.h" 25 #include "base/StorageAdviser.h"
26 #include "base/Exceptions.h"
26 #include "base/Profiler.h" 27 #include "base/Profiler.h"
28
29 #include <QMessageBox>
30 #include <QApplication>
27 31
28 32
29 //#define DEBUG_FFT_SERVER 1 33 //#define DEBUG_FFT_SERVER 1
30 //#define DEBUG_FFT_SERVER_FILL 1 34 //#define DEBUG_FFT_SERVER_FILL 1
31 35
74 78
75 if ((server = findServer(npn))) { 79 if ((server = findServer(npn))) {
76 return server; 80 return server;
77 } 81 }
78 82
79 m_servers[n] = ServerCountPair 83 try {
80 (new FFTDataServer(n, 84 server = new FFTDataServer(n,
81 model, 85 model,
82 channel, 86 channel,
83 windowType, 87 windowType,
84 windowSize, 88 windowSize,
85 windowIncrement, 89 windowIncrement,
86 fftSize, 90 fftSize,
87 polar, 91 polar,
88 fillFromColumn), 92 fillFromColumn);
89 1); 93 } catch (InsufficientDiscSpace) {
90 94 delete server;
91 return m_servers[n].first; 95 server = 0;
96 }
97
98 if (server) {
99 m_servers[n] = ServerCountPair(server, 1);
100 }
101
102 return server;
92 } 103 }
93 104
94 FFTDataServer * 105 FFTDataServer *
95 FFTDataServer::getFuzzyInstance(const DenseTimeValueModel *model, 106 FFTDataServer::getFuzzyInstance(const DenseTimeValueModel *model,
96 int channel, 107 int channel,
362 373
363 int cells = m_width * m_height; 374 int cells = m_width * m_height;
364 int minimumSize = (cells / 1024) * sizeof(uint16_t); // kb 375 int minimumSize = (cells / 1024) * sizeof(uint16_t); // kb
365 int maximumSize = (cells / 1024) * sizeof(float); // kb 376 int maximumSize = (cells / 1024) * sizeof(float); // kb
366 377
367 //!!! catch InsufficientDiscSpace 378 // This can throw InsufficientDiscSpace. We don't catch it here -- we
379 // haven't allocated anything yet and can safely let the exception out.
380 // Caller needs to check for it.
368 381
369 StorageAdviser::Recommendation recommendation = 382 StorageAdviser::Recommendation recommendation =
370 StorageAdviser::recommend(criteria, minimumSize, maximumSize); 383 StorageAdviser::recommend(criteria, minimumSize, maximumSize);
371 384
372 std::cerr << "Recommendation was: " << recommendation << std::endl; 385 std::cerr << "Recommendation was: " << recommendation << std::endl;
373 386
374 m_memoryCache = ((recommendation & StorageAdviser::UseMemory) || 387 m_memoryCache = ((recommendation & StorageAdviser::UseMemory) ||
542 555
543 QString name = QString("%1-%2").arg(m_fileBaseName).arg(c); 556 QString name = QString("%1-%2").arg(m_fileBaseName).arg(c);
544 557
545 FFTCache *cache = 0; 558 FFTCache *cache = 0;
546 559
547 if (m_memoryCache) { 560 try {
548 561
549 cache = new FFTMemoryCache(); 562 if (m_memoryCache) {
550 563
551 } else if (m_compactCache) { 564 cache = new FFTMemoryCache();
552 565
553 cache = new FFTFileCache(name, MatrixFile::ReadWrite, 566 } else if (m_compactCache) {
554 FFTFileCache::Compact); 567
555 568 cache = new FFTFileCache(name, MatrixFile::ReadWrite,
556 } else { 569 FFTFileCache::Compact);
557 570
558 cache = new FFTFileCache(name, MatrixFile::ReadWrite, 571 } else {
559 m_polar ? FFTFileCache::Polar : 572
560 FFTFileCache::Rectangular); 573 cache = new FFTFileCache(name, MatrixFile::ReadWrite,
561 } 574 m_polar ? FFTFileCache::Polar :
562 575 FFTFileCache::Rectangular);
563 // FFTCache *cache = new FFTMemoryCache(); 576 }
564 577
565 size_t width = m_cacheWidth; 578 size_t width = m_cacheWidth;
566 if (c * m_cacheWidth + width > m_width) { 579 if (c * m_cacheWidth + width > m_width) {
567 width = m_width - c * m_cacheWidth; 580 width = m_width - c * m_cacheWidth;
568 } 581 }
569 582
570 cache->resize(width, m_height); 583 cache->resize(width, m_height);
571 cache->reset(); 584 cache->reset();
585
586 } catch (std::bad_alloc) {
587 std::cerr << "ERROR: Memory allocation failed in FFTFileCache::resize:"
588 << " abandoning this cache" << std::endl;
589 //!!! Shouldn't be using QtGui here. Need a better way to report this.
590 QMessageBox::critical
591 (0, QApplication::tr("FFT cache resize failed"),
592 QApplication::tr
593 ("Failed to create or resize an FFT model slice.\n"
594 "There may be insufficient memory or disc space to continue."));
595 delete cache;
596 m_caches[c] = 0;
597 return 0;
598 }
572 599
573 m_caches[c] = cache; 600 m_caches[c] = cache;
574 m_lastUsedCache = c; 601 m_lastUsedCache = c;
575 602
576 return cache; 603 return cache;
581 { 608 {
582 Profiler profiler("FFTDataServer::getMagnitudeAt", false); 609 Profiler profiler("FFTDataServer::getMagnitudeAt", false);
583 610
584 size_t col; 611 size_t col;
585 FFTCache *cache = getCache(x, col); 612 FFTCache *cache = getCache(x, col);
613 if (!cache) return 0;
586 614
587 if (!cache->haveSetColumnAt(col)) { 615 if (!cache->haveSetColumnAt(col)) {
588 std::cerr << "FFTDataServer::getMagnitudeAt: calling fillColumn(" 616 std::cerr << "FFTDataServer::getMagnitudeAt: calling fillColumn("
589 << x << ")" << std::endl; 617 << x << ")" << std::endl;
590 fillColumn(x); 618 fillColumn(x);
597 { 625 {
598 Profiler profiler("FFTDataServer::getNormalizedMagnitudeAt", false); 626 Profiler profiler("FFTDataServer::getNormalizedMagnitudeAt", false);
599 627
600 size_t col; 628 size_t col;
601 FFTCache *cache = getCache(x, col); 629 FFTCache *cache = getCache(x, col);
630 if (!cache) return 0;
602 631
603 if (!cache->haveSetColumnAt(col)) { 632 if (!cache->haveSetColumnAt(col)) {
604 fillColumn(x); 633 fillColumn(x);
605 } 634 }
606 return cache->getNormalizedMagnitudeAt(col, y); 635 return cache->getNormalizedMagnitudeAt(col, y);
611 { 640 {
612 Profiler profiler("FFTDataServer::getMaximumMagnitudeAt", false); 641 Profiler profiler("FFTDataServer::getMaximumMagnitudeAt", false);
613 642
614 size_t col; 643 size_t col;
615 FFTCache *cache = getCache(x, col); 644 FFTCache *cache = getCache(x, col);
645 if (!cache) return 0;
616 646
617 if (!cache->haveSetColumnAt(col)) { 647 if (!cache->haveSetColumnAt(col)) {
618 fillColumn(x); 648 fillColumn(x);
619 } 649 }
620 return cache->getMaximumMagnitudeAt(col); 650 return cache->getMaximumMagnitudeAt(col);
625 { 655 {
626 Profiler profiler("FFTDataServer::getPhaseAt", false); 656 Profiler profiler("FFTDataServer::getPhaseAt", false);
627 657
628 size_t col; 658 size_t col;
629 FFTCache *cache = getCache(x, col); 659 FFTCache *cache = getCache(x, col);
660 if (!cache) return 0;
630 661
631 if (!cache->haveSetColumnAt(col)) { 662 if (!cache->haveSetColumnAt(col)) {
632 fillColumn(x); 663 fillColumn(x);
633 } 664 }
634 return cache->getPhaseAt(col, y); 665 return cache->getPhaseAt(col, y);
639 { 670 {
640 Profiler profiler("FFTDataServer::getValuesAt", false); 671 Profiler profiler("FFTDataServer::getValuesAt", false);
641 672
642 size_t col; 673 size_t col;
643 FFTCache *cache = getCache(x, col); 674 FFTCache *cache = getCache(x, col);
675 if (!cache) { real = 0; imaginary = 0; return; }
644 676
645 if (!cache->haveSetColumnAt(col)) { 677 if (!cache->haveSetColumnAt(col)) {
646 #ifdef DEBUG_FFT_SERVER 678 #ifdef DEBUG_FFT_SERVER
647 std::cerr << "FFTDataServer::getValuesAt(" << x << ", " << y << "): filling" << std::endl; 679 std::cerr << "FFTDataServer::getValuesAt(" << x << ", " << y << "): filling" << std::endl;
648 #endif 680 #endif
670 return false; 702 return false;
671 } 703 }
672 704
673 size_t col; 705 size_t col;
674 FFTCache *cache = getCache(x, col); 706 FFTCache *cache = getCache(x, col);
707 if (!cache) return true;
675 708
676 return cache->haveSetColumnAt(col); 709 return cache->haveSetColumnAt(col);
677 } 710 }
678 711
679 void 712 void
684 size_t col; 717 size_t col;
685 #ifdef DEBUG_FFT_SERVER_FILL 718 #ifdef DEBUG_FFT_SERVER_FILL
686 std::cout << "FFTDataServer::fillColumn(" << x << ")" << std::endl; 719 std::cout << "FFTDataServer::fillColumn(" << x << ")" << std::endl;
687 #endif 720 #endif
688 FFTCache *cache = getCache(x, col); 721 FFTCache *cache = getCache(x, col);
722 if (!cache) return;
689 723
690 QMutexLocker locker(&m_writeMutex); 724 QMutexLocker locker(&m_writeMutex);
691 725
692 if (cache->haveSetColumnAt(col)) return; 726 if (cache->haveSetColumnAt(col)) return;
693 727