USGS

Isis 3.0 Object Programmers' Reference

Home

CubeDataThreadTester.cpp
00001 #include "CubeDataThreadTester.h"
00002 
00003 #include <iostream>
00004 
00005 #include <QMap>
00006 #include <QMutex>
00007 #include <QReadWriteLock>
00008 #include <QPair>
00009 #include <QVector>
00010 
00011 #include "CubeDataThread.h"
00012 #include "IString.h"
00013 #include "FileName.h"
00014 #include "Brick.h"
00015 #include "Cube.h"
00016 
00017 using namespace std;
00018 using namespace Isis;
00019 
00020 namespace Isis {
00027   CubeDataThreadTester::CubeDataThreadTester(CubeDataThread *testObject) :
00028     QThread() {
00029     p_cachedDoneBricks = NULL;
00030     p_cubeDataThread = testObject;
00031     p_numTestsDone = 0;
00032     p_execStarted = false;
00033     p_notifyDone = true;
00034 
00035     p_cachedDoneBricks = new QVector< QPair<int, const Isis::Brick *> >;
00036 
00037     start();
00038     moveToThread(this);
00039   }
00040 
00041 
00046   void CubeDataThreadTester::Connect() {
00047     connect(this,
00048             SIGNAL(RequestReadCube(int, int, int, int, int, int, void *)),
00049             p_cubeDataThread,
00050             SLOT(ReadCube(int, int, int, int, int, int, void *)));
00051 
00052     connect(this,
00053             SIGNAL(RequestReadWriteCube(int, int, int, int, int, int, void *)),
00054             p_cubeDataThread,
00055             SLOT(ReadWriteCube(int, int, int, int, int, int, void *)));
00056 
00057     connect(this, SIGNAL(NotifyDoneWithData(int, const Isis::Brick *)),
00058             p_cubeDataThread, SLOT(DoneWithData(int, const Isis::Brick *)));
00059 
00060     connect(p_cubeDataThread, SIGNAL(ReadReady(void *, int, const Isis::Brick *)),
00061             this, SLOT(ReadBrick(void *, int, const Isis::Brick *)));
00062 
00063     connect(p_cubeDataThread, SIGNAL(ReadWriteReady(void *, int, Isis::Brick *)),
00064             this, SLOT(ReadWriteBrick(void *, int, Isis::Brick *)));
00065   }
00066 
00067 
00072   CubeDataThreadTester::~CubeDataThreadTester() {
00073     if(!p_execStarted) {
00074       QThread::yieldCurrentThread();
00075     }
00076 
00077     QThread::exit(0);
00078 
00079     wait();
00080   }
00081 
00083   void CubeDataThreadTester::run() {
00084     p_execStarted = true;
00085     exec();
00086   }
00087 
00093   void CubeDataThreadTester::ReadCubeTest(int cubeId) {
00094     cout << "=============== Testing Basic Read ===============" << endl;
00095     emit RequestReadCube(cubeId, 1, 1, 2, 2, 1, this);
00096   }
00097 
00098 
00105   void CubeDataThreadTester::ReadCubeTest2(int cubeId1, int cubeId2) {
00106     cout << "=============== Testing Multiple Non-Conflicting Cube Reads " <<
00107          "===============" << endl;
00108 
00109     p_notifyDone = false;
00110     emit RequestReadCube(cubeId1, 1, 1, 3, 2, 1, this);
00111     emit RequestReadCube(cubeId2, 1, 2, 3, 2, 1, this);
00112   }
00113 
00114 
00120   void CubeDataThreadTester::ReadCubeTest3(int cubeId) {
00121     cout << "=============== Testing Exact Overlap Cube Reads ==============="
00122          << endl << endl;
00123 
00124     p_notifyDone = false;
00125     emit RequestReadCube(cubeId, 1, 2, 2, 2, 1, this);
00126     emit RequestReadCube(cubeId, 1, 2, 2, 2, 1, this);
00127   }
00128 
00129 
00135   void CubeDataThreadTester::WriteCubeTest(int cubeId) {
00136     cout << "=============== Testing Basic R/W ===============" << endl << endl;
00137     emit RequestReadWriteCube(cubeId, 1, 1, 2, 2, 1, this);
00138     emit RequestReadCube(cubeId, 1, 1, 2, 2, 1, this);
00139   }
00140 
00141 
00148   void CubeDataThreadTester::WriteCubeTest2(int cubeId1, int cubeId2) {
00149     cout << "=============== Testing Multiple Non-Conflicting Cube R/W " <<
00150          "===============" << endl << endl;
00151 
00152     p_notifyDone = false;
00153     emit RequestReadWriteCube(cubeId1, 1, 1, 3, 1, 1, this);
00154     emit RequestReadWriteCube(cubeId2, 1, 1, 3, 1, 1, this);
00155   }
00156 
00157 
00166   void CubeDataThreadTester::WriteCubeTest3(int cubeId) {
00167     cout << "=============== Testing Conflicting Cube R/W ==============="
00168          << endl;
00169 
00170     p_notifyDone = false;
00171     emit RequestReadWriteCube(cubeId, 1, 1, 3, 1, 1, this);
00172     emit RequestReadWriteCube(cubeId, 1, 1, 3, 1, 1, this);
00173   }
00174 
00175 
00180   void CubeDataThreadTester::WriteCubeTest3BreakDeadlock() {
00181     cout << "  Breaking Deadlock From Test 3" << endl;
00182     while(!p_cachedDoneBricks->size()) {
00183       msleep(100);
00184     }
00185 
00186     if(p_cachedDoneBricks->size()) {
00187       cout << "  Notify done with first brick" << endl;
00188       emit NotifyDoneWithData((*p_cachedDoneBricks)[0].first,
00189                               (*p_cachedDoneBricks)[0].second);
00190       p_cachedDoneBricks->clear();
00191     }
00192   }
00193 
00194 
00200   void CubeDataThreadTester::NotifyChangeTest(int cubeId) {
00201     cout << "=============== Testing Change Notification ==============="
00202          << endl;
00203 
00204     connect(p_cubeDataThread,
00205             SIGNAL(BrickChanged(int, const Isis::Brick *)),
00206             this,
00207             SLOT(BrickChanged(int, const Isis::Brick *))
00208            );
00209 
00210     p_cubeDataThread->AddChangeListener();
00211     emit RequestReadWriteCube(cubeId, 5, 1, 5, 1, 1, this);
00212   }
00213 
00214 
00222   void CubeDataThreadTester::ReadBrick(void *requester, int cubeId,
00223                                        const Isis::Brick *data) {
00224     cout << "  CubeDataThreadTester::ReadBrick" << endl;
00225 
00226     cout << "    Requester is me? " << ((this == requester) ? "Yes" : "No")
00227          << endl;
00228 
00229     if(this != requester) return;
00230 
00231     cout << "    Data:" << endl;
00232 
00233     for(int i = 0; i < data->size(); i++) {
00234       if(i == 0) cout << "      ";
00235       if(i % 6 == 6 - 1 && i != data->size() - 1) {
00236         cout << data->at(i) << endl << "      ";
00237       }
00238       else if(i == data->size() - 1) {
00239         cout << data->at(i) << endl;
00240       }
00241       else {
00242         cout << data->at(i) << "\t";
00243       }
00244     }
00245 
00246     cout << endl;
00247     if(p_notifyDone) {
00248       cout << "  Notify done with this brick" << endl;
00249       emit NotifyDoneWithData(cubeId, data);
00250 
00251       if(p_cachedDoneBricks->size()) {
00252         cout << "  Notify done with first brick" << endl;
00253         emit NotifyDoneWithData((*p_cachedDoneBricks)[0].first,
00254                                 (*p_cachedDoneBricks)[0].second);
00255         p_cachedDoneBricks->clear();
00256       }
00257     }
00258     else {
00259       QPair<int, const Brick *> cache;
00260       cache.first = cubeId;
00261       cache.second = data;
00262 
00263       p_cachedDoneBricks->push_back(cache);
00264     }
00265 
00266     p_notifyDone = true;
00267     p_numTestsDone ++;
00268   }
00269 
00277   void CubeDataThreadTester::ReadWriteBrick(void *requester, int cubeId,
00278       Isis::Brick *data) {
00279     cout << "  CubeDataThreadTester::ReadWriteBrick" << endl;
00280 
00281     // This was a nice idea, but has race conditions that are difficult
00282     //   at best to resolve.
00283 
00284     //cout << "    Managed Bricks in Memory = " <<
00285     //  p_cubeDataThread->BricksInMemory() << endl;
00286 
00287     cout << "    Changing Brick : Index 0 Becoming 5" << endl;
00288     cout << endl;
00289 
00290     cout << "    Old Data: " << endl;
00291 
00292     for(int i = 0; i < data->size(); i++) {
00293       if(i == 0) cout << "      ";
00294       if(i % 6 == 6 - 1 && i != data->size() - 1) {
00295         cout << data->at(i) << endl << "      ";
00296       }
00297       else if(i == data->size() - 1) {
00298         cout << data->at(i) << endl;
00299       }
00300       else {
00301         cout << data->at(i) << "\t";
00302       }
00303     }
00304 
00305     (*data)[0] = 5;
00306 
00307     cout << "    New Data: " << endl;
00308 
00309     for(int i = 0; i < data->size(); i++) {
00310       if(i == 0) cout << "      ";
00311       if(i % 6 == 6 - 1 && i != data->size() - 1) {
00312         cout << data->at(i) << endl << "      ";
00313       }
00314       else if(i == data->size() - 1) {
00315         cout << data->at(i) << endl;
00316       }
00317       else {
00318         cout << data->at(i) << "\t";
00319       }
00320     }
00321 
00322     cout << endl;
00323 
00324     if(p_notifyDone) {
00325       cout << "  Notify done with this brick" << endl;
00326       emit NotifyDoneWithData(cubeId, data);
00327 
00328       if(p_cachedDoneBricks->size()) {
00329         cout << "  Notify done with first brick" << endl;
00330         emit NotifyDoneWithData((*p_cachedDoneBricks)[0].first,
00331                                 (*p_cachedDoneBricks)[0].second);
00332         p_cachedDoneBricks->clear();
00333       }
00334     }
00335     else {
00336       QPair<int, const Brick *> cache;
00337       cache.first = cubeId;
00338       cache.second = data;
00339 
00340       p_cachedDoneBricks->push_back(cache);
00341     }
00342 
00343     p_notifyDone = true;
00344     p_numTestsDone ++;
00345   }
00346 
00347 
00354   void CubeDataThreadTester::BrickChanged(int cubeId, const Isis::Brick *data) {
00355     cout << "  CubeDataThreadTester::BrickChanged" << endl;
00356     cout << "    Data:" << endl;
00357 
00358     for(int i = 0; i < data->size(); i++) {
00359       if(i == 0) cout << "      ";
00360       if(i % 6 == 6 - 1 && i != data->size() - 1) {
00361         cout << data->at(i) << endl << "       ";
00362       }
00363       else if(i == data->size() - 1) {
00364         cout << data->at(i) << endl;
00365       }
00366       else {
00367         cout << data->at(i) << "\t";
00368       }
00369     }
00370 
00371     p_numTestsDone ++;
00372     emit NotifyDoneWithData(cubeId, data);
00373   }
00374 };