<commit_before>#include "MetaImageImporter.hpp"
#include "Exception.hpp"
#include <fstream>
#include <boost/iostreams/device/mapped_file.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
using namespace fast;

Image::pointer MetaImageImporter::getOutput() {
    return getOutputData<Image>(0);
}

void MetaImageImporter::setFilename(std::string filename) {
    mFilename = filename;
    mIsModified = true;
}

MetaImageImporter::MetaImageImporter() {
    mFilename = "";
    mIsModified = true;
}

std::vector<std::string> stringSplit(std::string str, std::string delimiter) {
    std::vector<std::string> values;
    int startPosition = 0;
    int endPosition = str.find(delimiter, startPosition+1);
    while(true) {
        if(endPosition == std::string::npos) {
            endPosition = str.size();
            values.push_back(str.substr(startPosition, endPosition-startPosition));
            break;
        } else {
            values.push_back(str.substr(startPosition, endPosition-startPosition));
            startPosition = endPosition+1;
            endPosition = str.find(delimiter, startPosition+1);
        }
    }
    return values;
}

template <class T>
void * readRawData(std::string rawFilename, unsigned int width, unsigned int height, unsigned int depth, unsigned int nrOfComponents) {
    boost::iostreams::mapped_file_source file;
    file.open(rawFilename, width*height*depth*nrOfComponents*sizeof(T));
    if(!file.is_open())
        throw FileNotFoundException(rawFilename);
    T * data = new T[width*height*depth*nrOfComponents];
    T * fileData = (T*)file.data();
    memcpy(data,fileData,width*height*depth*nrOfComponents*sizeof(T));
    file.close();
    return data;
}

void MetaImageImporter::execute() {
    if(mFilename == "")
        throw Exception("Filename was not set in MetaImageImporter");

    // Open and parse mhd file
    std::fstream mhdFile;
    mhdFile.open(mFilename.c_str(), std::fstream::in);
    if(!mhdFile.is_open())
        throw FileNotFoundException(mFilename);
    std::string line;
    std::string rawFilename;
    bool sizeFound = false,
         rawFilenameFound = false,
         typeFound = false,
         dimensionsFound = false;
    std::string typeName;

    // Find NDims first
    bool imageIs3D = false;
    do {
        std::getline(mhdFile, line);
        if(line.substr(0, 5) == "NDims") {
            if(line.substr(5+3, 1) == "3") {
                imageIs3D = true;
            } else if(line.substr(5+3, 1) == "2") {
                imageIs3D = false;
            }
            dimensionsFound = true;
        }
    } while(!mhdFile.eof() && !dimensionsFound);

    if(!dimensionsFound)
        throw Exception("NDims not found in metaimage file.");

    // Reset and start reading file from beginning
    mhdFile.seekg(0);

    unsigned int width, height, depth = 1;
    unsigned int nrOfComponents = 1;
    Image::pointer output = getOutputData<Image>(0);

    Vector3f spacing(1,1,1), offset(0,0,0), centerOfRotation(0,0,0);
    Matrix3f transformMatrix = Matrix3f::Identity();

    do{
        std::getline(mhdFile, line);
        boost::trim(line);
        if(!mhdFile.eof()) {
            int firstSpace = line.find(" ");
            std::string key = line.substr(0, firstSpace);
            std::string value = line.substr(firstSpace+3);
            //this->setAttribute(key, value);
        }
        if(line.substr(0, 7) == "DimSize") {
            std::string sizeString = line.substr(7+3);
            std::string sizeX = sizeString.substr(0,sizeString.find(" "));
            sizeString = sizeString.substr(sizeString.find(" ")+1);
            std::string sizeY = sizeString.substr(0,sizeString.find(" "));
            width = boost::lexical_cast<int>(sizeX.c_str());
            height = boost::lexical_cast<int>(sizeY.c_str());
            if(imageIs3D) {
                sizeString = sizeString.substr(sizeString.find(" ")+1);
                std::string sizeZ = sizeString.substr(0,sizeString.find(" "));
                depth = boost::lexical_cast<int>(sizeZ.c_str());
            }

            sizeFound = true;
        } else if(line.substr(0, 15) == "ElementDataFile") {
            rawFilename = line.substr(15+3);
            rawFilenameFound = true;

            // Remove any trailing spaces
            int pos = rawFilename.find(" ");
            if(pos > 0)
            rawFilename = rawFilename.substr(0,pos);

            // Get path name
            pos = mFilename.rfind('/');
            if(pos > 0)
                rawFilename = mFilename.substr(0,pos+1) + rawFilename;
        } else if(line.substr(0, 11) == "ElementType") {
            typeFound = true;
            typeName = line.substr(11+3);

            // Remove any trailing spaces
            int pos = typeName.find(" ");
            if(pos > 0)
            typeName = typeName.substr(0,pos);

            if(typeName == "MET_SHORT") {
            } else if(typeName == "MET_USHORT") {
            } else if(typeName == "MET_CHAR") {
            } else if(typeName == "MET_UCHAR") {
            } else if(typeName == "MET_INT") {
            } else if(typeName == "MET_UINT") {
            } else if(typeName == "MET_FLOAT") {
            } else {
                throw Exception("Trying to read volume of unsupported data type", __LINE__, __FILE__);
            }
        } else if(line.substr(0,23) == "ElementNumberOfChannels") {
            nrOfComponents = boost::lexical_cast<int>(line.substr(23+3).c_str());
            if(nrOfComponents <= 0)
                throw Exception("Error in reading the number of components in the MetaImageImporter");
        } else if(line.substr(0, 14) == "ElementSpacing") {
            std::string sizeString = line.substr(14+3);
            boost::trim(sizeString);
            std::string sizeX = sizeString.substr(0,sizeString.find(" "));
            sizeString = sizeString.substr(sizeString.find(" ")+1);
            std::string sizeY = sizeString.substr(0,sizeString.find(" "));
            std::string sizeZ = "1";
            if(imageIs3D) {
                sizeString = sizeString.substr(sizeString.find(" ")+1);
                sizeZ = sizeString.substr(0,sizeString.find(" "));
            }

            spacing[0] = boost::lexical_cast<float>(sizeX.c_str());
            spacing[1] = boost::lexical_cast<float>(sizeY.c_str());
            spacing[2] = boost::lexical_cast<float>(sizeZ.c_str());
        } else if(line.substr(0, 16) == "CenterOfRotation") {
            std::string sizeString = line.substr(16+3);
            boost::trim(sizeString);
            std::string sizeX = sizeString.substr(0,sizeString.find(" "));
            sizeString = sizeString.substr(sizeString.find(" ")+1);
            std::string sizeY = sizeString.substr(0,sizeString.find(" "));
            sizeString = sizeString.substr(sizeString.find(" ")+1);
            std::string sizeZ = sizeString.substr(0,sizeString.find(" "));

            centerOfRotation[0] = boost::lexical_cast<float>(sizeX.c_str());
            centerOfRotation[1] = boost::lexical_cast<float>(sizeY.c_str());
            centerOfRotation[2] = boost::lexical_cast<float>(sizeZ.c_str());
        } else if(line.substr(0, 6) == "Offset") {
            std::string sizeString = line.substr(6+3);
            boost::trim(sizeString);
            std::string sizeX = sizeString.substr(0,sizeString.find(" "));
            sizeString = sizeString.substr(sizeString.find(" ")+1);
            std::string sizeY = sizeString.substr(0,sizeString.find(" "));
            sizeString = sizeString.substr(sizeString.find(" ")+1);
            std::string sizeZ = sizeString.substr(0,sizeString.find(" "));

            offset[0] = boost::lexical_cast<float>(sizeX.c_str());
            offset[1] = boost::lexical_cast<float>(sizeY.c_str());
            offset[2] = boost::lexical_cast<float>(sizeZ.c_str());
        } else if(line.substr(0, 15) == "TransformMatrix") {
            std::string string = line.substr(15+3);
            boost::trim(string);

            std::vector<std::string> values = stringSplit(string, " ");
            if(values.size() != 9)
                throw Exception("Encountered a transform matrix with incorrect number of elements in the MetaImageImporter");

            for(unsigned int i = 0; i < 3; i++) {
            for(unsigned int j = 0; j < 3; j++) {
                transformMatrix(j,i) = boost::lexical_cast<float>(values[j+i*3].c_str());
            }}
        }

    } while(!mhdFile.eof());

    mhdFile.close();
    if(!sizeFound || !rawFilenameFound || !typeFound || !dimensionsFound)
        throw Exception("Error reading the mhd file", __LINE__, __FILE__);

    if(rawFilename.substr(rawFilename.length()-5) == ".zraw")
        throw Exception("Error reading MetaImage. Compressed raw files (.zraw) currently not supported.");

    void * data;
    DataType type;
    if(typeName == "MET_SHORT") {
        type = TYPE_INT16;
        data = readRawData<short>(rawFilename, width, height, depth, nrOfComponents);
    } else if(typeName == "MET_USHORT") {
        type = TYPE_UINT16;
        data = readRawData<unsigned short>(rawFilename, width, height, depth, nrOfComponents);
    } else if(typeName == "MET_CHAR") {
        type = TYPE_INT8;
        data = readRawData<char>(rawFilename, width, height, depth, nrOfComponents);
    } else if(typeName == "MET_UCHAR") {
        type = TYPE_UINT8;
        data = readRawData<unsigned char>(rawFilename, width, height, depth, nrOfComponents);
    } else if(typeName == "MET_FLOAT") {
        type = TYPE_FLOAT;
        data = readRawData<float>(rawFilename, width, height, depth, nrOfComponents);
    }

    if(imageIs3D) {
        output->create3DImage(width,height,depth,type,nrOfComponents,getMainDevice(),data);
    } else {
        output->create2DImage(width,height,type,nrOfComponents,getMainDevice(),data);
    }

    output->setOffset(offset);
    output->setSpacing(spacing);
    output->setCenterOfRotation(centerOfRotation);
    output->setTransformMatrix(transformMatrix);

    // Clean up
    deleteArray(data, type);
}
<commit_msg>refactored the MetaImageImporter<commit_after>#include "MetaImageImporter.hpp"
#include "Exception.hpp"
#include <fstream>
#include <boost/iostreams/device/mapped_file.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
using namespace fast;

Image::pointer MetaImageImporter::getOutput() {
    return getOutputData<Image>(0);
}

void MetaImageImporter::setFilename(std::string filename) {
    mFilename = filename;
    mIsModified = true;
}

MetaImageImporter::MetaImageImporter() {
    mFilename = "";
    mIsModified = true;
}

std::vector<std::string> stringSplit(std::string str, std::string delimiter) {
    std::vector<std::string> values;
    int startPosition = 0;
    int endPosition = str.find(delimiter, startPosition+1);
    while(true) {
        if(endPosition == std::string::npos) {
            endPosition = str.size();
            values.push_back(str.substr(startPosition, endPosition-startPosition));
            break;
        } else {
            values.push_back(str.substr(startPosition, endPosition-startPosition));
            startPosition = endPosition+1;
            endPosition = str.find(delimiter, startPosition+1);
        }
    }
    return values;
}

template <class T>
void * readRawData(std::string rawFilename, unsigned int width, unsigned int height, unsigned int depth, unsigned int nrOfComponents) {
    boost::iostreams::mapped_file_source file;
    file.open(rawFilename, width*height*depth*nrOfComponents*sizeof(T));
    if(!file.is_open())
        throw FileNotFoundException(rawFilename);
    T * data = new T[width*height*depth*nrOfComponents];
    T * fileData = (T*)file.data();
    memcpy(data,fileData,width*height*depth*nrOfComponents*sizeof(T));
    file.close();
    return data;
}

void MetaImageImporter::execute() {
    if(mFilename == "")
        throw Exception("Filename was not set in MetaImageImporter");

    // Open and parse mhd file
    std::fstream mhdFile;
    mhdFile.open(mFilename.c_str(), std::fstream::in);
    if(!mhdFile.is_open())
        throw FileNotFoundException(mFilename);
    std::string line;
    std::string rawFilename;
    bool sizeFound = false,
         rawFilenameFound = false,
         typeFound = false,
         dimensionsFound = false;
    std::string typeName;

    // Find NDims first
    bool imageIs3D = false;
    do {
        std::getline(mhdFile, line);
        if(line.substr(0, 5) == "NDims") {
            if(line.substr(5+3, 1) == "3") {
                imageIs3D = true;
            } else if(line.substr(5+3, 1) == "2") {
                imageIs3D = false;
            }
            dimensionsFound = true;
        }
    } while(!mhdFile.eof() && !dimensionsFound);

    if(!dimensionsFound)
        throw Exception("NDims not found in metaimage file.");

    // Reset and start reading file from beginning
    mhdFile.seekg(0);

    unsigned int width, height, depth = 1;
    unsigned int nrOfComponents = 1;
    Image::pointer output = getOutputData<Image>(0);

    Vector3f spacing(1,1,1), offset(0,0,0), centerOfRotation(0,0,0);
    Matrix3f transformMatrix = Matrix3f::Identity();

    do{
        std::getline(mhdFile, line);
        boost::trim(line);
        if(line.size() == 0) // line is empty
            continue;
        int firstSpace = line.find(" ");
        std::string key = line.substr(0, firstSpace);
        boost::trim(key);
        int equalSignPos = line.find("=");
        std::string value = line.substr(equalSignPos+1);
        boost::trim(value);
        if(key == "DimSize") {
            std::vector<std::string> values;
            boost::split(values, value, boost::is_any_of(" "));
            // Remove any empty values:
            values.erase(std::remove(values.begin(), values.end(), ""), values.end());

            if(imageIs3D) {
                if(values.size() != 3)
                    throw Exception("DimSize in MetaImage file did not contain 3 numbers");
                depth = boost::lexical_cast<int>(values[2]);
            } else {
                if(values.size() != 2)
                    throw Exception("DimSize in MetaImage file did not contain 2 numbers");
            }
            width = boost::lexical_cast<int>(values[0]);
            height = boost::lexical_cast<int>(values[1]);
            sizeFound = true;
        } else if(key == "ElementDataFile") {
            rawFilename = value;
            rawFilenameFound = true;

            // Remove any trailing spaces
            int pos = rawFilename.find(" ");
            if(pos > 0)
            rawFilename = rawFilename.substr(0,pos);

            // Get path name
            pos = mFilename.rfind('/');
            if(pos > 0)
                rawFilename = mFilename.substr(0,pos+1) + rawFilename;
        } else if(key == "ElementType") {
            typeFound = true;
            typeName = value;

            // Remove any trailing spaces
            int pos = typeName.find(" ");
            if(pos > 0)
            typeName = typeName.substr(0,pos);

            if(typeName == "MET_SHORT") {
            } else if(typeName == "MET_USHORT") {
            } else if(typeName == "MET_CHAR") {
            } else if(typeName == "MET_UCHAR") {
            } else if(typeName == "MET_INT") {
            } else if(typeName == "MET_UINT") {
            } else if(typeName == "MET_FLOAT") {
            } else {
                throw Exception("Trying to read volume of unsupported data type", __LINE__, __FILE__);
            }
        } else if(key == "ElementNumberOfChannels") {
            nrOfComponents = boost::lexical_cast<int>(value.c_str());
            if(nrOfComponents <= 0)
                throw Exception("Error in reading the number of components in the MetaImageImporter");
        } else if(key == "ElementSpacing") {
            std::vector<std::string> values;
            boost::split(values, value, boost::is_any_of(" "));
            // Remove any empty values:
            values.erase(std::remove(values.begin(), values.end(), ""), values.end());
            if(imageIs3D) {
                if(values.size() != 3)
                    throw Exception("ElementSpacing in MetaImage file did not contain 3 numbers");
                spacing[0] = boost::lexical_cast<float>(values[0]);
                spacing[1] = boost::lexical_cast<float>(values[1]);
                spacing[2] = boost::lexical_cast<float>(values[2]);
            } else {
                if(values.size() != 2 && values.size() != 3)
                    throw Exception("ElementSpacing in MetaImage file did not contain 2 or 3 numbers");

                spacing[0] = boost::lexical_cast<float>(values[0]);
                spacing[1] = boost::lexical_cast<float>(values[1]);
                if(values.size() == 2) {
                    spacing[2] = 1;
                } else {
                    spacing[2] = boost::lexical_cast<float>(values[2]);
                }
            }

        } else if(key == "CenterOfRotation") {
            std::vector<std::string> values;
            boost::split(values, value, boost::is_any_of(" "));
            // Remove any empty values:
            values.erase(std::remove(values.begin(), values.end(), ""), values.end());
            if(imageIs3D) {
                if(values.size() != 3)
                    throw Exception("CenterOfRotation in MetaImage file did not contain 3 numbers");
                centerOfRotation[0] = boost::lexical_cast<float>(values[0]);
                centerOfRotation[1] = boost::lexical_cast<float>(values[1]);
                centerOfRotation[2] = boost::lexical_cast<float>(values[2]);
            } else {
                if(values.size() != 2 && values.size() != 3)
                    throw Exception("CenterOfRotation in MetaImage file did not contain 2 or 3 numbers");

                centerOfRotation[0] = boost::lexical_cast<float>(values[0]);
                centerOfRotation[1] = boost::lexical_cast<float>(values[1]);
                if(values.size() == 2) {
                    centerOfRotation[2] = 0;
                } else {
                    centerOfRotation[2] = boost::lexical_cast<float>(values[2]);
                }
            }
        } else if(key == "Offset") {
            std::vector<std::string> values;
            boost::split(values, value, boost::is_any_of(" "));
            // Remove any empty values:
            values.erase(std::remove(values.begin(), values.end(), ""), values.end());
            if(values.size() != 3)
                throw Exception("Offset in MetaImage file did not contain 3 numbers");

            offset[0] = boost::lexical_cast<float>(values[0].c_str());
            offset[1] = boost::lexical_cast<float>(values[1].c_str());
            offset[2] = boost::lexical_cast<float>(values[2].c_str());
        } else if(key == "TransformMatrix") {
            std::vector<std::string> values;
            boost::split(values, value, boost::is_any_of(" "));
            // Remove any empty values:
            values.erase(std::remove(values.begin(), values.end(), ""), values.end());
            if(values.size() != 9)
                throw Exception("Encountered a transform matrix with incorrect number of elements in the MetaImageImporter");

            for(unsigned int i = 0; i < 3; i++) {
            for(unsigned int j = 0; j < 3; j++) {
                transformMatrix(j,i) = boost::lexical_cast<float>(values[j+i*3].c_str());
            }}
        }

    } while(!mhdFile.eof());

    mhdFile.close();
    if(!sizeFound || !rawFilenameFound || !typeFound || !dimensionsFound)
        throw Exception("Error reading the mhd file", __LINE__, __FILE__);

    if(rawFilename.substr(rawFilename.length()-5) == ".zraw")
        throw Exception("Error reading MetaImage. Compressed raw files (.zraw) currently not supported.");

    void * data;
    DataType type;
    if(typeName == "MET_SHORT") {
        type = TYPE_INT16;
        data = readRawData<short>(rawFilename, width, height, depth, nrOfComponents);
    } else if(typeName == "MET_USHORT") {
        type = TYPE_UINT16;
        data = readRawData<unsigned short>(rawFilename, width, height, depth, nrOfComponents);
    } else if(typeName == "MET_CHAR") {
        type = TYPE_INT8;
        data = readRawData<char>(rawFilename, width, height, depth, nrOfComponents);
    } else if(typeName == "MET_UCHAR") {
        type = TYPE_UINT8;
        data = readRawData<unsigned char>(rawFilename, width, height, depth, nrOfComponents);
    } else if(typeName == "MET_FLOAT") {
        type = TYPE_FLOAT;
        data = readRawData<float>(rawFilename, width, height, depth, nrOfComponents);
    }

    if(imageIs3D) {
        output->create3DImage(width,height,depth,type,nrOfComponents,getMainDevice(),data);
    } else {
        output->create2DImage(width,height,type,nrOfComponents,getMainDevice(),data);
    }

    output->setOffset(offset);
    output->setSpacing(spacing);
    output->setCenterOfRotation(centerOfRotation);
    output->setTransformMatrix(transformMatrix);

    // Clean up
    deleteArray(data, type);
}
<|endoftext|>


<commit_before>/* socket_per_thread.cc
   Jeremy Barnes, 5 March 2012
   Copyright (c) 2012 Datacratic.  All rights reserved.

   One socket per thread.
*/

#include "soa/service/socket_per_thread.h"
#include "jml/arch/format.h"
#include "ace/OS_NS_Thread.h"
#include "jml/arch/backtrace.h"
#include "jml/arch/spinlock.h"
#include "jml/arch/atomic_ops.h"
#include "jml/arch/exception.h"
#include "jml/utils/exc_assert.h"
#include "soa/service/zmq_utils.h"

using namespace std;
using namespace ML;

namespace Datacratic {

/*****************************************************************************/
/* SOCKET PER THREAD                                                         */
/*****************************************************************************/

SocketPerThread::
SocketPerThread()
    : context(0), type(0), numOpen(0), state(NOTINITIALIZED),
      entries(onFreeEntry)
{
}

SocketPerThread::
SocketPerThread(zmq::context_t & context,
                int type,
                const std::string & uri,
                bool allowForceClose)
    : context(&context), type(type), uri(uri),
      allowForceClose(allowForceClose), numOpen(0),
      state(READY), entries(onFreeEntry)
{
    //std::cerr << "finished init of socket " << uri << std::endl;
}

SocketPerThread::
~SocketPerThread()
{
    shutdown();
}

void
SocketPerThread::
init(zmq::context_t & context,
     int type,
     const std::string & uri,
     bool allowForceClose)
{
    if (this->context)
        throw ML::Exception("attempt to double initialize a SocketPerThread");
    this->context = &context;
    this->type = type;
    this->uri = uri;
    this->allowForceClose = allowForceClose;

    state = READY;
    //using namespace std;
    //cerr << "initializing SocketPerThread with uri " << uri << endl;
}

void
SocketPerThread::
shutdown()
{
    state = FINISHED;

    entries.reset();
    context = 0;
    //using namespace std;
    //cerr << "destroying SocketPerThread with uri " << uri << " and "
    //     << numOpen << " open entries" << endl;

    if (numOpen > 0) {
        if (!allowForceClose) {
            throw ML::Exception("attempt to destroy SocketPerThread with %d open entries",
                                numOpen);
        }

        while (!allThreads.empty()) {
            auto it = allThreads.begin();
            onFreeEntry(*it);
        }

        ExcAssertEqual(numOpen, 0);
    }
}

void
SocketPerThread::
initForThisThread() const
{
    if (entries.get())
        return;

    //cerr << "initializing zeromq socket for this thread to connect to "
    //     << uri << endl;

    if (!context)
        throw ML::Exception("attempt to use a SocketPerThread "
                            "without initializing");

    auto mThis = const_cast<SocketPerThread *>(this);

    std::auto_ptr<Entry> newEntry(new Entry());
    newEntry->owner = mThis;

    std::auto_ptr<zmq::socket_t> newPtr
        (new zmq::socket_t(*context, type));
    setIdentity(*newPtr, ML::format("thr%lld",
                                    (long long)ACE_OS::thr_self()));
    newPtr->connect(uri.c_str());

    newEntry->sock = newPtr.release();
    //if (!allForThread.get())
    //    allForThread.reset(new std::set<SocketPerThread *>());
    //allForThread->insert(mThis);
    entries.reset(newEntry.release());

    mThis->addThreadEntry(entries.get());
    ML::atomic_inc(numOpen);
}

void
SocketPerThread::
onFreeEntry(Entry * entry)
{
    using namespace std;
    //cerr << "onFreeEntry " << entry << endl;
    //cerr << "closing zmq socket" << entry->sock << " with owner "
    //     << entry->owner << endl;
    delete entry->sock;
    //cerr << "erasing" << endl;
    //allForThread->erase(entry->owner);
    //cerr << "unowning" << endl;
    ML::atomic_dec(entry->owner->numOpen);

    entry->owner->removeThreadEntry(entry);

    delete entry;

    //Datacratic::close(*sock);
    //ML::backtrace();
    //cerr << endl << endl;
}

void
SocketPerThread::
cleanupThisThread()
{
    //cerr << "cleaning up socket " << entries->sock << endl;
    entries.reset();
}

void
SocketPerThread::
cleanupAllForThread()
{
    if (!allForThread.get()) return;
    //cerr << "cleaning up " << allForThread->size() << " sockets" << endl;

    for (auto it = allForThread->begin();  it != allForThread->end();
         it = allForThread->begin())
        (*it)->cleanupThisThread();

    //cerr << "we now have " << allForThread->size() << " sockets left" << endl;
}

void
SocketPerThread::
removeThreadEntry(Entry * entry)
{
    Guard guard(allThreadsLock);
    allThreads.erase(entry);
}

void
SocketPerThread::
addThreadEntry(Entry * entry)
{
    Guard guard(allThreadsLock);
    allThreads.insert(entry);
}

boost::thread_specific_ptr<std::set<SocketPerThread *> >
SocketPerThread::allForThread;

} // namespace Datacratic
<commit_msg>workaround the race condition in ZMQ<commit_after>/* socket_per_thread.cc
   Jeremy Barnes, 5 March 2012
   Copyright (c) 2012 Datacratic.  All rights reserved.

   One socket per thread.
*/

#include "soa/service/socket_per_thread.h"
#include "jml/arch/format.h"
#include "ace/OS_NS_Thread.h"
#include "jml/arch/backtrace.h"
#include "jml/arch/spinlock.h"
#include "jml/arch/atomic_ops.h"
#include "jml/arch/exception.h"
#include "jml/arch/timers.h"
#include "jml/utils/exc_assert.h"
#include "soa/service/zmq_utils.h"

using namespace std;
using namespace ML;

namespace Datacratic {

/*****************************************************************************/
/* SOCKET PER THREAD                                                         */
/*****************************************************************************/

SocketPerThread::
SocketPerThread()
    : context(0), type(0), numOpen(0), state(NOTINITIALIZED),
      entries(onFreeEntry)
{
}

SocketPerThread::
SocketPerThread(zmq::context_t & context,
                int type,
                const std::string & uri,
                bool allowForceClose)
    : context(&context), type(type), uri(uri),
      allowForceClose(allowForceClose), numOpen(0),
      state(READY), entries(onFreeEntry)
{
    //std::cerr << "finished init of socket " << uri << std::endl;
}

SocketPerThread::
~SocketPerThread()
{
    shutdown();
}

void
SocketPerThread::
init(zmq::context_t & context,
     int type,
     const std::string & uri,
     bool allowForceClose)
{
    if (this->context)
        throw ML::Exception("attempt to double initialize a SocketPerThread");
    this->context = &context;
    this->type = type;
    this->uri = uri;
    this->allowForceClose = allowForceClose;

    state = READY;
    //using namespace std;
    //cerr << "initializing SocketPerThread with uri " << uri << endl;
}

void
SocketPerThread::
shutdown()
{
    state = FINISHED;

    entries.reset();
    context = 0;
    //using namespace std;
    //cerr << "destroying SocketPerThread with uri " << uri << " and "
    //     << numOpen << " open entries" << endl;

    if (numOpen > 0) {
        if (!allowForceClose) {
            throw ML::Exception("attempt to destroy SocketPerThread with %d open entries",
                                numOpen);
        }

        while (!allThreads.empty()) {
            auto it = allThreads.begin();
            onFreeEntry(*it);
        }

        ExcAssertEqual(numOpen, 0);
    }
}

void
SocketPerThread::
initForThisThread() const
{
    if (entries.get())
        return;

    //cerr << "initializing zeromq socket for this thread to connect to "
    //     << uri << endl;

    if (!context)
        throw ML::Exception("attempt to use a SocketPerThread "
                            "without initializing");

    auto mThis = const_cast<SocketPerThread *>(this);

    std::auto_ptr<Entry> newEntry(new Entry());
    newEntry->owner = mThis;

    std::auto_ptr<zmq::socket_t> newPtr
        (new zmq::socket_t(*context, type));
    setIdentity(*newPtr, ML::format("thr%lld",
                                    (long long)ACE_OS::thr_self()));
    newPtr->connect(uri.c_str());

    newEntry->sock = newPtr.release();
    //if (!allForThread.get())
    //    allForThread.reset(new std::set<SocketPerThread *>());
    //allForThread->insert(mThis);
    entries.reset(newEntry.release());

    mThis->addThreadEntry(entries.get());
    ML::atomic_inc(numOpen);

    // wait for ZMQ when connecting...
    ML::sleep(0.1);
}

void
SocketPerThread::
onFreeEntry(Entry * entry)
{
    using namespace std;
    //cerr << "onFreeEntry " << entry << endl;
    //cerr << "closing zmq socket" << entry->sock << " with owner "
    //     << entry->owner << endl;
    delete entry->sock;
    //cerr << "erasing" << endl;
    //allForThread->erase(entry->owner);
    //cerr << "unowning" << endl;
    ML::atomic_dec(entry->owner->numOpen);

    entry->owner->removeThreadEntry(entry);

    delete entry;

    //Datacratic::close(*sock);
    //ML::backtrace();
    //cerr << endl << endl;
}

void
SocketPerThread::
cleanupThisThread()
{
    //cerr << "cleaning up socket " << entries->sock << endl;
    entries.reset();
}

void
SocketPerThread::
cleanupAllForThread()
{
    if (!allForThread.get()) return;
    //cerr << "cleaning up " << allForThread->size() << " sockets" << endl;

    for (auto it = allForThread->begin();  it != allForThread->end();
         it = allForThread->begin())
        (*it)->cleanupThisThread();

    //cerr << "we now have " << allForThread->size() << " sockets left" << endl;
}

void
SocketPerThread::
removeThreadEntry(Entry * entry)
{
    Guard guard(allThreadsLock);
    allThreads.erase(entry);
}

void
SocketPerThread::
addThreadEntry(Entry * entry)
{
    Guard guard(allThreadsLock);
    allThreads.insert(entry);
}

boost::thread_specific_ptr<std::set<SocketPerThread *> >
SocketPerThread::allForThread;

} // namespace Datacratic
<|endoftext|>


<commit_before>//
// QC.cpp
//
// Class to compute QC metrics on .sim files
// Metrics include: Sample magnitude (normalized by probe), sample xydiff
//
//
// Author: Iain Bancarz <ib5@sanger.ac.uk>
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation and/or
// other materials provided with the distribution.
// 3. Neither the name of the Genome Research Ltd nor the names of its contributors
// may be used to endorse or promote products derived from software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. EVENT SHALL GENOME RESEARCH LTD. BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
// THE POSSIBILITY OF SUCH DAMAGE.
//

#include <cmath>
#include <cstdio>
#include <ctime>
#include <iostream>
#include <stdlib.h>
#include <string.h>

#include "QC.h"
#include "Sim.h"

using namespace std;

QC::QC(string simPath, bool verbose=false) {
  qcsim = new Sim();
  if (!qcsim->errorMsg.empty()) {
    cout << qcsim->errorMsg << endl;
    exit(1);
  }
  qcsim->open(simPath);
  if (verbose) cerr << "Opened .sim file " << simPath << endl;
  // define vector objects to hold intensities
  intensity_int = new vector<uint16_t>();
  intensity_float = new vector<float>();
  if (verbose) cerr << "Created intensity vectors" << endl;
  int vectorSize = qcsim->numProbes * qcsim->numChannels;
  if (verbose) cerr << "Reserving space for " << vectorSize <<
		 " intensities... ";
  intensity_int->reserve(vectorSize);
  intensity_float->reserve(vectorSize);
  if (verbose) cerr << "done." << endl;
}

void QC::writeMagnitude(string outPath, bool verbose) {
  // compute normalized magnitudes by sample, write to given file
  qcsim->reset(); // return read position to first sample
  float *probeMagArray;
  probeMagArray = (float *) calloc(qcsim->numProbes, sizeof(float));
  magnitudeByProbe(probeMagArray, verbose);
  float *sampleMagArray;
  sampleMagArray = (float *) calloc(qcsim->numSamples, sizeof(float));
  char sampleNames[qcsim->numSamples][Sim::SAMPLE_NAME_SIZE+1];
  qcsim->reset();
  magnitudeBySample(sampleMagArray, probeMagArray, sampleNames, verbose);
  if (verbose) cerr << "Writing results" << endl;
  FILE *outFile = fopen(outPath.c_str(), "w");
  for (unsigned int i=0; i<qcsim->numSamples; i++) {
    // use fprintf to control number of decimal places
    fprintf(outFile, "%s\t%.6f\n", sampleNames[i], sampleMagArray[i]);
  }
  fclose(outFile);
  free(probeMagArray);
  free(sampleMagArray);
  if (verbose) cerr << "Finished magnitude" << endl;
}

void QC::writeXydiff(string outPath, bool verbose) {
  // compute XY intensity difference by sample, write to given file
  if (qcsim->numChannels!=2) {
    cerr << "Error: XY intensity difference is only defined for exactly "
      "two intensity channels." << endl;
    exit(1);
  }
  if (verbose) cerr << "Computing XY intensity difference" << endl;
  qcsim->reset(); // return read position to first sample
  float *xydArray;
  xydArray = (float *) calloc(qcsim->numSamples, sizeof(float));
  char sampleNames[qcsim->numSamples][Sim::SAMPLE_NAME_SIZE+1];
  xydiffBySample(xydArray, sampleNames);
  if (verbose) cerr << "Writing results" << endl;
  FILE *outFile = fopen(outPath.c_str(), "w");
  for (unsigned int i=0; i<qcsim->numSamples; i++) {
    // use fprintf to control number of decimal places
    fprintf(outFile, "%s\t%.6f\n", sampleNames[i], xydArray[i]);
  }
  if (verbose) cerr << "Finished xydiff" << endl;
  fclose(outFile);
}

void QC::getNextMagnitudes(float magnitudes[], char *sampleName, Sim *sim) {
  // compute magnitudes for each probe from next sample in .sim input
  // can handle arbitrarily many intensity channels; also reads sample name
  //vector<uint16_t> *intensity_int = new vector<uint16_t>;
  //vector<float> *intensity_float = new vector<float>;
  intensity_float->clear();
  intensity_int->clear();
  if (sim->numberFormat == 0) {
    sim->getNextRecord(sampleName, intensity_float);
  } else {
    sim->getNextRecord(sampleName, intensity_int);
  }
  for (unsigned int i=0; i < sim->numProbes; i++) {
    float total = 0.0; // running total of squared intensities
    for (int j=0; j<sim->numChannels; j++) {
      int index = i*sim->numChannels + j;
      float signal;
      if (sim->numberFormat == 0) signal = intensity_float->at(index);
      else signal = intensity_int->at(index);
      total += signal * signal;
    }
    magnitudes[i] = sqrt(total);
  }
}

void QC::magnitudeByProbe(float magByProbe[], bool verbose=false) {
  // iterate over samples; update running totals of magnitude by probe
  // then divide to find mean for each probe
  if (verbose) cerr << "Finding mean magnitude by probe" << endl;
  float *magnitudes;
  magnitudes = (float *) calloc(qcsim->numProbes, sizeof(float));
  char *sampleName; // placeholder; name used in magnitudeBySample
  sampleName = new char[qcsim->sampleNameSize];
  for(unsigned int i=0; i < qcsim->numSamples; i++) {
    getNextMagnitudes(magnitudes, sampleName, qcsim);
    for (unsigned int j=0; j < qcsim->numProbes; j++) {
      magByProbe[j] += magnitudes[j];
    }
    if (verbose && i % QC::VERBOSE_FREQ == 0) {
      char *t;
      t = new char[QC::TIME_BUFFER];
      timeText(t);
      cerr << t << " Sample " << i+1 << " of " << qcsim->numSamples << endl;
      delete t;
    }
  }
  for (unsigned int i=0; i < qcsim->numProbes; i++) {
    magByProbe[i] = magByProbe[i] / qcsim->numSamples;
  }
  free(magnitudes);
  if (verbose) cerr << "Completed mean magnitude by probe" << endl;
}

void QC::magnitudeBySample(float magBySample[], float magByProbe[],
			   char sampleNames[][Sim::SAMPLE_NAME_SIZE+1],
			   bool verbose=false) {
  // find mean sample magnitude, normalized for each probe
  // also read sample names
  if (verbose) cerr << "Finding normalized mean magnitude by sample" << endl;
  float *magnitudes;
  magnitudes = (float *) calloc(qcsim->numProbes, sizeof(float));
  for(unsigned int i=0; i < qcsim->numSamples; i++) {
    char *sampleName;
    sampleName = new char[qcsim->sampleNameSize];
    getNextMagnitudes(magnitudes, sampleName, qcsim);
    strcpy(sampleNames[i], sampleName);
    float mag = 0;
    for (unsigned int j=0; j < qcsim->numProbes; j++) {
      mag += magnitudes[j]/magByProbe[j];
    }
    magBySample[i] = mag / qcsim -> numProbes;
    if (verbose && i % QC::VERBOSE_FREQ == 0) {
      char *t;
      t = new char[QC::TIME_BUFFER];
      timeText(t);
      cerr << t << " Sample " << i+1 << " of " << qcsim->numSamples << endl;
      delete t;
    }
  }
  free(magnitudes);
  if (verbose) cerr << "Completed mean magnitude by sample" << endl;
}

void QC::xydiffBySample(float xydBySample[],
			char sampleNames[][Sim::SAMPLE_NAME_SIZE+1]) {
  // find xydiff and read sample names
  for(unsigned int i=0; i < qcsim->numSamples; i++) {
    char *sampleName;
    sampleName = new char[qcsim->sampleNameSize];
    float xydTotal = 0.0; // running total of xy difference
    vector<uint16_t> *intensity_int = new vector<uint16_t>;
    vector<float> *intensity_float = new vector<float>;
    if (qcsim->numberFormat == 0) {
      qcsim->getNextRecord(sampleName, intensity_float);
    } else {
      qcsim->getNextRecord(sampleName, intensity_int);
    }
    strcpy(sampleNames[i], sampleName);
    for (unsigned int j=0; j<qcsim->numProbes; j++) {
      int index = j*qcsim->numChannels;
      float xyd;
      if (qcsim->numberFormat == 0) {
	xyd = intensity_float->at(index+1) - intensity_float->at(index);
      }
      else {
	xyd = intensity_int->at(index+1) - intensity_int->at(index);
      }
      xydTotal += xyd;
    }
    xydBySample[i] = xydTotal / qcsim->numProbes;
    delete intensity_int;
    delete intensity_float;
  }
}

void QC::timeText(char *buffer) {
  // get current time in format 06-09-2013_09:01:58
  time_t rawtime;
  time(&rawtime);
  strftime(buffer, QC::TIME_BUFFER, "%d-%m-%Y_%H:%M:%S", localtime(&rawtime));
}

<commit_msg>Use pointers instead of at() for faster access to vector<commit_after>//
// QC.cpp
//
// Class to compute QC metrics on .sim files
// Metrics include: Sample magnitude (normalized by probe), sample xydiff
//
//
// Author: Iain Bancarz <ib5@sanger.ac.uk>
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation and/or
// other materials provided with the distribution.
// 3. Neither the name of the Genome Research Ltd nor the names of its contributors
// may be used to endorse or promote products derived from software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. EVENT SHALL GENOME RESEARCH LTD. BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
// THE POSSIBILITY OF SUCH DAMAGE.
//

#include <cmath>
#include <cstdio>
#include <ctime>
#include <iostream>
#include <stdlib.h>
#include <string.h>

#include "QC.h"
#include "Sim.h"

using namespace std;

QC::QC(string simPath, bool verbose=false) {
  qcsim = new Sim();
  if (!qcsim->errorMsg.empty()) {
    cout << qcsim->errorMsg << endl;
    exit(1);
  }
  qcsim->open(simPath);
  if (verbose) cerr << "Opened .sim file " << simPath << endl;
  // define vector objects to hold intensities
  intensity_int = new vector<uint16_t>();
  intensity_float = new vector<float>();
  if (verbose) cerr << "Created intensity vectors" << endl;
  int vectorSize = qcsim->numProbes * qcsim->numChannels;
  if (verbose) cerr << "Reserving space for " << vectorSize <<
		 " intensities... ";
  intensity_int->reserve(vectorSize);
  intensity_float->reserve(vectorSize);
  if (verbose) cerr << "done." << endl;
}

void QC::writeMagnitude(string outPath, bool verbose) {
  // compute normalized magnitudes by sample, write to given file
  qcsim->reset(); // return read position to first sample
  float *probeMagArray;
  probeMagArray = (float *) calloc(qcsim->numProbes, sizeof(float));
  magnitudeByProbe(probeMagArray, verbose);
  float *sampleMagArray;
  sampleMagArray = (float *) calloc(qcsim->numSamples, sizeof(float));
  char sampleNames[qcsim->numSamples][Sim::SAMPLE_NAME_SIZE+1];
  qcsim->reset();
  magnitudeBySample(sampleMagArray, probeMagArray, sampleNames, verbose);
  if (verbose) cerr << "Writing results" << endl;
  FILE *outFile = fopen(outPath.c_str(), "w");
  for (unsigned int i=0; i<qcsim->numSamples; i++) {
    // use fprintf to control number of decimal places
    fprintf(outFile, "%s\t%.6f\n", sampleNames[i], sampleMagArray[i]);
  }
  fclose(outFile);
  free(probeMagArray);
  free(sampleMagArray);
  if (verbose) cerr << "Finished magnitude" << endl;
}

void QC::writeXydiff(string outPath, bool verbose) {
  // compute XY intensity difference by sample, write to given file
  if (qcsim->numChannels!=2) {
    cerr << "Error: XY intensity difference is only defined for exactly "
      "two intensity channels." << endl;
    exit(1);
  }
  if (verbose) cerr << "Computing XY intensity difference" << endl;
  qcsim->reset(); // return read position to first sample
  float *xydArray;
  xydArray = (float *) calloc(qcsim->numSamples, sizeof(float));
  char sampleNames[qcsim->numSamples][Sim::SAMPLE_NAME_SIZE+1];
  xydiffBySample(xydArray, sampleNames);
  if (verbose) cerr << "Writing results" << endl;
  FILE *outFile = fopen(outPath.c_str(), "w");
  for (unsigned int i=0; i<qcsim->numSamples; i++) {
    // use fprintf to control number of decimal places
    fprintf(outFile, "%s\t%.6f\n", sampleNames[i], xydArray[i]);
  }
  if (verbose) cerr << "Finished xydiff" << endl;
  fclose(outFile);
}

void QC::getNextMagnitudes(float magnitudes[], char *sampleName, Sim *sim) {
  // compute magnitudes for each probe from next sample in .sim input
  // can handle arbitrarily many intensity channels; also reads sample name
  intensity_float->clear();
  intensity_int->clear();
  if (sim->numberFormat == 0) {
    sim->getNextRecord(sampleName, intensity_float);
  } else {
    sim->getNextRecord(sampleName, intensity_int);
  }
  // define pointer to first intensity element (depending on format)
  // pointer is used for fast access to vector contents
  float *intensityf;
  uint16_t *intensityi;
  unsigned int i, j, index;
  float intensity, total;
  if (sim->numberFormat == 0) intensityf = &(intensity_float->front());
  else intensityi = &(intensity_int->front());
  for (i=0; i < sim->numProbes; i++) {
    total = 0.0; // running total of squared intensities
    for (j=0; j<sim->numChannels; j++) {
      index = i*sim->numChannels + j;
      if (sim->numberFormat == 0) intensity = *(intensityf+index);
      else intensity = *(intensityi+index);
      total += intensity * intensity;
    }
    magnitudes[i] = sqrt(total);
  }
}

void QC::magnitudeByProbe(float magByProbe[], bool verbose=false) {
  // iterate over samples; update running totals of magnitude by probe
  // then divide to find mean for each probe
  if (verbose) cerr << "Finding mean magnitude by probe" << endl;
  float *magnitudes;
  magnitudes = (float *) calloc(qcsim->numProbes, sizeof(float));
  char *sampleName; // placeholder; name used in magnitudeBySample
  sampleName = new char[qcsim->sampleNameSize];
  for(unsigned int i=0; i < qcsim->numSamples; i++) {
    getNextMagnitudes(magnitudes, sampleName, qcsim);
    for (unsigned int j=0; j < qcsim->numProbes; j++) {
      magByProbe[j] += magnitudes[j];
    }
    if (verbose && i % QC::VERBOSE_FREQ == 0) {
      char *t;
      t = new char[QC::TIME_BUFFER];
      timeText(t);
      cerr << t << " Sample " << i+1 << " of " << qcsim->numSamples << endl;
      delete t;
    }
  }
  for (unsigned int i=0; i < qcsim->numProbes; i++) {
    magByProbe[i] = magByProbe[i] / qcsim->numSamples;
  }
  free(magnitudes);
  if (verbose) cerr << "Completed mean magnitude by probe" << endl;
}

void QC::magnitudeBySample(float magBySample[], float magByProbe[],
			   char sampleNames[][Sim::SAMPLE_NAME_SIZE+1],
			   bool verbose=false) {
  // find mean sample magnitude, normalized for each probe
  // also read sample names
  if (verbose) cerr << "Finding normalized mean magnitude by sample" << endl;
  float *magnitudes;
  magnitudes = (float *) calloc(qcsim->numProbes, sizeof(float));
  for(unsigned int i=0; i < qcsim->numSamples; i++) {
    char *sampleName;
    sampleName = new char[qcsim->sampleNameSize];
    getNextMagnitudes(magnitudes, sampleName, qcsim);
    strcpy(sampleNames[i], sampleName);
    float mag = 0;
    for (unsigned int j=0; j < qcsim->numProbes; j++) {
      mag += magnitudes[j]/magByProbe[j];
    }
    magBySample[i] = mag / qcsim -> numProbes;
    if (verbose && i % QC::VERBOSE_FREQ == 0) {
      char *t;
      t = new char[QC::TIME_BUFFER];
      timeText(t);
      cerr << t << " Sample " << i+1 << " of " << qcsim->numSamples << endl;
      delete t;
    }
  }
  free(magnitudes);
  if (verbose) cerr << "Completed mean magnitude by sample" << endl;
}

void QC::xydiffBySample(float xydBySample[],
			char sampleNames[][Sim::SAMPLE_NAME_SIZE+1]) {
  // find xydiff and read sample names
  for(unsigned int i=0; i < qcsim->numSamples; i++) {
    char *sampleName;
    sampleName = new char[qcsim->sampleNameSize];
    float xydTotal = 0.0; // running total of xy difference
    vector<uint16_t> *intensity_int = new vector<uint16_t>;
    vector<float> *intensity_float = new vector<float>;
    if (qcsim->numberFormat == 0) {
      qcsim->getNextRecord(sampleName, intensity_float);
    } else {
      qcsim->getNextRecord(sampleName, intensity_int);
    }
    strcpy(sampleNames[i], sampleName);
    // define pointer to first intensity element (depending on format)
    // pointer is used for fast access to vector contents
    float *intensityf;
    uint16_t *intensityi;
    if (qcsim->numberFormat == 0) intensityf = &(intensity_float->front());
    else intensityi = &(intensity_int->front());
    for (unsigned int j=0; j<qcsim->numProbes; j++) {
      int index = j*qcsim->numChannels;
      float x, y;
      if (qcsim->numberFormat == 0) {
	x = *(intensityf+index);
	y = *(intensityf+index+1);
      }
      else {
	x = *(intensityi+index);
	y = *(intensityi+index+1);
      }
      xydTotal += (y-x);
    }
    xydBySample[i] = xydTotal / qcsim->numProbes;
    delete intensity_int;
    delete intensity_float;
  }
}

void QC::timeText(char *buffer) {
  // get current time in format 06-09-2013_09:01:58
  time_t rawtime;
  time(&rawtime);
  strftime(buffer, QC::TIME_BUFFER, "%d-%m-%Y_%H:%M:%S", localtime(&rawtime));
}

<|endoftext|>


<commit_before>//===-- Writer.cpp - Library for Printing VM assembly files ------*- C++ -*--=//
//
// This library implements the functionality defined in llvm/Assembly/Writer.h
//
// This library uses the Analysis library to figure out offsets for
// variables in the method tables...
//
// TODO: print out the type name instead of the full type if a particular type
//       is in the symbol table...
//
//===----------------------------------------------------------------------===//

#include "llvm/Assembly/Writer.h"
#include "llvm/Analysis/SlotCalculator.h"
#include "llvm/Module.h"
#include "llvm/Method.h"
#include "llvm/GlobalVariable.h"
#include "llvm/BasicBlock.h"
#include "llvm/ConstPoolVals.h"
#include "llvm/iOther.h"
#include "llvm/iMemory.h"
#include "llvm/Support/STLExtras.h"
#include "llvm/SymbolTable.h"
#include <algorithm>

void DebugValue(const Value *V) {
  cerr << V << endl;
}

// WriteAsOperand - Write the name of the specified value out to the specified
// ostream.  This can be useful when you just want to print int %reg126, not the
// whole instruction that generated it.
//
ostream &WriteAsOperand(ostream &Out, const Value *V, bool PrintType,
			bool PrintName, SlotCalculator *Table) {
  if (PrintType)
    Out << " " << V->getType();

  if (PrintName && V->hasName()) {
    Out << " %" << V->getName();
  } else {
    if (const ConstPoolVal *CPV = V->castConstant()) {
      Out << " " << CPV->getStrValue();
    } else {
      int Slot;
      if (Table) {
	Slot = Table->getValSlot(V);
      } else {
	if (const Type *Ty = V->castType()) {
	  return Out << " " << Ty;
	} else if (const MethodArgument *MA = V->castMethodArgument()) {
	  Table = new SlotCalculator(MA->getParent(), true);
	} else if (const Instruction *I = V->castInstruction()) {
	  Table = new SlotCalculator(I->getParent()->getParent(), true);
	} else if (const BasicBlock *BB = V->castBasicBlock()) {
	  Table = new SlotCalculator(BB->getParent(), true);
	} else if (const Method *Meth = V->castMethod()) {
	  Table = new SlotCalculator(Meth, true);
	} else if (const Module *Mod  = V->castModule()) {
	  Table = new SlotCalculator(Mod, true);
	} else {
	  return Out << "BAD VALUE TYPE!";
	}
	Slot = Table->getValSlot(V);
	delete Table;
      }
      if (Slot >= 0)  Out << " %" << Slot;
      else if (PrintName)
        Out << "<badref>";     // Not embeded into a location?
    }
  }
  return Out;
}

class AssemblyWriter {
  ostream &Out;
  SlotCalculator &Table;
public:
  inline AssemblyWriter(ostream &o, SlotCalculator &Tab) : Out(o), Table(Tab) {
  }

  inline void write(const Module *M)         { processModule(M);      }
  inline void write(const GlobalVariable *G) { processGlobal(G);      }
  inline void write(const Method *M)         { processMethod(M);      }
  inline void write(const BasicBlock *BB)    { processBasicBlock(BB); }
  inline void write(const Instruction *I)    { processInstruction(I); }
  inline void write(const ConstPoolVal *CPV) { processConstant(CPV);  }

private :
  void processModule(const Module *M);
  void processSymbolTable(const SymbolTable &ST);
  void processConstant(const ConstPoolVal *CPV);
  void processGlobal(const GlobalVariable *GV);
  void processMethod(const Method *M);
  void processMethodArgument(const MethodArgument *MA);
  void processBasicBlock(const BasicBlock *BB);
  void processInstruction(const Instruction *I);

  void writeOperand(const Value *Op, bool PrintType, bool PrintName = true);
};

void AssemblyWriter::writeOperand(const Value *Operand, bool PrintType,
				  bool PrintName) {
  WriteAsOperand(Out, Operand, PrintType, PrintName, &Table);
}

void AssemblyWriter::processModule(const Module *M) {
  // Loop over the symbol table, emitting all named constants...
  if (M->hasSymbolTable())
    processSymbolTable(*M->getSymbolTable());

  for_each(M->gbegin(), M->gend(),
	   bind_obj(this, &AssemblyWriter::processGlobal));

  Out << "implementation\n";

  // Output all of the methods...
  for_each(M->begin(), M->end(), bind_obj(this,&AssemblyWriter::processMethod));
}

void AssemblyWriter::processGlobal(const GlobalVariable *GV) {
  if (GV->hasName()) Out << "%" << GV->getName() << " = ";

  if (!GV->hasInitializer()) Out << "uninitialized ";

  Out << (GV->isConstant() ? "constant " : "global ")
      << GV->getType()->getValueType()->getDescription();

  if (GV->hasInitializer())
    writeOperand(GV->getInitializer(), false, false);

  Out << endl;
}

// processSymbolTable - Run through symbol table looking for named constants
// if a named constant is found, emit it's declaration...
//
void AssemblyWriter::processSymbolTable(const SymbolTable &ST) {
  for (SymbolTable::const_iterator TI = ST.begin(); TI != ST.end(); ++TI) {
    SymbolTable::type_const_iterator I = ST.type_begin(TI->first);
    SymbolTable::type_const_iterator End = ST.type_end(TI->first);

    for (; I != End; ++I) {
      const Value *V = I->second;
      if (const ConstPoolVal *CPV = V->castConstant()) {
	processConstant(CPV);
      } else if (const Type *Ty = V->castType()) {
	Out << "\t%" << I->first << " = type " << Ty->getDescription() << endl;
      }
    }
  }
}

// processConstant - Print out a constant pool entry...
//
void AssemblyWriter::processConstant(const ConstPoolVal *CPV) {
  // Don't print out unnamed constants, they will be inlined
  if (!CPV->hasName()) return;

  // Print out name...
  Out << "\t%" << CPV->getName() << " = ";

  // Print out the constant type...
  Out << CPV->getType();

  // Write the value out now...
  writeOperand(CPV, false, false);

  if (!CPV->hasName() && CPV->getType() != Type::VoidTy) {
    int Slot = Table.getValSlot(CPV); // Print out the def slot taken...
    Out << "\t\t; <" << CPV->getType() << ">:";
    if (Slot >= 0) Out << Slot;
    else Out << "<badref>";
  }

  Out << endl;
}

// processMethod - Process all aspects of a method.
//
void AssemblyWriter::processMethod(const Method *M) {
  // Print out the return type and name...
  Out << "\n" << (M->isExternal() ? "declare " : "")
      << M->getReturnType() << " \"" << M->getName() << "\"(";
  Table.incorporateMethod(M);

  // Loop over the arguments, processing them...
  for_each(M->getArgumentList().begin(), M->getArgumentList().end(),
	   bind_obj(this, &AssemblyWriter::processMethodArgument));

  // Finish printing arguments...
  const MethodType *MT = (const MethodType*)M->getType();
  if (MT->isVarArg()) {
    if (MT->getParamTypes().size()) Out << ", ";
    Out << "...";  // Output varargs portion of signature!
  }
  Out << ")\n";

  if (!M->isExternal()) {
    // Loop over the symbol table, emitting all named constants...
    if (M->hasSymbolTable())
      processSymbolTable(*M->getSymbolTable());

    Out << "begin";

    // Output all of its basic blocks... for the method
    for_each(M->begin(), M->end(),
	     bind_obj(this, &AssemblyWriter::processBasicBlock));

    Out << "end\n";
  }

  Table.purgeMethod();
}

// processMethodArgument - This member is called for every argument that
// is passed into the method.  Simply print it out
//
void AssemblyWriter::processMethodArgument(const MethodArgument *Arg) {
  // Insert commas as we go... the first arg doesn't get a comma
  if (Arg != Arg->getParent()->getArgumentList().front()) Out << ", ";

  // Output type...
  Out << Arg->getType();

  // Output name, if available...
  if (Arg->hasName())
    Out << " %" << Arg->getName();
  else if (Table.getValSlot(Arg) < 0)
    Out << "<badref>";
}

// processBasicBlock - This member is called for each basic block in a methd.
//
void AssemblyWriter::processBasicBlock(const BasicBlock *BB) {
  if (BB->hasName()) {              // Print out the label if it exists...
    Out << "\n" << BB->getName() << ":";
  } else {
    int Slot = Table.getValSlot(BB);
    Out << "\n; <label>:";
    if (Slot >= 0)
      Out << Slot;         // Extra newline seperates out label's
    else
      Out << "<badref>";
  }
  Out << "\t\t\t\t\t;[#uses=" << BB->use_size() << "]\n";  // Output # uses

  // Output all of the instructions in the basic block...
  for_each(BB->begin(), BB->end(),
	   bind_obj(this, &AssemblyWriter::processInstruction));
}

// processInstruction - This member is called for each Instruction in a methd.
//
void AssemblyWriter::processInstruction(const Instruction *I) {
  Out << "\t";

  // Print out name if it exists...
  if (I && I->hasName())
    Out << "%" << I->getName() << " = ";

  // Print out the opcode...
  Out << I->getOpcodeName();

  // Print out the type of the operands...
  const Value *Operand = I->getNumOperands() ? I->getOperand(0) : 0;

  // Special case conditional branches to swizzle the condition out to the front
  if (I->getOpcode() == Instruction::Br && I->getNumOperands() > 1) {
    writeOperand(I->getOperand(2), true);
    Out << ",";
    writeOperand(Operand, true);
    Out << ",";
    writeOperand(I->getOperand(1), true);

  } else if (I->getOpcode() == Instruction::Switch) {
    // Special case switch statement to get formatting nice and correct...
    writeOperand(Operand         , true); Out << ",";
    writeOperand(I->getOperand(1), true); Out << " [";

    for (unsigned op = 2, Eop = I->getNumOperands(); op < Eop; op += 2) {
      Out << "\n\t\t";
      writeOperand(I->getOperand(op  ), true); Out << ",";
      writeOperand(I->getOperand(op+1), true);
    }
    Out << "\n\t]";
  } else if (I->isPHINode()) {
    Out << " " << Operand->getType();

    Out << " [";  writeOperand(Operand, false); Out << ",";
    writeOperand(I->getOperand(1), false); Out << " ]";
    for (unsigned op = 2, Eop = I->getNumOperands(); op < Eop; op += 2) {
      Out << ", [";
      writeOperand(I->getOperand(op  ), false); Out << ",";
      writeOperand(I->getOperand(op+1), false); Out << " ]";
    }
  } else if (I->getOpcode() == Instruction::Ret && !Operand) {
    Out << " void";
  } else if (I->getOpcode() == Instruction::Call) {
    writeOperand(Operand, true);
    Out << "(";
    if (I->getNumOperands() > 1) writeOperand(I->getOperand(1), true);
    for (unsigned op = 2, Eop = I->getNumOperands(); op < Eop; ++op) {
      Out << ",";
      writeOperand(I->getOperand(op), true);
    }

    Out << " )";
  } else if (I->getOpcode() == Instruction::Malloc ||
	     I->getOpcode() == Instruction::Alloca) {
    Out << " " << ((const PointerType*)I->getType())->getValueType();
    if (I->getNumOperands()) {
      Out << ",";
      writeOperand(I->getOperand(0), true);
    }
  } else if (I->getOpcode() == Instruction::Cast) {
    writeOperand(Operand, true);
    Out << " to " << I->getType();
  } else if (Operand) {   // Print the normal way...

    // PrintAllTypes - Instructions who have operands of all the same type
    // omit the type from all but the first operand.  If the instruction has
    // different type operands (for example br), then they are all printed.
    bool PrintAllTypes = false;
    const Type *TheType = Operand->getType();

    for (unsigned i = 1, E = I->getNumOperands(); i != E; ++i) {
      Operand = I->getOperand(i);
      if (Operand->getType() != TheType) {
	PrintAllTypes = true;       // We have differing types!  Print them all!
	break;
      }
    }

    if (!PrintAllTypes)
      Out << " " << I->getOperand(0)->getType();

    for (unsigned i = 0, E = I->getNumOperands(); i != E; ++i) {
      if (i) Out << ",";
      writeOperand(I->getOperand(i), PrintAllTypes);
    }
  }

  // Print a little comment after the instruction indicating which slot it
  // occupies.
  //
  if (I->getType() != Type::VoidTy) {
    Out << "\t\t; <" << I->getType() << ">";

    if (!I->hasName()) {
      int Slot = Table.getValSlot(I); // Print out the def slot taken...
      if (Slot >= 0) Out << ":" << Slot;
      else Out << ":<badref>";
    }
    Out << "\t[#uses=" << I->use_size() << "]";  // Output # uses
  }
  Out << endl;
}

//===----------------------------------------------------------------------===//
//                       External Interface declarations
//===----------------------------------------------------------------------===//

void WriteToAssembly(const Module *M, ostream &o) {
  if (M == 0) { o << "<null> module\n"; return; }
  SlotCalculator SlotTable(M, true);
  AssemblyWriter W(o, SlotTable);

  W.write(M);
}

void WriteToAssembly(const GlobalVariable *G, ostream &o) {
  if (G == 0) { o << "<null> global variable\n"; return; }
  SlotCalculator SlotTable(G->getParent(), true);
  AssemblyWriter W(o, SlotTable);
  W.write(G);
}

void WriteToAssembly(const Method *M, ostream &o) {
  if (M == 0) { o << "<null> method\n"; return; }
  SlotCalculator SlotTable(M->getParent(), true);
  AssemblyWriter W(o, SlotTable);

  W.write(M);
}

void WriteToAssembly(const BasicBlock *BB, ostream &o) {
  if (BB == 0) { o << "<null> basic block\n"; return; }

  SlotCalculator SlotTable(BB->getParent(), true);
  AssemblyWriter W(o, SlotTable);

  W.write(BB);
}

void WriteToAssembly(const ConstPoolVal *CPV, ostream &o) {
  if (CPV == 0) { o << "<null> constant pool value\n"; return; }
  WriteAsOperand(o, CPV, true, true, 0);
}

void WriteToAssembly(const Instruction *I, ostream &o) {
  if (I == 0) { o << "<null> instruction\n"; return; }

  SlotCalculator SlotTable(I->getParent() ? I->getParent()->getParent() : 0,
			   true);
  AssemblyWriter W(o, SlotTable);

  W.write(I);
}
<commit_msg>Moved DebugValue to Value.cpp.<commit_after>//===-- Writer.cpp - Library for Printing VM assembly files ------*- C++ -*--=//
//
// This library implements the functionality defined in llvm/Assembly/Writer.h
//
// This library uses the Analysis library to figure out offsets for
// variables in the method tables...
//
// TODO: print out the type name instead of the full type if a particular type
//       is in the symbol table...
//
//===----------------------------------------------------------------------===//

#include "llvm/Assembly/Writer.h"
#include "llvm/Analysis/SlotCalculator.h"
#include "llvm/Module.h"
#include "llvm/Method.h"
#include "llvm/GlobalVariable.h"
#include "llvm/BasicBlock.h"
#include "llvm/ConstPoolVals.h"
#include "llvm/iOther.h"
#include "llvm/iMemory.h"
#include "llvm/Support/STLExtras.h"
#include "llvm/SymbolTable.h"
#include <algorithm>

// WriteAsOperand - Write the name of the specified value out to the specified
// ostream.  This can be useful when you just want to print int %reg126, not the
// whole instruction that generated it.
//
ostream &WriteAsOperand(ostream &Out, const Value *V, bool PrintType,
			bool PrintName, SlotCalculator *Table) {
  if (PrintType)
    Out << " " << V->getType();

  if (PrintName && V->hasName()) {
    Out << " %" << V->getName();
  } else {
    if (const ConstPoolVal *CPV = V->castConstant()) {
      Out << " " << CPV->getStrValue();
    } else {
      int Slot;
      if (Table) {
	Slot = Table->getValSlot(V);
      } else {
	if (const Type *Ty = V->castType()) {
	  return Out << " " << Ty;
	} else if (const MethodArgument *MA = V->castMethodArgument()) {
	  Table = new SlotCalculator(MA->getParent(), true);
	} else if (const Instruction *I = V->castInstruction()) {
	  Table = new SlotCalculator(I->getParent()->getParent(), true);
	} else if (const BasicBlock *BB = V->castBasicBlock()) {
	  Table = new SlotCalculator(BB->getParent(), true);
	} else if (const Method *Meth = V->castMethod()) {
	  Table = new SlotCalculator(Meth, true);
	} else if (const Module *Mod  = V->castModule()) {
	  Table = new SlotCalculator(Mod, true);
	} else {
	  return Out << "BAD VALUE TYPE!";
	}
	Slot = Table->getValSlot(V);
	delete Table;
      }
      if (Slot >= 0)  Out << " %" << Slot;
      else if (PrintName)
        Out << "<badref>";     // Not embeded into a location?
    }
  }
  return Out;
}

class AssemblyWriter {
  ostream &Out;
  SlotCalculator &Table;
public:
  inline AssemblyWriter(ostream &o, SlotCalculator &Tab) : Out(o), Table(Tab) {
  }

  inline void write(const Module *M)         { processModule(M);      }
  inline void write(const GlobalVariable *G) { processGlobal(G);      }
  inline void write(const Method *M)         { processMethod(M);      }
  inline void write(const BasicBlock *BB)    { processBasicBlock(BB); }
  inline void write(const Instruction *I)    { processInstruction(I); }
  inline void write(const ConstPoolVal *CPV) { processConstant(CPV);  }

private :
  void processModule(const Module *M);
  void processSymbolTable(const SymbolTable &ST);
  void processConstant(const ConstPoolVal *CPV);
  void processGlobal(const GlobalVariable *GV);
  void processMethod(const Method *M);
  void processMethodArgument(const MethodArgument *MA);
  void processBasicBlock(const BasicBlock *BB);
  void processInstruction(const Instruction *I);

  void writeOperand(const Value *Op, bool PrintType, bool PrintName = true);
};

void AssemblyWriter::writeOperand(const Value *Operand, bool PrintType,
				  bool PrintName) {
  WriteAsOperand(Out, Operand, PrintType, PrintName, &Table);
}

void AssemblyWriter::processModule(const Module *M) {
  // Loop over the symbol table, emitting all named constants...
  if (M->hasSymbolTable())
    processSymbolTable(*M->getSymbolTable());

  for_each(M->gbegin(), M->gend(),
	   bind_obj(this, &AssemblyWriter::processGlobal));

  Out << "implementation\n";

  // Output all of the methods...
  for_each(M->begin(), M->end(), bind_obj(this,&AssemblyWriter::processMethod));
}

void AssemblyWriter::processGlobal(const GlobalVariable *GV) {
  if (GV->hasName()) Out << "%" << GV->getName() << " = ";

  if (!GV->hasInitializer()) Out << "uninitialized ";

  Out << (GV->isConstant() ? "constant " : "global ")
      << GV->getType()->getValueType()->getDescription();

  if (GV->hasInitializer())
    writeOperand(GV->getInitializer(), false, false);

  Out << endl;
}

// processSymbolTable - Run through symbol table looking for named constants
// if a named constant is found, emit it's declaration...
//
void AssemblyWriter::processSymbolTable(const SymbolTable &ST) {
  for (SymbolTable::const_iterator TI = ST.begin(); TI != ST.end(); ++TI) {
    SymbolTable::type_const_iterator I = ST.type_begin(TI->first);
    SymbolTable::type_const_iterator End = ST.type_end(TI->first);

    for (; I != End; ++I) {
      const Value *V = I->second;
      if (const ConstPoolVal *CPV = V->castConstant()) {
	processConstant(CPV);
      } else if (const Type *Ty = V->castType()) {
	Out << "\t%" << I->first << " = type " << Ty->getDescription() << endl;
      }
    }
  }
}

// processConstant - Print out a constant pool entry...
//
void AssemblyWriter::processConstant(const ConstPoolVal *CPV) {
  // Don't print out unnamed constants, they will be inlined
  if (!CPV->hasName()) return;

  // Print out name...
  Out << "\t%" << CPV->getName() << " = ";

  // Print out the constant type...
  Out << CPV->getType();

  // Write the value out now...
  writeOperand(CPV, false, false);

  if (!CPV->hasName() && CPV->getType() != Type::VoidTy) {
    int Slot = Table.getValSlot(CPV); // Print out the def slot taken...
    Out << "\t\t; <" << CPV->getType() << ">:";
    if (Slot >= 0) Out << Slot;
    else Out << "<badref>";
  }

  Out << endl;
}

// processMethod - Process all aspects of a method.
//
void AssemblyWriter::processMethod(const Method *M) {
  // Print out the return type and name...
  Out << "\n" << (M->isExternal() ? "declare " : "")
      << M->getReturnType() << " \"" << M->getName() << "\"(";
  Table.incorporateMethod(M);

  // Loop over the arguments, processing them...
  for_each(M->getArgumentList().begin(), M->getArgumentList().end(),
	   bind_obj(this, &AssemblyWriter::processMethodArgument));

  // Finish printing arguments...
  const MethodType *MT = (const MethodType*)M->getType();
  if (MT->isVarArg()) {
    if (MT->getParamTypes().size()) Out << ", ";
    Out << "...";  // Output varargs portion of signature!
  }
  Out << ")\n";

  if (!M->isExternal()) {
    // Loop over the symbol table, emitting all named constants...
    if (M->hasSymbolTable())
      processSymbolTable(*M->getSymbolTable());

    Out << "begin";

    // Output all of its basic blocks... for the method
    for_each(M->begin(), M->end(),
	     bind_obj(this, &AssemblyWriter::processBasicBlock));

    Out << "end\n";
  }

  Table.purgeMethod();
}

// processMethodArgument - This member is called for every argument that
// is passed into the method.  Simply print it out
//
void AssemblyWriter::processMethodArgument(const MethodArgument *Arg) {
  // Insert commas as we go... the first arg doesn't get a comma
  if (Arg != Arg->getParent()->getArgumentList().front()) Out << ", ";

  // Output type...
  Out << Arg->getType();

  // Output name, if available...
  if (Arg->hasName())
    Out << " %" << Arg->getName();
  else if (Table.getValSlot(Arg) < 0)
    Out << "<badref>";
}

// processBasicBlock - This member is called for each basic block in a methd.
//
void AssemblyWriter::processBasicBlock(const BasicBlock *BB) {
  if (BB->hasName()) {              // Print out the label if it exists...
    Out << "\n" << BB->getName() << ":";
  } else {
    int Slot = Table.getValSlot(BB);
    Out << "\n; <label>:";
    if (Slot >= 0)
      Out << Slot;         // Extra newline seperates out label's
    else
      Out << "<badref>";
  }
  Out << "\t\t\t\t\t;[#uses=" << BB->use_size() << "]\n";  // Output # uses

  // Output all of the instructions in the basic block...
  for_each(BB->begin(), BB->end(),
	   bind_obj(this, &AssemblyWriter::processInstruction));
}

// processInstruction - This member is called for each Instruction in a methd.
//
void AssemblyWriter::processInstruction(const Instruction *I) {
  Out << "\t";

  // Print out name if it exists...
  if (I && I->hasName())
    Out << "%" << I->getName() << " = ";

  // Print out the opcode...
  Out << I->getOpcodeName();

  // Print out the type of the operands...
  const Value *Operand = I->getNumOperands() ? I->getOperand(0) : 0;

  // Special case conditional branches to swizzle the condition out to the front
  if (I->getOpcode() == Instruction::Br && I->getNumOperands() > 1) {
    writeOperand(I->getOperand(2), true);
    Out << ",";
    writeOperand(Operand, true);
    Out << ",";
    writeOperand(I->getOperand(1), true);

  } else if (I->getOpcode() == Instruction::Switch) {
    // Special case switch statement to get formatting nice and correct...
    writeOperand(Operand         , true); Out << ",";
    writeOperand(I->getOperand(1), true); Out << " [";

    for (unsigned op = 2, Eop = I->getNumOperands(); op < Eop; op += 2) {
      Out << "\n\t\t";
      writeOperand(I->getOperand(op  ), true); Out << ",";
      writeOperand(I->getOperand(op+1), true);
    }
    Out << "\n\t]";
  } else if (I->isPHINode()) {
    Out << " " << Operand->getType();

    Out << " [";  writeOperand(Operand, false); Out << ",";
    writeOperand(I->getOperand(1), false); Out << " ]";
    for (unsigned op = 2, Eop = I->getNumOperands(); op < Eop; op += 2) {
      Out << ", [";
      writeOperand(I->getOperand(op  ), false); Out << ",";
      writeOperand(I->getOperand(op+1), false); Out << " ]";
    }
  } else if (I->getOpcode() == Instruction::Ret && !Operand) {
    Out << " void";
  } else if (I->getOpcode() == Instruction::Call) {
    writeOperand(Operand, true);
    Out << "(";
    if (I->getNumOperands() > 1) writeOperand(I->getOperand(1), true);
    for (unsigned op = 2, Eop = I->getNumOperands(); op < Eop; ++op) {
      Out << ",";
      writeOperand(I->getOperand(op), true);
    }

    Out << " )";
  } else if (I->getOpcode() == Instruction::Malloc ||
	     I->getOpcode() == Instruction::Alloca) {
    Out << " " << ((const PointerType*)I->getType())->getValueType();
    if (I->getNumOperands()) {
      Out << ",";
      writeOperand(I->getOperand(0), true);
    }
  } else if (I->getOpcode() == Instruction::Cast) {
    writeOperand(Operand, true);
    Out << " to " << I->getType();
  } else if (Operand) {   // Print the normal way...

    // PrintAllTypes - Instructions who have operands of all the same type
    // omit the type from all but the first operand.  If the instruction has
    // different type operands (for example br), then they are all printed.
    bool PrintAllTypes = false;
    const Type *TheType = Operand->getType();

    for (unsigned i = 1, E = I->getNumOperands(); i != E; ++i) {
      Operand = I->getOperand(i);
      if (Operand->getType() != TheType) {
	PrintAllTypes = true;       // We have differing types!  Print them all!
	break;
      }
    }

    if (!PrintAllTypes)
      Out << " " << I->getOperand(0)->getType();

    for (unsigned i = 0, E = I->getNumOperands(); i != E; ++i) {
      if (i) Out << ",";
      writeOperand(I->getOperand(i), PrintAllTypes);
    }
  }

  // Print a little comment after the instruction indicating which slot it
  // occupies.
  //
  if (I->getType() != Type::VoidTy) {
    Out << "\t\t; <" << I->getType() << ">";

    if (!I->hasName()) {
      int Slot = Table.getValSlot(I); // Print out the def slot taken...
      if (Slot >= 0) Out << ":" << Slot;
      else Out << ":<badref>";
    }
    Out << "\t[#uses=" << I->use_size() << "]";  // Output # uses
  }
  Out << endl;
}

//===----------------------------------------------------------------------===//
//                       External Interface declarations
//===----------------------------------------------------------------------===//

void WriteToAssembly(const Module *M, ostream &o) {
  if (M == 0) { o << "<null> module\n"; return; }
  SlotCalculator SlotTable(M, true);
  AssemblyWriter W(o, SlotTable);

  W.write(M);
}

void WriteToAssembly(const GlobalVariable *G, ostream &o) {
  if (G == 0) { o << "<null> global variable\n"; return; }
  SlotCalculator SlotTable(G->getParent(), true);
  AssemblyWriter W(o, SlotTable);
  W.write(G);
}

void WriteToAssembly(const Method *M, ostream &o) {
  if (M == 0) { o << "<null> method\n"; return; }
  SlotCalculator SlotTable(M->getParent(), true);
  AssemblyWriter W(o, SlotTable);

  W.write(M);
}

void WriteToAssembly(const BasicBlock *BB, ostream &o) {
  if (BB == 0) { o << "<null> basic block\n"; return; }

  SlotCalculator SlotTable(BB->getParent(), true);
  AssemblyWriter W(o, SlotTable);

  W.write(BB);
}

void WriteToAssembly(const ConstPoolVal *CPV, ostream &o) {
  if (CPV == 0) { o << "<null> constant pool value\n"; return; }
  WriteAsOperand(o, CPV, true, true, 0);
}

void WriteToAssembly(const Instruction *I, ostream &o) {
  if (I == 0) { o << "<null> instruction\n"; return; }

  SlotCalculator SlotTable(I->getParent() ? I->getParent()->getParent() : 0,
			   true);
  AssemblyWriter W(o, SlotTable);

  W.write(I);
}
<|endoftext|>


<commit_before>#include <string>
#include <fstream>
#include <iostream>
#include "map.h"

using namespace std;

Map::Map() {}

Map::~Map() {}

void Map::LoadMap(string MapFileName){
	string Temp;
	string T;
	fstream MapFile;
	int X = 0;
	int Y = 0;
	int F = 0;

	MapFile.open (MapFileName, fstream::in);
	while ( MapFile >> Temp ){

				cout << Temp << endl << endl << endl << flush;
		for (int i = 0; i < Temp.length(); i++){
			if (Temp[i] == ','){
				T = Temp.substr(F,i-F);
				cout << "T=" << T << " ";
				mapArray[X][Y] = stoi(T);
				X++;
				if (X > MaxX){X = 0; Y++;}
				F = i + 1;
				cout << mapArray[X][Y] << flush;
			}
		}
	}
	MapFile.close();
}

int Map::Point(int X, int Y){
	return (int)mapArray[X][Y];
}

bool Map::Passable(int X, int Y){
	return (mapArray[X][Y] < PassableThreshhold);
}

string Map::GetPlot(int X, int Y){
	//Returns a 20x20 chunk of the map
	string RetVal;
	string Temp;
	for (int i = X; i < X + 20; i++){
		for (int j = Y; j < Y + 20; j++){
			if (i <= MaxX && i > -1 && j <= MaxY && j > -1){
				Temp = to_string(mapArray[i][j]);
				if (Temp.length() == 1) { RetVal += "0";}
				RetVal += Temp;
			} else {
			RetVal += "-1";
			}
		}
	}
	return RetVal;
}<commit_msg>Work in progress<commit_after>#include <string>
#include <fstream>
#include <iostream>
#include "map.h"

using namespace std;

Map::Map() {}

Map::~Map() {}

void Map::LoadMap(string MapFileName){
	string Temp;
	string T;
	fstream MapFile;
	int X = 0;
	int Y = 0;
	int F = 0;

	MapFile.open (MapFileName, fstream::in);
	while ( MapFile >> Temp ){

				cout << Temp << endl << endl << endl << flush;
		for (int i = 0; i < Temp.length(); i++){
			if (Temp[i] == ','){
				T = Temp.substr(F,i-F);
				cout << "T=" << T << " ";
				mapArray[X][Y] = stoi(T);
				cout << mapArray[X][Y] << flush;
				X++;
				if (X > MaxX){X = 0; Y++;}
				F = i + 1;
			}
		}
	}
	MapFile.close();
}

int Map::Point(int X, int Y){
	return (int)mapArray[X][Y];
}

bool Map::Passable(int X, int Y){
	return (mapArray[X][Y] < PassableThreshhold);
}

string Map::GetPlot(int X, int Y){
	//Returns a 20x20 chunk of the map
	string RetVal;
	string Temp;
	for (int i = X; i < X + 20; i++){
		for (int j = Y; j < Y + 20; j++){
			if (i <= MaxX && i > -1 && j <= MaxY && j > -1){
				Temp = to_string(mapArray[i][j]);
				if (Temp.length() == 1) { RetVal += "0";}
				RetVal += Temp;
			} else {
			RetVal += "-1";
			}
		}
	}
	return RetVal;
}<|endoftext|>


<commit_before>/*
 * Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// Create a dot graph render of a Node Topology generated from a Redfish backend

#include <algorithm>
#include <deque>
#include <iostream>
#include <memory>
#include <string>

#include "absl/container/flat_hash_map.h"
#include "absl/flags/flag.h"
#include "absl/flags/parse.h"
#include "absl/log/initialize.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include "ecclesia/lib/http/cred.pb.h"
#include "ecclesia/lib/http/curl_client.h"
#include "ecclesia/lib/redfish/interface.h"
#include "ecclesia/lib/redfish/node_topology.h"
#include "ecclesia/lib/redfish/topology.h"
#include "ecclesia/lib/redfish/transport/cache.h"
#include "ecclesia/lib/redfish/transport/http.h"
#include "ecclesia/lib/redfish/transport/http_redfish_intf.h"

ABSL_FLAG(std::string, hostname_port, "",
          "TCP endpoint to connect with both hostname and port separated by a "
          "colon i.e. \"localhost:8000\"");
ABSL_FLAG(std::string, unix_domain_socket, "", "UDS endpoint to connect to");

namespace ecclesia {
namespace {

int RealMain(int argc, char* argv[]) {
  absl::InitializeLog();

  std::string hostname_port = absl::GetFlag(FLAGS_hostname_port),
              unix_domain_socket = absl::GetFlag(FLAGS_unix_domain_socket);

  // Either TCP or UDS must provided
  if (hostname_port.empty() == unix_domain_socket.empty()) {
    std::cout << "USAGE: " << argv[0]
              << " (--hostname_port=\"{hostname:port}\") XOR "
                 "(--unix_domain_socket=\"{unix_domain.socket}\")"
              << "\n";
    return -1;
  }

  std::unique_ptr<CurlHttpClient> curl_http_client =
      std::make_unique<CurlHttpClient>(LibCurlProxy::CreateInstance(),
                                       HttpCredential());
  std::unique_ptr<HttpRedfishTransport> transport =
      hostname_port.empty()
          ? HttpRedfishTransport::MakeUds(std::move(curl_http_client),
                                          unix_domain_socket)
          : HttpRedfishTransport::MakeNetwork(std::move(curl_http_client),
                                              hostname_port);
  std::unique_ptr<RedfishCachedGetterInterface> cache =
      std::make_unique<NullCache>(transport.get());
  std::unique_ptr<RedfishInterface> intf = NewHttpInterface(
      std::move(transport), std::move(cache), RedfishInterface::kTrusted);

  if (!intf || !intf->GetRoot().status().ok()) {
    std::cerr << "Failed to connect to backend" << std::endl;
    return -1;
  }

  NodeTopology topology = CreateTopologyFromRedfish(intf.get());

  std::vector<std::string> lines;
  lines.push_back("// Start of the digraph");
  lines.push_back("digraph {");
  lines.push_back("  graph [splines=ortho, nodesep=0.25]");
  lines.push_back("  rankdir = LR;");
  lines.push_back("  node [shape=box];");
  lines.push_back("  edge [arrowsize=0.75];");

  absl::flat_hash_map<std::string, uint32_t> devpath_to_counter;
  absl::flat_hash_map<Node*, std::string> node_to_secondary_devpath;
  for (auto& node : topology.nodes) {
    std::string devpath = node->local_devpath;
    auto [it, inserted] = devpath_to_counter.try_emplace(devpath, 0);
    if (!inserted) {
      // Need to create the node as a secondary node
      lines.push_back("  // Duplicate devpath found");
      uint32_t current_counter = ++it->second;
      absl::StrAppend(&devpath, "_dupe_", current_counter);
      node_to_secondary_devpath[node.get()] = devpath;
    }

    lines.push_back(absl::StrFormat(
        "  \"%s\" [tooltip=\"%s\", label=<%s
%s>]", devpath,
        absl::StrJoin(node->associated_uris, "\\n"), devpath, node->name));
  }

  auto it = topology.devpath_to_node_map.find("/phys");
  if (it == topology.devpath_to_node_map.end()) {
    lines.push_back("// No root node found");
  } else {
    std::deque<Node*> queue;
    queue.push_back(it->second);

    while (!queue.empty()) {
      auto* current_node = queue.front();
      queue.pop_front();

      auto children = topology.node_to_children.find(current_node);
      if (children != topology.node_to_children.end()) {
        // Check if the current node has a duplicated devpath
        auto current_node_local_devpath = current_node->local_devpath;
        if (auto current_node_it = node_to_secondary_devpath.find(current_node);
            current_node_it != node_to_secondary_devpath.end()) {
          current_node_local_devpath = current_node_it->second;
        }

        for (auto* child : children->second) {
          // Check if the child node has a duplicated devpath
          auto child_local_devpath = child->local_devpath;
          if (auto child_it = node_to_secondary_devpath.find(child);
              child_it != node_to_secondary_devpath.end()) {
            child_local_devpath = child_it->second;
          }

          lines.push_back(absl::StrFormat("  \"%s\" -> \"%s\"",
                                          current_node_local_devpath,
                                          child_local_devpath));

          queue.push_back(child);
        }
      }
    }
  }

  lines.push_back("}");

  std::cout << absl::StrJoin(lines, "\n") << "\n";

  return 0;
}

}  // namespace
}  // namespace ecclesia

int main(int argc, char* argv[]) { return ecclesia::RealMain(argc, argv); }
<commit_msg>Internal change<commit_after>/*
 * Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// Create a dot graph render of a Node Topology generated from a Redfish backend

#include <algorithm>
#include <deque>
#include <iostream>
#include <memory>
#include <string>

#include "absl/container/flat_hash_map.h"
#include "absl/flags/flag.h"
#include "absl/flags/parse.h"
#include "absl/log/initialize.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include "ecclesia/lib/http/cred.pb.h"
#include "ecclesia/lib/http/curl_client.h"
#include "ecclesia/lib/redfish/interface.h"
#include "ecclesia/lib/redfish/node_topology.h"
#include "ecclesia/lib/redfish/topology.h"
#include "ecclesia/lib/redfish/transport/cache.h"
#include "ecclesia/lib/redfish/transport/http.h"
#include "ecclesia/lib/redfish/transport/http_redfish_intf.h"

ABSL_FLAG(std::string, hostname_port, "",
          "TCP endpoint to connect with both hostname and port separated by a "
          "colon i.e. \"localhost:8000\"");
ABSL_FLAG(std::string, unix_domain_socket, "", "UDS endpoint to connect to");

namespace ecclesia {
namespace {

int RealMain(int argc, char* argv[]) {
  absl::InitializeLog();
  absl::ParseCommandLine(argc, argv);

  std::string hostname_port = absl::GetFlag(FLAGS_hostname_port),
              unix_domain_socket = absl::GetFlag(FLAGS_unix_domain_socket);

  // Either TCP or UDS must provided
  if (hostname_port.empty() == unix_domain_socket.empty()) {
    std::cout << "USAGE: " << argv[0]
              << " (--hostname_port=\"{hostname:port}\") XOR "
                 "(--unix_domain_socket=\"{unix_domain.socket}\")"
              << "\n";
    return -1;
  }

  std::unique_ptr<CurlHttpClient> curl_http_client =
      std::make_unique<CurlHttpClient>(LibCurlProxy::CreateInstance(),
                                       HttpCredential());
  std::unique_ptr<HttpRedfishTransport> transport =
      hostname_port.empty()
          ? HttpRedfishTransport::MakeUds(std::move(curl_http_client),
                                          unix_domain_socket)
          : HttpRedfishTransport::MakeNetwork(std::move(curl_http_client),
                                              hostname_port);
  std::unique_ptr<RedfishCachedGetterInterface> cache =
      std::make_unique<NullCache>(transport.get());
  std::unique_ptr<RedfishInterface> intf = NewHttpInterface(
      std::move(transport), std::move(cache), RedfishInterface::kTrusted);

  if (!intf || !intf->GetRoot().status().ok()) {
    std::cerr << "Failed to connect to backend" << std::endl;
    return -1;
  }

  NodeTopology topology = CreateTopologyFromRedfish(intf.get());

  std::vector<std::string> lines;
  lines.push_back("// Start of the digraph");
  lines.push_back("digraph {");
  lines.push_back("  graph [splines=ortho, nodesep=0.25]");
  lines.push_back("  rankdir = LR;");
  lines.push_back("  node [shape=box];");
  lines.push_back("  edge [arrowsize=0.75];");

  absl::flat_hash_map<std::string, uint32_t> devpath_to_counter;
  absl::flat_hash_map<Node*, std::string> node_to_secondary_devpath;
  for (auto& node : topology.nodes) {
    std::string devpath = node->local_devpath;
    auto [it, inserted] = devpath_to_counter.try_emplace(devpath, 0);
    if (!inserted) {
      // Need to create the node as a secondary node
      lines.push_back("  // Duplicate devpath found");
      uint32_t current_counter = ++it->second;
      absl::StrAppend(&devpath, "_dupe_", current_counter);
      node_to_secondary_devpath[node.get()] = devpath;
    }

    lines.push_back(absl::StrFormat(
        "  \"%s\" [tooltip=\"%s\", label=<%s
%s>]", devpath,
        absl::StrJoin(node->associated_uris, "\\n"), devpath, node->name));
  }

  auto it = topology.devpath_to_node_map.find("/phys");
  if (it == topology.devpath_to_node_map.end()) {
    lines.push_back("// No root node found");
  } else {
    std::deque<Node*> queue;
    queue.push_back(it->second);

    while (!queue.empty()) {
      auto* current_node = queue.front();
      queue.pop_front();

      auto children = topology.node_to_children.find(current_node);
      if (children != topology.node_to_children.end()) {
        // Check if the current node has a duplicated devpath
        auto current_node_local_devpath = current_node->local_devpath;
        if (auto current_node_it = node_to_secondary_devpath.find(current_node);
            current_node_it != node_to_secondary_devpath.end()) {
          current_node_local_devpath = current_node_it->second;
        }

        for (auto* child : children->second) {
          // Check if the child node has a duplicated devpath
          auto child_local_devpath = child->local_devpath;
          if (auto child_it = node_to_secondary_devpath.find(child);
              child_it != node_to_secondary_devpath.end()) {
            child_local_devpath = child_it->second;
          }

          lines.push_back(absl::StrFormat("  \"%s\" -> \"%s\"",
                                          current_node_local_devpath,
                                          child_local_devpath));

          queue.push_back(child);
        }
      }
    }
  }

  lines.push_back("}");

  std::cout << absl::StrJoin(lines, "\n") << "\n";

  return 0;
}

}  // namespace
}  // namespace ecclesia

int main(int argc, char* argv[]) { return ecclesia::RealMain(argc, argv); }
<|endoftext|>