<commit_before>/*
    This file is part of Akregator.

    Copyright (C) 2005 Stanislav Karchebny <Stanislav.Karchebny@kdemail.net>
                  2005 Frank Osterfeld <frank.osterfeld@kdemail.net>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/
#include "storagemk4impl.h"
#include "feedstoragemk4impl.h"

#include <mk4.h>

#include <qmap.h>
#include <qstring.h>
#include <qstringlist.h>
#include <qtimer.h>

#include <kdebug.h>
#include <kstandarddirs.h>

namespace Akregator {
namespace Backend {

class StorageMK4Impl::StorageMK4ImplPrivate
{
    public:
        StorageMK4ImplPrivate() : modified(false),
            purl("url"),
            pFeedList("feedList"),
            pTagSet("tagSet"),
            punread("unread"),
            ptotalCount("totalCount"),
            plastFetch("lastFetch") {}

        c4_Storage* storage;
        c4_View archiveView;
        bool autoCommit;
        bool modified;
        QMap<QString, FeedStorage*> feeds;
        QStringList feedURLs;
        c4_StringProp purl, pFeedList, pTagSet;
        c4_IntProp punread, ptotalCount, plastFetch;
        QTimer* commitTimer;
        QString archivePath;

        c4_Storage* feedListStorage;
        c4_View feedListView;
};

void StorageMK4Impl::setArchivePath(const QString& archivePath)
{
    if (archivePath.isNull()) // if isNull, reset to default
        d->archivePath = defaultArchivePath();
    else
        d->archivePath = archivePath;
}

QString StorageMK4Impl::archivePath() const
{
    return d->archivePath;
}

StorageMK4Impl::StorageMK4Impl() : d(new StorageMK4ImplPrivate)
{
    setArchivePath(QString::null); // set path to default
    // commit changes every 3 seconds
    d->commitTimer = new QTimer(this);
    connect(d->commitTimer, SIGNAL(timeout()), this, SLOT(slotCommit()));
    d->commitTimer->start(3000);
}

QString StorageMK4Impl::defaultArchivePath()
{
    return KGlobal::dirs()->saveLocation("data", "akregator")+"Archive";
}

StorageMK4Impl::~StorageMK4Impl()
{
    close();
    delete d;
    d = 0;
}
void StorageMK4Impl::initialize(const QStringList&) {}

bool StorageMK4Impl::open(bool autoCommit)
{
    QString filePath = d->archivePath +"/archiveindex.mk4";
    d->storage = new c4_Storage(filePath.local8Bit(), true);
    d->archiveView = d->storage->GetAs("archive[url:S,unread:I,totalCount:I,lastFetch:I]");
    c4_View hash = d->storage->GetAs("archiveHash[_H:I,_R:I]");
    d->archiveView = d->archiveView.Hash(hash, 1); // hash on url
    d->autoCommit = autoCommit;

    filePath = d->archivePath +"/feedlistbackup.mk4";
    d->feedListStorage = new c4_Storage(filePath.local8Bit(), true);
    d->feedListView = d->feedListStorage->GetAs("archive[feedList:S,tagSet:S]");
    d->feedListView = d->feedListView.Hash(hash, 1); // hash on url
    return true;
}

bool StorageMK4Impl::autoCommit() const
{
    return d->autoCommit;
}

bool StorageMK4Impl::close()
{
    d->commitTimer->stop();

    QMap<QString, FeedStorage*>::Iterator it;
    QMap<QString, FeedStorage*>::Iterator end(d->feeds.end() ) ;
    for (it = d->feeds.begin(); it != end; ++it)
    {
        it.data()->close();
        delete it.data();
    }
    if(d->autoCommit)
        d->storage->Commit();

    delete d->storage;
    d->storage = 0;

    d->feedListStorage->Commit();
    delete d->feedListStorage;
    d->feedListStorage = 0;

    return true;
}

bool StorageMK4Impl::commit()
{
    QMap<QString, FeedStorage*>::Iterator it;
    QMap<QString, FeedStorage*>::Iterator end(d->feeds.end() ) ;
    for ( it = d->feeds.begin(); it != end; ++it )
        it.data()->commit();

    if(d->storage)
    {
        d->storage->Commit();
        return true;
    }

    return false;
}

bool StorageMK4Impl::rollback()
{
    QMap<QString, FeedStorage*>::Iterator it;
    QMap<QString, FeedStorage*>::Iterator end(d->feeds.end() ) ;
    for ( it = d->feeds.begin(); it != end; ++it )
        it.data()->rollback();

    if(d->storage)
    {
        d->storage->Rollback();
        return true;
    }
    return false;
}

int StorageMK4Impl::unreadFor(const QString &url)
{
    c4_Row findrow;
    d->purl(findrow) = url.ascii();
    int findidx = d->archiveView.Find(findrow);

    return findidx != -1 ? d->punread(d->archiveView.GetAt(findidx)) : 0;
}

void StorageMK4Impl::setUnreadFor(const QString &url, int unread)
{
    c4_Row findrow;
    d->purl(findrow) = url.ascii();
    int findidx = d->archiveView.Find(findrow);
    if (findidx == -1)
        return;
    findrow = d->archiveView.GetAt(findidx);
    d->punread(findrow) = unread;
    d->archiveView.SetAt(findidx, findrow);
    d->modified = true;
}

int StorageMK4Impl::totalCountFor(const QString &url)
{
    c4_Row findrow;
    d->purl(findrow) = url.ascii();
    int findidx = d->archiveView.Find(findrow);

    return findidx != -1 ? d->ptotalCount(d->archiveView.GetAt(findidx)) : 0;
}

void StorageMK4Impl::setTotalCountFor(const QString &url, int total)
{
    c4_Row findrow;
    d->purl(findrow) = url.ascii();
    int findidx = d->archiveView.Find(findrow);
    if (findidx == -1)
        return;
    findrow = d->archiveView.GetAt(findidx);
    d->ptotalCount(findrow) = total;
    d->archiveView.SetAt(findidx, findrow);
    d->modified = true;
}

int StorageMK4Impl::lastFetchFor(const QString& url)
{
    c4_Row findrow;
    d->purl(findrow) = url.ascii();
    int findidx = d->archiveView.Find(findrow);

    return (findidx != -1 ? d->plastFetch(d->archiveView.GetAt(findidx)) : 0);
}

void StorageMK4Impl::setLastFetchFor(const QString& url, int lastFetch)
{
    c4_Row findrow;
    d->purl(findrow) = url.ascii();
    int findidx = d->archiveView.Find(findrow);
    if (findidx == -1)
        return;
    findrow = d->archiveView.GetAt(findidx);
    d->plastFetch(findrow) = lastFetch;
    d->archiveView.SetAt(findidx, findrow);
    d->modified = true;
}

void StorageMK4Impl::slotCommit()
{
    if (d->modified)
    	commit();
    d->modified = false;
}

FeedStorage* StorageMK4Impl::archiveFor(const QString& url)
{
    if (!d->feeds.contains(url))
    {
        FeedStorage* fs = new FeedStorageMK4Impl(url, this);
        d->feeds[url] = fs;
        c4_Row findrow;
        d->purl(findrow) = url.ascii();
        int findidx = d->archiveView.Find(findrow);
        if (findidx == -1)
        {
            d->punread(findrow) = 0;
	    d->ptotalCount(findrow) = 0;
	    d->plastFetch(findrow) = 0;
            d->archiveView.Add(findrow);
            d->modified = true;
        }
        fs->convertOldArchive();
    }
    return d->feeds[url];
}

QStringList StorageMK4Impl::feeds() const
{
    // TODO: cache list
    QStringList list;
    int size = d->archiveView.GetSize();
    for (int i = 0; i < size; i++)
        list += QString(d->purl(d->archiveView.GetAt(i)));
    // fill with urls
    return list;

}

void StorageMK4Impl::add(Storage* source)
{
    QStringList feeds = source->feeds();
    QStringList::ConstIterator end(feeds.end() ) ;

    for (QStringList::ConstIterator it = feeds.begin(); it != end; ++it)
    {
        FeedStorage* fa = archiveFor(*it);
        fa->add(source->archiveFor(*it));
    }
}

void StorageMK4Impl::clear()
{
   QStringList feeds;
    int size = d->archiveView.GetSize();
    for (int i = 0; i < size; i++)
        feeds += QString(d->purl(d->archiveView.GetAt(i)));
    QStringList::ConstIterator end(feeds.end() ) ;

    for (QStringList::ConstIterator it = feeds.begin(); it != end; ++it)
    {
        FeedStorage* fa = archiveFor(*it);
        fa->clear();
        fa->commit();
        // FIXME: delete file (should be 0 in size now)
    }
    d->storage->RemoveAll();

}

void StorageMK4Impl::storeFeedList(const QString& opmlStr)
{
    c4_Row row;

    if  (d->feedListView.GetSize() == 0)
        d->feedListView.Add(row);

    row = d->feedListView.GetAt(0);
    d->pFeedList(row) = opmlStr.utf8().data();
    d->feedListView.SetAt(0, row);
    d->modified = true;
}

QString StorageMK4Impl::restoreFeedList() const
{
    if  (d->feedListView.GetSize() == 0)
        return "";

    c4_Row row = d->feedListView.GetAt(0);
    return QString::fromUtf8(d->pFeedList(row));
}

void StorageMK4Impl::storeTagSet(const QString& xmlStr)
{
    c4_Row row;

    if  (d->feedListView.GetSize() == 0)
        d->feedListView.Add(row);

    row = d->feedListView.GetAt(0);
    d->pTagSet(row) = xmlStr.utf8().data();
    d->feedListView.SetAt(0, row);
    d->modified = true;
}

QString StorageMK4Impl::restoreTagSet() const
{
    if  (d->feedListView.GetSize() == 0)
        return "";

    c4_Row row = d->feedListView.GetAt(0);
    return QString::fromUtf8(d->pTagSet(row));
}

} // namespace Backend
} // namespace Akregator

#include "storagemk4impl.moc"
<commit_msg>trying to fix the problems with storeFeedList() Gentoo users, it would be great if someone could apply this patch and check if it solves the problem. CCBUG: 114831 CCMAIL: zander@kde.org<commit_after>/*
    This file is part of Akregator.

    Copyright (C) 2005 Stanislav Karchebny <Stanislav.Karchebny@kdemail.net>
                  2005 Frank Osterfeld <frank.osterfeld@kdemail.net>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/
#include "storagemk4impl.h"
#include "feedstoragemk4impl.h"

#include <mk4.h>

#include <qmap.h>
#include <qstring.h>
#include <qstringlist.h>
#include <qtimer.h>

#include <kdebug.h>
#include <kstandarddirs.h>

namespace Akregator {
namespace Backend {

class StorageMK4Impl::StorageMK4ImplPrivate
{
    public:
        StorageMK4ImplPrivate() : modified(false),
            purl("url"),
            pFeedList("feedList"),
            pTagSet("tagSet"),
            punread("unread"),
            ptotalCount("totalCount"),
            plastFetch("lastFetch") {}

        c4_Storage* storage;
        c4_View archiveView;
        bool autoCommit;
        bool modified;
        QMap<QString, FeedStorage*> feeds;
        QStringList feedURLs;
        c4_StringProp purl, pFeedList, pTagSet;
        c4_IntProp punread, ptotalCount, plastFetch;
        QTimer* commitTimer;
        QString archivePath;

        c4_Storage* feedListStorage;
        c4_View feedListView;
};

void StorageMK4Impl::setArchivePath(const QString& archivePath)
{
    if (archivePath.isNull()) // if isNull, reset to default
        d->archivePath = defaultArchivePath();
    else
        d->archivePath = archivePath;
}

QString StorageMK4Impl::archivePath() const
{
    return d->archivePath;
}

StorageMK4Impl::StorageMK4Impl() : d(new StorageMK4ImplPrivate)
{
    setArchivePath(QString::null); // set path to default
    // commit changes every 3 seconds
    d->commitTimer = new QTimer(this);
    connect(d->commitTimer, SIGNAL(timeout()), this, SLOT(slotCommit()));
    d->commitTimer->start(3000);
}

QString StorageMK4Impl::defaultArchivePath()
{
    return KGlobal::dirs()->saveLocation("data", "akregator")+"Archive";
}

StorageMK4Impl::~StorageMK4Impl()
{
    close();
    delete d;
    d = 0;
}
void StorageMK4Impl::initialize(const QStringList&) {}

bool StorageMK4Impl::open(bool autoCommit)
{
    QString filePath = d->archivePath +"/archiveindex.mk4";
    d->storage = new c4_Storage(filePath.local8Bit(), true);
    d->archiveView = d->storage->GetAs("archive[url:S,unread:I,totalCount:I,lastFetch:I]");
    c4_View hash = d->storage->GetAs("archiveHash[_H:I,_R:I]");
    d->archiveView = d->archiveView.Hash(hash, 1); // hash on url
    d->autoCommit = autoCommit;

    filePath = d->archivePath +"/feedlistbackup.mk4";
    d->feedListStorage = new c4_Storage(filePath.local8Bit(), true);
    d->feedListView = d->feedListStorage->GetAs("archive[feedList:S,tagSet:S]");
    d->feedListView = d->feedListView.Hash(hash, 1); // hash on url
    return true;
}

bool StorageMK4Impl::autoCommit() const
{
    return d->autoCommit;
}

bool StorageMK4Impl::close()
{
    d->commitTimer->stop();

    QMap<QString, FeedStorage*>::Iterator it;
    QMap<QString, FeedStorage*>::Iterator end(d->feeds.end() ) ;
    for (it = d->feeds.begin(); it != end; ++it)
    {
        it.data()->close();
        delete it.data();
    }
    if(d->autoCommit)
        d->storage->Commit();

    delete d->storage;
    d->storage = 0;

    d->feedListStorage->Commit();
    delete d->feedListStorage;
    d->feedListStorage = 0;

    return true;
}

bool StorageMK4Impl::commit()
{
    QMap<QString, FeedStorage*>::Iterator it;
    QMap<QString, FeedStorage*>::Iterator end(d->feeds.end() ) ;
    for ( it = d->feeds.begin(); it != end; ++it )
        it.data()->commit();

    if(d->storage)
    {
        d->storage->Commit();
        return true;
    }

    return false;
}

bool StorageMK4Impl::rollback()
{
    QMap<QString, FeedStorage*>::Iterator it;
    QMap<QString, FeedStorage*>::Iterator end(d->feeds.end() ) ;
    for ( it = d->feeds.begin(); it != end; ++it )
        it.data()->rollback();

    if(d->storage)
    {
        d->storage->Rollback();
        return true;
    }
    return false;
}

int StorageMK4Impl::unreadFor(const QString &url)
{
    c4_Row findrow;
    d->purl(findrow) = url.ascii();
    int findidx = d->archiveView.Find(findrow);

    return findidx != -1 ? d->punread(d->archiveView.GetAt(findidx)) : 0;
}

void StorageMK4Impl::setUnreadFor(const QString &url, int unread)
{
    c4_Row findrow;
    d->purl(findrow) = url.ascii();
    int findidx = d->archiveView.Find(findrow);
    if (findidx == -1)
        return;
    findrow = d->archiveView.GetAt(findidx);
    d->punread(findrow) = unread;
    d->archiveView.SetAt(findidx, findrow);
    d->modified = true;
}

int StorageMK4Impl::totalCountFor(const QString &url)
{
    c4_Row findrow;
    d->purl(findrow) = url.ascii();
    int findidx = d->archiveView.Find(findrow);

    return findidx != -1 ? d->ptotalCount(d->archiveView.GetAt(findidx)) : 0;
}

void StorageMK4Impl::setTotalCountFor(const QString &url, int total)
{
    c4_Row findrow;
    d->purl(findrow) = url.ascii();
    int findidx = d->archiveView.Find(findrow);
    if (findidx == -1)
        return;
    findrow = d->archiveView.GetAt(findidx);
    d->ptotalCount(findrow) = total;
    d->archiveView.SetAt(findidx, findrow);
    d->modified = true;
}

int StorageMK4Impl::lastFetchFor(const QString& url)
{
    c4_Row findrow;
    d->purl(findrow) = url.ascii();
    int findidx = d->archiveView.Find(findrow);

    return (findidx != -1 ? d->plastFetch(d->archiveView.GetAt(findidx)) : 0);
}

void StorageMK4Impl::setLastFetchFor(const QString& url, int lastFetch)
{
    c4_Row findrow;
    d->purl(findrow) = url.ascii();
    int findidx = d->archiveView.Find(findrow);
    if (findidx == -1)
        return;
    findrow = d->archiveView.GetAt(findidx);
    d->plastFetch(findrow) = lastFetch;
    d->archiveView.SetAt(findidx, findrow);
    d->modified = true;
}

void StorageMK4Impl::slotCommit()
{
    if (d->modified)
    	commit();
    d->modified = false;
}

FeedStorage* StorageMK4Impl::archiveFor(const QString& url)
{
    if (!d->feeds.contains(url))
    {
        FeedStorage* fs = new FeedStorageMK4Impl(url, this);
        d->feeds[url] = fs;
        c4_Row findrow;
        d->purl(findrow) = url.ascii();
        int findidx = d->archiveView.Find(findrow);
        if (findidx == -1)
        {
            d->punread(findrow) = 0;
	    d->ptotalCount(findrow) = 0;
	    d->plastFetch(findrow) = 0;
            d->archiveView.Add(findrow);
            d->modified = true;
        }
        fs->convertOldArchive();
    }
    return d->feeds[url];
}

QStringList StorageMK4Impl::feeds() const
{
    // TODO: cache list
    QStringList list;
    int size = d->archiveView.GetSize();
    for (int i = 0; i < size; i++)
        list += QString(d->purl(d->archiveView.GetAt(i)));
    // fill with urls
    return list;

}

void StorageMK4Impl::add(Storage* source)
{
    QStringList feeds = source->feeds();
    QStringList::ConstIterator end(feeds.end() ) ;

    for (QStringList::ConstIterator it = feeds.begin(); it != end; ++it)
    {
        FeedStorage* fa = archiveFor(*it);
        fa->add(source->archiveFor(*it));
    }
}

void StorageMK4Impl::clear()
{
   QStringList feeds;
    int size = d->archiveView.GetSize();
    for (int i = 0; i < size; i++)
        feeds += QString(d->purl(d->archiveView.GetAt(i)));
    QStringList::ConstIterator end(feeds.end() ) ;

    for (QStringList::ConstIterator it = feeds.begin(); it != end; ++it)
    {
        FeedStorage* fa = archiveFor(*it);
        fa->clear();
        fa->commit();
        // FIXME: delete file (should be 0 in size now)
    }
    d->storage->RemoveAll();

}

void StorageMK4Impl::storeFeedList(const QString& opmlStr)
{

    if  (d->feedListView.GetSize() == 0)
    {
        c4_Row row;
        d->pFeedList(row) = !opmlStr.isEmpty() ? opmlStr.utf8().data() : "";
        d->pTagSet(row) = "";
        d->feedListView.Add(row);
    }
    else
    {
        c4_Row row = d->feedListView.GetAt(0);
        d->pFeedList(row) = !opmlStr.isEmpty() ? opmlStr.utf8().data() : "";
        d->feedListView.SetAt(0, row);
    }
    d->modified = true;
}

QString StorageMK4Impl::restoreFeedList() const
{
    if  (d->feedListView.GetSize() == 0)
        return "";

    c4_Row row = d->feedListView.GetAt(0);
    return QString::fromUtf8(d->pFeedList(row));
}

void StorageMK4Impl::storeTagSet(const QString& xmlStr)
{

    if  (d->feedListView.GetSize() == 0)
    {
        c4_Row row;
        d->pTagSet(row) = !xmlStr.isEmpty() ? xmlStr.utf8().data() : "";
        d->pFeedList(row) = "";
        d->feedListView.Add(row);
    }
    else
    {
        c4_Row row = d->feedListView.GetAt(0);
        d->pTagSet(row) = !xmlStr.isEmpty() ? xmlStr.utf8().data() : "";
        d->feedListView.SetAt(0, row);
    }
    d->modified = true;
}

QString StorageMK4Impl::restoreTagSet() const
{
    if  (d->feedListView.GetSize() == 0)
        return "";

    c4_Row row = d->feedListView.GetAt(0);
    return QString::fromUtf8(d->pTagSet(row));
}

} // namespace Backend
} // namespace Akregator

#include "storagemk4impl.moc"
<|endoftext|>


<commit_before>#include "DatabaseServer.h"
#include "core/global.h"
#include "core/messages.h"
#include "dcparser/dcClass.h"
#include <fstream>

ConfigVariable<channel_t> control_channel("control", 0);
ConfigVariable<unsigned int> id_start("generate/min", 1000);
ConfigVariable<unsigned int> id_end("generate/max", 2000);
ConfigVariable<std::string> storage_folder("storage_folder", "objs/");
LogCategory db_log("db", "Database");

void WriteIDFile(RoleConfig &roleconfig, unsigned int doId)
{
	std::ofstream file;
	std::stringstream ss;
	ss << storage_folder.get_rval(roleconfig)  << "id.txt";
	file.open(ss.str());
	file << doId;
	file.close();
}

void db_UnpackFieldFromDG(DCPackerInterface *field, DatagramIterator &dgi, std::string &str)
{
	if(field->has_fixed_byte_size())
	{
		str += dgi.read_data(field->get_fixed_byte_size());
	}
	else if(field->get_num_length_bytes() > 0)
	{
		unsigned int length = field->get_num_length_bytes();
		switch(length)
		{
		case 2:
		{
			unsigned short l = dgi.read_uint16();
			str += std::string((char*)&l, 2);
			length = l;
		}
		break;
		case 4:
		{
			unsigned int l = dgi.read_uint32();
			str += std::string((char*)&l, 4);
			length = l;
		}
		break;
		break;
		}
		str += dgi.read_data(length);
	}
	else
	{
		unsigned int nNested = field->get_num_nested_fields();
		for(unsigned int i = 0; i < nNested; ++i)
		{
			db_UnpackFieldFromDG(field->get_nested_field(i), dgi, str);
		}
	}
}

DatabaseServer::DatabaseServer(RoleConfig roleconfig) :
	Role(roleconfig), m_freeId(id_start.get_rval(roleconfig))
{
	std::ifstream file;
	std::stringstream ss;
	ss << storage_folder.get_rval(roleconfig)  << "id.txt";
	file.open(ss.str());
	if(file.is_open())
	{
		file >> m_freeId;
	}
	file.close();

	subscribe_channel(control_channel.get_rval(roleconfig));
}

void DatabaseServer::handle_datagram(Datagram &dg, DatagramIterator &dgi)
{
	unsigned long long sender = dgi.read_uint64();
	unsigned short msg_type = dgi.read_uint16();
	switch(msg_type)
	{
		case DBSERVER_CREATE_STORED_OBJECT:
		{
			unsigned int context = dgi.read_uint32();
			unsigned short dcId = dgi.read_uint16();
			DCClass *dcc = gDCF->get_class(dcId);
			unsigned short nFields = dgi.read_uint16();
			unsigned int doId = m_freeId;
			if(doId > id_end.get_rval(m_roleconfig))
			{
				db_log.fatal() << "DB ran out of doIds" << std::endl;
				exit(1);
			}
			m_freeId++;
			WriteIDFile(m_roleconfig, m_freeId);

			Datagram serializedDO;
			serializedDO.add_uint32(doId);
			serializedDO.add_uint16(nFields);

			for(unsigned short  i = 0; i < nFields; ++i)
			{
				unsigned short fieldId = dgi.read_uint16();
				DCField *field = dcc->get_field(fieldId);
				if(field)
				{
					serializedDO.add_string(field->get_name());
					std::string data;
					db_UnpackFieldFromDG(field, dgi, data);
					serializedDO.add_string(data);
				}
			}

			std::stringstream ss;
			ss << storage_folder.get_rval(m_roleconfig)  << doId;
			std::ofstream file;
			file.open(ss.str());
			Datagram resp;
			resp.add_uint8(1);
			resp.add_uint64(sender);
			resp.add_uint64(control_channel.get_rval(m_roleconfig));
			resp.add_uint16(DBSERVER_CREATE_STORED_OBJECT_RESP);

			resp.add_uint32(context);
			if(file.is_open())
			{
				file.write(serializedDO.get_data(), serializedDO.get_buf_end());
				resp.add_uint32(doId);
			}
			else
			{
				resp.add_uint32(0);
			}
			file.close();
			send(resp);
		}
		break;
		default:
			db_log.error() << "DB recv'd unknown MsgType: " << msg_type
				<< std::endl;
	};
}

RoleFactoryItem<DatabaseServer> dbserver_fact("database");<commit_msg>DBServer: Added missing deconstructor.<commit_after>#include "core/global.h"
#include "core/messages.h"
#include "dcparser/dcClass.h"
#include <fstream>

#include "DatabaseServer.h"

ConfigVariable<channel_t> control_channel("control", 0);
ConfigVariable<unsigned int> id_start("generate/min", 1000);
ConfigVariable<unsigned int> id_end("generate/max", 2000);
ConfigVariable<std::string> storage_folder("storage_folder", "objs/");
LogCategory db_log("db", "Database");

void WriteIDFile(RoleConfig &roleconfig, unsigned int doId)
{
	std::ofstream file;
	std::stringstream ss;
	ss << storage_folder.get_rval(roleconfig)  << "id.txt";
	file.open(ss.str());
	file << doId;
	file.close();
}

void db_UnpackFieldFromDG(DCPackerInterface *field, DatagramIterator &dgi, std::string &str)
{
	if(field->has_fixed_byte_size())
	{
		str += dgi.read_data(field->get_fixed_byte_size());
	}
	else if(field->get_num_length_bytes() > 0)
	{
		unsigned int length = field->get_num_length_bytes();
		switch(length)
		{
		case 2:
		{
			unsigned short l = dgi.read_uint16();
			str += std::string((char*)&l, 2);
			length = l;
		}
		break;
		case 4:
		{
			unsigned int l = dgi.read_uint32();
			str += std::string((char*)&l, 4);
			length = l;
		}
		break;
		break;
		}
		str += dgi.read_data(length);
	}
	else
	{
		unsigned int nNested = field->get_num_nested_fields();
		for(unsigned int i = 0; i < nNested; ++i)
		{
			db_UnpackFieldFromDG(field->get_nested_field(i), dgi, str);
		}
	}
}

DatabaseServer::DatabaseServer(RoleConfig roleconfig) : Role(roleconfig)
{
	m_freeId = id_start.get_rval(roleconfig);

	std::ifstream file;
	std::stringstream ss;
	ss << storage_folder.get_rval(roleconfig)  << "id.txt";
	file.open(ss.str());
	if(file.is_open())
	{
		file >> m_freeId;
	}
	file.close();

	subscribe_channel(control_channel.get_rval(roleconfig));
}

DatabaseServer::~DatabaseServer()
{}

void DatabaseServer::handle_datagram(Datagram &in_dg, DatagramIterator &dgi)
{
	unsigned long long sender = dgi.read_uint64();
	unsigned short msg_type = dgi.read_uint16();
	switch(msg_type)
	{
		case DBSERVER_CREATE_STORED_OBJECT:
		{
			unsigned int context = dgi.read_uint32();
			unsigned short dcId = dgi.read_uint16();
			DCClass *dcc = gDCF->get_class(dcId);
			unsigned short nFields = dgi.read_uint16();
			unsigned int doId = m_freeId;
			if(doId > id_end.get_rval(m_roleconfig))
			{
				db_log.fatal() << "DB ran out of doIds" << std::endl;
				exit(1);
			}
			m_freeId++;
			WriteIDFile(m_roleconfig, m_freeId);

			Datagram serializedDO;
			serializedDO.add_uint32(doId);
			serializedDO.add_uint16(nFields);

			for(unsigned short  i = 0; i < nFields; ++i)
			{
				unsigned short fieldId = dgi.read_uint16();
				DCField *field = dcc->get_field(fieldId);
				if(field)
				{
					serializedDO.add_string(field->get_name());
					std::string data;
					db_UnpackFieldFromDG(field, dgi, data);
					serializedDO.add_string(data);
				}
			}

			std::stringstream ss;
			ss << storage_folder.get_rval(m_roleconfig)  << doId;
			std::ofstream file;
			file.open(ss.str());
			Datagram resp;
			resp.add_uint8(1);
			resp.add_uint64(sender);
			resp.add_uint64(control_channel.get_rval(m_roleconfig));
			resp.add_uint16(DBSERVER_CREATE_STORED_OBJECT_RESP);

			resp.add_uint32(context);
			if(file.is_open())
			{
				file.write(serializedDO.get_data(), serializedDO.get_buf_end());
				resp.add_uint32(doId);
			}
			else
			{
				resp.add_uint32(0);
			}
			file.close();
			send(resp);
		}
		break;
		default:
			db_log.error() << "DB recv'd unknown MsgType: " << msg_type
				<< std::endl;
	};
}

RoleFactoryItem<DatabaseServer> dbserver_fact("database");<|endoftext|>


<commit_before>/*
 * Copyright (c) 2010 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * 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;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * 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.
 *
 * Authors: Ali Saidi
 */

#include "base/trace.hh"
#include "dev/arm/rv_ctrl.hh"
#include "mem/packet.hh"
#include "mem/packet_access.hh"

RealViewCtrl::RealViewCtrl(Params *p)
    : BasicPioDevice(p), flags(0)
{
    pioSize = 0xD4;
}

Tick
RealViewCtrl::read(PacketPtr pkt)
{
    assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
    assert(pkt->getSize() == 4);
    Addr daddr = pkt->getAddr() - pioAddr;
    pkt->allocate();

    switch(daddr) {
      case ProcId0:
        pkt->set(params()->proc_id0);
        break;
      case ProcId1:
        pkt->set(params()->proc_id1);
        break;
      case Clock24:
        Tick clk;
        clk = (Tick)(curTick() / (24 * SimClock::Int::us));
        pkt->set((uint32_t)(clk));
        break;
      case Clock100:
        Tick clk100;
        clk100 = (Tick)(curTick() / (100 * SimClock::Int::us));
        pkt->set((uint32_t)(clk100));
        break;
      case Flash:
        pkt->set<uint32_t>(0);
        break;
      case Clcd:
        pkt->set<uint32_t>(0x00001F00);
        break;
      case Osc0:
        pkt->set<uint32_t>(0x00012C5C);
        break;
      case Osc1:
        pkt->set<uint32_t>(0x00002CC0);
        break;
      case Osc2:
        pkt->set<uint32_t>(0x00002C75);
        break;
      case Osc3:
        pkt->set<uint32_t>(0x00020211);
        break;
      case Osc4:
        pkt->set<uint32_t>(0x00002C75);
        break;
      case Lock:
        pkt->set<uint32_t>(sysLock);
        break;
      case Flags:
        pkt->set<uint32_t>(flags);
        break;
      case IdReg:
        pkt->set<uint32_t>(params()->idreg);
        break;
      case CfgStat:
        pkt->set<uint32_t>(1);
        break;
      default:
        warn("Tried to read RealView I/O at offset %#x that doesn't exist\n",
             daddr);
        break;
    }
    pkt->makeAtomicResponse();
    return pioDelay;

}

Tick
RealViewCtrl::write(PacketPtr pkt)
{
    assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);

    Addr daddr = pkt->getAddr() - pioAddr;
    switch (daddr) {
      case Flash:
      case Clcd:
      case Osc0:
      case Osc1:
      case Osc2:
      case Osc3:
      case Osc4:
        break;
      case Lock:
        sysLock.lockVal = pkt->get<uint16_t>();
        break;
      case Flags:
        flags = pkt->get<uint32_t>();
        break;
      case FlagsClr:
        flags = 0;
        break;
      default:
        warn("Tried to write RVIO at offset %#x that doesn't exist\n",
             daddr);
        break;
    }
    pkt->makeAtomicResponse();
    return pioDelay;
}

void
RealViewCtrl::serialize(std::ostream &os)
{
    SERIALIZE_SCALAR(flags);
}

void
RealViewCtrl::unserialize(Checkpoint *cp, const std::string &section)
{
    UNSERIALIZE_SCALAR(flags);
}

RealViewCtrl *
RealViewCtrlParams::create()
{
    return new RealViewCtrl(this);
}
<commit_msg>ARM: fix the calculation of the values in the RV clocks<commit_after>/*
 * Copyright (c) 2010 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * 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;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * 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.
 *
 * Authors: Ali Saidi
 */

#include "base/trace.hh"
#include "dev/arm/rv_ctrl.hh"
#include "mem/packet.hh"
#include "mem/packet_access.hh"

RealViewCtrl::RealViewCtrl(Params *p)
    : BasicPioDevice(p), flags(0)
{
    pioSize = 0xD4;
}

Tick
RealViewCtrl::read(PacketPtr pkt)
{
    assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
    assert(pkt->getSize() == 4);
    Addr daddr = pkt->getAddr() - pioAddr;
    pkt->allocate();

    switch(daddr) {
      case ProcId0:
        pkt->set(params()->proc_id0);
        break;
      case ProcId1:
        pkt->set(params()->proc_id1);
        break;
      case Clock24:
        Tick clk;
        clk = SimClock::Float::MHz * curTick() * 24;
        pkt->set((uint32_t)(clk));
        break;
      case Clock100:
        Tick clk100;
        clk100 = SimClock::Float::MHz * curTick() * 100;
        pkt->set((uint32_t)(clk100));
        break;
      case Flash:
        pkt->set<uint32_t>(0);
        break;
      case Clcd:
        pkt->set<uint32_t>(0x00001F00);
        break;
      case Osc0:
        pkt->set<uint32_t>(0x00012C5C);
        break;
      case Osc1:
        pkt->set<uint32_t>(0x00002CC0);
        break;
      case Osc2:
        pkt->set<uint32_t>(0x00002C75);
        break;
      case Osc3:
        pkt->set<uint32_t>(0x00020211);
        break;
      case Osc4:
        pkt->set<uint32_t>(0x00002C75);
        break;
      case Lock:
        pkt->set<uint32_t>(sysLock);
        break;
      case Flags:
        pkt->set<uint32_t>(flags);
        break;
      case IdReg:
        pkt->set<uint32_t>(params()->idreg);
        break;
      case CfgStat:
        pkt->set<uint32_t>(1);
        break;
      default:
        warn("Tried to read RealView I/O at offset %#x that doesn't exist\n",
             daddr);
        break;
    }
    pkt->makeAtomicResponse();
    return pioDelay;

}

Tick
RealViewCtrl::write(PacketPtr pkt)
{
    assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);

    Addr daddr = pkt->getAddr() - pioAddr;
    switch (daddr) {
      case Flash:
      case Clcd:
      case Osc0:
      case Osc1:
      case Osc2:
      case Osc3:
      case Osc4:
        break;
      case Lock:
        sysLock.lockVal = pkt->get<uint16_t>();
        break;
      case Flags:
        flags = pkt->get<uint32_t>();
        break;
      case FlagsClr:
        flags = 0;
        break;
      default:
        warn("Tried to write RVIO at offset %#x that doesn't exist\n",
             daddr);
        break;
    }
    pkt->makeAtomicResponse();
    return pioDelay;
}

void
RealViewCtrl::serialize(std::ostream &os)
{
    SERIALIZE_SCALAR(flags);
}

void
RealViewCtrl::unserialize(Checkpoint *cp, const std::string &section)
{
    UNSERIALIZE_SCALAR(flags);
}

RealViewCtrl *
RealViewCtrlParams::create()
{
    return new RealViewCtrl(this);
}
<|endoftext|>


<commit_before>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file trie.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 * Trie test functions.
 */

#include <fstream>
#include <random>
#include "JsonSpiritHeaders.h"
#include <libdevcore/CommonIO.h>
#include <libethereum/BlockChain.h>
#include <boost/test/unit_test.hpp>
#include "TestHelper.h"

using namespace std;
using namespace dev;
using namespace dev::eth;

namespace js = json_spirit;

BOOST_AUTO_TEST_SUITE(BasicTests)

BOOST_AUTO_TEST_CASE(genesis_tests)
{
	string testPath = test::getTestPath();
	testPath += "/BasicTests";

	cnote << "Testing Genesis block...";
	js::mValue v;
	string s = asString(contents(testPath + "/genesishashestest.json"));
	BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of 'genesishashestest.json' is empty. Have you cloned the 'tests' repo branch develop?");
	js::read_string(s, v);

	js::mObject o = v.get_obj();

	BOOST_CHECK_EQUAL(BlockChain::genesis().stateRoot, h256(o["genesis_state_root"].get_str()));
	BOOST_CHECK_EQUAL(toHex(BlockChain::createGenesisBlock()), toHex(fromHex(o["genesis_rlp_hex"].get_str())));
	BOOST_CHECK_EQUAL(sha3(BlockChain::createGenesisBlock()), h256(o["genesis_hash"].get_str()));
}

BOOST_AUTO_TEST_SUITE_END()

<commit_msg>empty sha test && common fix on mac<commit_after>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file trie.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 * Trie test functions.
 */

#include <fstream>
#include <random>
#include "JsonSpiritHeaders.h"
#include <libdevcore/CommonIO.h>
#include <libethereum/BlockChain.h>
#include <boost/test/unit_test.hpp>
#include "TestHelper.h"

using namespace std;
using namespace dev;
using namespace dev::eth;

namespace js = json_spirit;

BOOST_AUTO_TEST_SUITE(BasicTests)

BOOST_AUTO_TEST_CASE(emptySHA3Types)
{
	h256 emptyListSHA3(fromHex("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"));
	BOOST_REQUIRE_EQUAL(emptyListSHA3, EmptyListSHA3);

	h256 emptySHA3(fromHex("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"));
	BOOST_REQUIRE_EQUAL(emptySHA3, EmptySHA3);
}

BOOST_AUTO_TEST_CASE(genesis_tests)
{
	string testPath = test::getTestPath();
	testPath += "/BasicTests";

	cnote << "Testing Genesis block...";
	js::mValue v;
	string s = asString(contents(testPath + "/genesishashestest.json"));
	BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of 'genesishashestest.json' is empty. Have you cloned the 'tests' repo branch develop?");
	js::read_string(s, v);

	js::mObject o = v.get_obj();

	BOOST_CHECK_EQUAL(BlockChain::genesis().stateRoot, h256(o["genesis_state_root"].get_str()));
	BOOST_CHECK_EQUAL(toHex(BlockChain::createGenesisBlock()), toHex(fromHex(o["genesis_rlp_hex"].get_str())));
	BOOST_CHECK_EQUAL(sha3(BlockChain::createGenesisBlock()), h256(o["genesis_hash"].get_str()));
}

BOOST_AUTO_TEST_SUITE_END()

<|endoftext|>


<commit_before>/* update.cpp
 *
 * Copyright (c) 2011, 2012 Chantilly Robotics <chantilly612@gmail.com>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/*
 * Implement registry.  This is really easy.
 */

#include <algorithm>
#include "update.h"

update_registry& registry() {
    static update_registry reg_obj;
    return reg_obj;
}

void update_registry::register_func(update_registry::update_func f, void * a) {
    update_registry::registry_entry e(f, a);
    if (find_entry(e) == registry.end()) {
        registry.push_back(registry_entry(f, a));
    }
}

void update_registry::unregister_func(update_registry::update_func f, void * a) {
    update_registry::registry_entry e(f, a);
    std::vector<update_registry::registry_entry>::iterator i = find_entry(e);
    if (i != registry.end()) {
        registry.erase(i);
    }
}

void update_registry::update() {
    unsigned upper = registry.size();
    for (unsigned i = 0; i < upper; ++i) {
        registry[i]();
    }
}

std::vector<update_registry::registry_entry>::iterator
update_registry::find_entry(const update_registry::registry_entry& e) {
    return std::find(registry.begin(), registry.end(), e);
}
<commit_msg>Avoided Static Destruction Order Fiasco<commit_after>/* update.cpp
 *
 * Copyright (c) 2011, 2012 Chantilly Robotics <chantilly612@gmail.com>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/*
 * Implement registry.  This is really easy.
 */

#include <algorithm>
#include "update.h"

update_registry& registry() {
    //note that the destructor for reg_obj is never called.  This is OK because
    //when our program terminates, the kernel will reclaim the whole process'
    //address space.  However, if anything vital goes in the destructor, we'll
    //have issues :/
    static update_registry * reg_obj = new update_registry;
    return reg_obj;
}

void update_registry::register_func(update_registry::update_func f, void * a) {
    update_registry::registry_entry e(f, a);
    if (find_entry(e) == registry.end()) {
        registry.push_back(registry_entry(f, a));
    }
}

void update_registry::unregister_func(update_registry::update_func f, void * a) {
    update_registry::registry_entry e(f, a);
    std::vector<update_registry::registry_entry>::iterator i = find_entry(e);
    if (i != registry.end()) {
        registry.erase(i);
    }
}

void update_registry::update() {
    unsigned upper = registry.size();
    for (unsigned i = 0; i < upper; ++i) {
        registry[i]();
    }
}

std::vector<update_registry::registry_entry>::iterator
update_registry::find_entry(const update_registry::registry_entry& e) {
    return std::find(registry.begin(), registry.end(), e);
}
<|endoftext|>


<commit_before>/*_________________________________________________________________________

  MusicBrainz -- The Internet music metadatabase

  Portions Copyright (C) 2000 Relatable

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

  $Id$
____________________________________________________________________________*/
/***************************************************************************
                          comsocket.cpp  -  description
                             -------------------
    begin                : Thu Mar 23 2000
    copyright            : (C) 2000 by Relatable, LLC
    programed by         : Sean Ward
    email                : sward@relatable.com
 ***************************************************************************/

#include "config.h"

#include "comsocket.h"
#ifndef WIN32

#include <netinet/tcp.h>
#include <errno.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <net/if.h>
#include <sys/ioctl.h>
#endif

#define mb_socklen_t ACCEPT_ARG3

#ifndef SHUT_RDWR
#define SHUT_RDWR 2
#endif

/* FreeBSD uses IPPROTO_TCP */
#ifndef SOL_TCP
#define SOL_TCP IPPROTO_TCP
#endif

#if defined(__QNX__) || defined (__BEOS__)
struct pollfd
{
   int            fd;
   unsigned short events;
   unsigned short revents;
};

#define POLLIN   1
#define POLLOUT  4
#define POLLPRI  2
#define POLLERR  8
#define POLLHUP  16
#define POLLNVAL 32

static int poll(struct pollfd *fds, unsigned int nfds, int timeout)
{
    struct timeval tv;
    fd_set rset, wset, xset;
    struct pollfd *f;
    int ready;
    int maxfd = 0;

    FD_ZERO(&rset);
    FD_ZERO(&wset);
    FD_ZERO(&xset);

    for (f = fds; f < &fds[nfds]; ++f)
       if (f->fd >= 0)
       {
           if (f->events & POLLIN)
              FD_SET(f->fd, &rset);
           if (f->events & POLLOUT)
              FD_SET(f->fd, &wset);
           if (f->events & POLLPRI)
              FD_SET(f->fd, &xset);
           if (f->fd > maxfd && (f->events & (POLLIN|POLLOUT|POLLPRI)))
              maxfd = f->fd;
       }

    tv.tv_sec = timeout / 1000;
    tv.tv_usec = (timeout % 1000) * 1000;

    ready = select(maxfd + 1, &rset, &wset, &xset, timeout == -1 ? NULL : &tv);

    if (ready > 0)
       for (f = fds; f < &fds[nfds]; ++f)
       {
           f->revents = 0;
           if (f->fd >= 0)
           {
               if (FD_ISSET(f->fd, &rset))
                   f->revents |= POLLIN;
               if (FD_ISSET(f->fd, &wset))
                   f->revents |= POLLOUT;
               if (FD_ISSET(f->fd, &xset))
                   f->revents |= POLLPRI;
           }
       }

    return ready;
}
#else
#include <sys/poll.h>
#endif

MBCOMSocket::MBCOMSocket(int nSocket, int nSockType)
{
	m_nSocket = nSocket;
	m_bConnected = false;
	if (m_nSocket != INVALID_SOCKET) m_bConnected = true;
	m_nSockType = nSockType;
}

MBCOMSocket::~MBCOMSocket()
{
	if (IsConnected()) Disconnect();
}

/** Connects a socket to pIP, on nPort, of type nType. */
int MBCOMSocket::Connect(const char* pIP, int nPort, int nType, bool
	bBroadcast)
{
	if (this->IsConnected()) this->Disconnect();

	sockaddr_in addr;

	hostent* pServer;
	int nErr = 0;
	m_nSockType = nType;
	m_nSocket = socket(AF_INET, nType, 0);
	if (m_nSocket < 0) return m_nSocket;

	pServer = gethostbyname(pIP);
	if (pServer == NULL)
	{
		close(m_nSocket);
		m_nSocket = -1;
		return -1;
	}
	memset((char*)&addr, 0, sizeof(addr));
	addr.sin_family = AF_INET;
	memcpy((char*)&(addr.sin_addr.s_addr), (char*)(pServer->h_addr), pServer->h_length);
	addr.sin_port = htons(nPort);

	int nflag = 1;
	if (nType == SOCK_STREAM)
	{
		nErr = setsockopt(m_nSocket, SOL_TCP, TCP_NODELAY, &nflag, sizeof(int));
	}
	if (bBroadcast)
	{
		nErr = setsockopt(m_nSocket, SOL_SOCKET, SO_BROADCAST,
			&nflag, sizeof(int));
	}

	nErr = connect(m_nSocket, (sockaddr*)&addr, sizeof(sockaddr_in));
	if (nErr != 0)
	{

		close(m_nSocket);
		m_nSocket = -1;
		return -1;
	}

	m_bConnected = true;
	return 0;
}

/** Disconnects the current socket */
int MBCOMSocket::Disconnect()
{
	int nErr = 0;
	if (!IsConnected()) return -1;
	if (m_nSockType == SOCK_STREAM)
	{
		nErr = shutdown(m_nSocket, SHUT_RDWR);
	}

	nErr = close(m_nSocket);
	m_nSocket = -1;
	m_bConnected = false;
	return (nErr != -1);
}

/** Checks if there is a current open connection */
bool MBCOMSocket::IsConnected()
{
	return m_bConnected;
}

/** Reads from a socket, into pbuffer, up to a max of nLen byte, and writes how many were actually written to nBytesWritten. */
int MBCOMSocket::Read(char* pBuffer, int nLen, int* nBytesWritten)
{
	if (!IsConnected()) return -1;	// no connection
	int nErr = 0;
	nErr = recv(m_nSocket, (void*)pBuffer, nLen, 0);
	if ((nErr != -1) && (nBytesWritten != NULL))
	{
		*nBytesWritten = nErr;
	}
	return ((nErr != -1) - 1);
}

/** Writes to a socket, from buffer pBuffer, up to nLen bytes, and returns the number of written bytes in pnBytesWritten. */
int MBCOMSocket::Write(const char* pBuffer, int nLen, int* pnBytesWritten)
{
	if (!IsConnected()) return -1; // no connection
	int nErr = 0;
	bool bRepeat = true;
	while (bRepeat)
	{
		nErr = send(m_nSocket, (void*)pBuffer, nLen, 0);
		bRepeat = false;
		if ((nErr == -1) && (errno == EINTR))
		{
			bRepeat = true;
		}
	}
	if ((nErr != -1) && (pnBytesWritten != NULL))
	{
		*pnBytesWritten = nErr;
	}
	return ((nErr != -1) - 1);
}
/** Sets TCPNODELAY to nFlag */
int MBCOMSocket::SetNoDelay(int nFlag)
{
	if (!IsConnected()) return -1;
	int nErr = 0;
	if (m_nSockType == SOCK_STREAM)
	{
		nErr = setsockopt(m_nSocket, SOL_TCP, TCP_NODELAY, &nFlag, sizeof(int));
	}
  return nErr;
}

/** Reads in a non blocking fashion (ie, selects and polls) for nTimeout seconds */
int MBCOMSocket::NBRead(char* pBuffer, int nLen, int* nBytesWritten, int nTimeout)
{
	struct pollfd pfd;
	pfd.fd = m_nSocket;
	pfd.events = POLLIN;

	int retval;

	retval = poll(&pfd, 1, nTimeout*1000);
	if (retval > 0)
	{
		return this->Read(pBuffer, nLen, nBytesWritten);
	}
	else
	{
		return -1;
	}
}

int MBCOMSocket::SetNonBlocking(bool bType)
{
	int nRes = 0;
	int flags = 0;
	flags = fcntl(m_nSocket, F_GETFL, 0);
	if (bType)
	{
		nRes = fcntl(m_nSocket, F_SETFL, flags | O_NONBLOCK);
	}
	else
	{
		flags &= ~O_NONBLOCK;
		nRes = fcntl(m_nSocket, F_SETFL, flags);
	}
	return nRes;
}

int MBCOMSocket::NBConnect(const char* pIP, int nPort, int nType, int nTimeout)
{
	if (this->IsConnected()) this->Disconnect();

	sockaddr_in addr;
	hostent* pServer;
	int nErr = 0;
	m_nSockType = nType;
	m_nSocket = socket(AF_INET, nType, 0);
	if (m_nSocket < 0) return m_nSocket;

	pServer = gethostbyname(pIP);
	if (pServer == NULL)
	{
		close(m_nSocket);
		m_nSocket = -1;
		return -1;
	}
	memset((char*)&addr, 0, sizeof(addr));
	addr.sin_family = AF_INET;
	memcpy((char *)&(addr.sin_addr.s_addr), (char*)(pServer->h_addr), pServer->h_length);
	addr.sin_port = htons(nPort);

	int nflag = 1;
	if (nType == SOCK_STREAM)
	{
		nErr = setsockopt(m_nSocket, SOL_TCP, TCP_NODELAY, &nflag, sizeof(int));
	}
	nErr = this->SetNonBlocking(true);

	nErr = connect(m_nSocket, (sockaddr*)&addr, sizeof(sockaddr_in));

	if (nErr == 0)
	{ // connected immediately
		m_bConnected = true;
		this->SetNonBlocking(false);
		return 1;
	}
	else
	{
		if (errno != EINPROGRESS)
		{
			close(m_nSocket);
			m_nSocket = -1;
			return -1;
		}
		fd_set rset, wset;
		FD_ZERO(&rset);
		FD_SET(m_nSocket, &rset);
		wset = rset;
		struct timeval tval;
		tval.tv_sec = nTimeout;
		tval.tv_usec = 0;

		if (( nErr = select(m_nSocket + 1, &rset, &wset, NULL,
			nTimeout ? &tval : NULL) ) == 0)
		{
			errno = ETIMEDOUT;
			close(m_nSocket);
			m_nSocket = -1;
			return -1;
		}
		if (FD_ISSET(m_nSocket, &rset) || FD_ISSET(m_nSocket,
&wset))
		{
			int error = 0;
                        mb_socklen_t len = sizeof(error);

		if (getsockopt(m_nSocket, SOL_SOCKET, SO_ERROR, &error,
&len) < 0)
		{
		errno = ETIMEDOUT;
			close(m_nSocket);
			m_nSocket = -1;
			return -1;
		}
		}
	}

	m_bConnected = true;
	this->SetNonBlocking(false);
	return 1;
}

/** Sets multicast packets to only go through the NIC labeled pNIC */
int MBCOMSocket::SetMCastInterface(const char* pNIC)
{
#ifndef __linux__
//#warning WARNING COMSocket::SetMCastInterface is NOT IMPLEMENTED
    return -1;
#else
	struct ip_mreqn mReq;
	memset(&mReq, 0, sizeof(ip_mreq));
	int nErr = -1;
	if (m_nSockType == SOCK_DGRAM)
	{
		mReq.imr_ifindex = if_nametoindex(pNIC);
		nErr = setsockopt(m_nSocket, SOL_IP, IP_MULTICAST_IF,
				&mReq, sizeof(ip_mreqn));
	}
	return ((nErr != -1) - 1);
#endif
}
<commit_msg>Another fix for OSX.<commit_after>/*_________________________________________________________________________

  MusicBrainz -- The Internet music metadatabase

  Portions Copyright (C) 2000 Relatable

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

  $Id$
____________________________________________________________________________*/
/***************************************************************************
                          comsocket.cpp  -  description
                             -------------------
    begin                : Thu Mar 23 2000
    copyright            : (C) 2000 by Relatable, LLC
    programed by         : Sean Ward
    email                : sward@relatable.com
 ***************************************************************************/

#include "config.h"

#include "comsocket.h"
#ifndef WIN32

#include <netinet/tcp.h>
#include <errno.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <net/if.h>
#include <sys/ioctl.h>
#endif

#define mb_socklen_t ACCEPT_ARG3

#ifndef SHUT_RDWR
#define SHUT_RDWR 2
#endif

/* FreeBSD uses IPPROTO_TCP */
#ifndef SOL_TCP
#define SOL_TCP IPPROTO_TCP
#endif

#if defined(__QNX__) || defined (__BEOS__) || defined (__APPLE__)
struct pollfd
{
   int            fd;
   unsigned short events;
   unsigned short revents;
};

#define POLLIN   1
#define POLLOUT  4
#define POLLPRI  2
#define POLLERR  8
#define POLLHUP  16
#define POLLNVAL 32

static int poll(struct pollfd *fds, unsigned int nfds, int timeout)
{
    struct timeval tv;
    fd_set rset, wset, xset;
    struct pollfd *f;
    int ready;
    int maxfd = 0;

    FD_ZERO(&rset);
    FD_ZERO(&wset);
    FD_ZERO(&xset);

    for (f = fds; f < &fds[nfds]; ++f)
       if (f->fd >= 0)
       {
           if (f->events & POLLIN)
              FD_SET(f->fd, &rset);
           if (f->events & POLLOUT)
              FD_SET(f->fd, &wset);
           if (f->events & POLLPRI)
              FD_SET(f->fd, &xset);
           if (f->fd > maxfd && (f->events & (POLLIN|POLLOUT|POLLPRI)))
              maxfd = f->fd;
       }

    tv.tv_sec = timeout / 1000;
    tv.tv_usec = (timeout % 1000) * 1000;

    ready = select(maxfd + 1, &rset, &wset, &xset, timeout == -1 ? NULL : &tv);

    if (ready > 0)
       for (f = fds; f < &fds[nfds]; ++f)
       {
           f->revents = 0;
           if (f->fd >= 0)
           {
               if (FD_ISSET(f->fd, &rset))
                   f->revents |= POLLIN;
               if (FD_ISSET(f->fd, &wset))
                   f->revents |= POLLOUT;
               if (FD_ISSET(f->fd, &xset))
                   f->revents |= POLLPRI;
           }
       }

    return ready;
}
#else
#include <sys/poll.h>
#endif

MBCOMSocket::MBCOMSocket(int nSocket, int nSockType)
{
	m_nSocket = nSocket;
	m_bConnected = false;
	if (m_nSocket != INVALID_SOCKET) m_bConnected = true;
	m_nSockType = nSockType;
}

MBCOMSocket::~MBCOMSocket()
{
	if (IsConnected()) Disconnect();
}

/** Connects a socket to pIP, on nPort, of type nType. */
int MBCOMSocket::Connect(const char* pIP, int nPort, int nType, bool
	bBroadcast)
{
	if (this->IsConnected()) this->Disconnect();

	sockaddr_in addr;

	hostent* pServer;
	int nErr = 0;
	m_nSockType = nType;
	m_nSocket = socket(AF_INET, nType, 0);
	if (m_nSocket < 0) return m_nSocket;

	pServer = gethostbyname(pIP);
	if (pServer == NULL)
	{
		close(m_nSocket);
		m_nSocket = -1;
		return -1;
	}
	memset((char*)&addr, 0, sizeof(addr));
	addr.sin_family = AF_INET;
	memcpy((char*)&(addr.sin_addr.s_addr), (char*)(pServer->h_addr), pServer->h_length);
	addr.sin_port = htons(nPort);

	int nflag = 1;
	if (nType == SOCK_STREAM)
	{
		nErr = setsockopt(m_nSocket, SOL_TCP, TCP_NODELAY, &nflag, sizeof(int));
	}
	if (bBroadcast)
	{
		nErr = setsockopt(m_nSocket, SOL_SOCKET, SO_BROADCAST,
			&nflag, sizeof(int));
	}

	nErr = connect(m_nSocket, (sockaddr*)&addr, sizeof(sockaddr_in));
	if (nErr != 0)
	{

		close(m_nSocket);
		m_nSocket = -1;
		return -1;
	}

	m_bConnected = true;
	return 0;
}

/** Disconnects the current socket */
int MBCOMSocket::Disconnect()
{
	int nErr = 0;
	if (!IsConnected()) return -1;
	if (m_nSockType == SOCK_STREAM)
	{
		nErr = shutdown(m_nSocket, SHUT_RDWR);
	}

	nErr = close(m_nSocket);
	m_nSocket = -1;
	m_bConnected = false;
	return (nErr != -1);
}

/** Checks if there is a current open connection */
bool MBCOMSocket::IsConnected()
{
	return m_bConnected;
}

/** Reads from a socket, into pbuffer, up to a max of nLen byte, and writes how many were actually written to nBytesWritten. */
int MBCOMSocket::Read(char* pBuffer, int nLen, int* nBytesWritten)
{
	if (!IsConnected()) return -1;	// no connection
	int nErr = 0;
	nErr = recv(m_nSocket, (void*)pBuffer, nLen, 0);
	if ((nErr != -1) && (nBytesWritten != NULL))
	{
		*nBytesWritten = nErr;
	}
	return ((nErr != -1) - 1);
}

/** Writes to a socket, from buffer pBuffer, up to nLen bytes, and returns the number of written bytes in pnBytesWritten. */
int MBCOMSocket::Write(const char* pBuffer, int nLen, int* pnBytesWritten)
{
	if (!IsConnected()) return -1; // no connection
	int nErr = 0;
	bool bRepeat = true;
	while (bRepeat)
	{
		nErr = send(m_nSocket, (void*)pBuffer, nLen, 0);
		bRepeat = false;
		if ((nErr == -1) && (errno == EINTR))
		{
			bRepeat = true;
		}
	}
	if ((nErr != -1) && (pnBytesWritten != NULL))
	{
		*pnBytesWritten = nErr;
	}
	return ((nErr != -1) - 1);
}
/** Sets TCPNODELAY to nFlag */
int MBCOMSocket::SetNoDelay(int nFlag)
{
	if (!IsConnected()) return -1;
	int nErr = 0;
	if (m_nSockType == SOCK_STREAM)
	{
		nErr = setsockopt(m_nSocket, SOL_TCP, TCP_NODELAY, &nFlag, sizeof(int));
	}
  return nErr;
}

/** Reads in a non blocking fashion (ie, selects and polls) for nTimeout seconds */
int MBCOMSocket::NBRead(char* pBuffer, int nLen, int* nBytesWritten, int nTimeout)
{
	struct pollfd pfd;
	pfd.fd = m_nSocket;
	pfd.events = POLLIN;

	int retval;

	retval = poll(&pfd, 1, nTimeout*1000);
	if (retval > 0)
	{
		return this->Read(pBuffer, nLen, nBytesWritten);
	}
	else
	{
		return -1;
	}
}

int MBCOMSocket::SetNonBlocking(bool bType)
{
	int nRes = 0;
	int flags = 0;
	flags = fcntl(m_nSocket, F_GETFL, 0);
	if (bType)
	{
		nRes = fcntl(m_nSocket, F_SETFL, flags | O_NONBLOCK);
	}
	else
	{
		flags &= ~O_NONBLOCK;
		nRes = fcntl(m_nSocket, F_SETFL, flags);
	}
	return nRes;
}

int MBCOMSocket::NBConnect(const char* pIP, int nPort, int nType, int nTimeout)
{
	if (this->IsConnected()) this->Disconnect();

	sockaddr_in addr;
	hostent* pServer;
	int nErr = 0;
	m_nSockType = nType;
	m_nSocket = socket(AF_INET, nType, 0);
	if (m_nSocket < 0) return m_nSocket;

	pServer = gethostbyname(pIP);
	if (pServer == NULL)
	{
		close(m_nSocket);
		m_nSocket = -1;
		return -1;
	}
	memset((char*)&addr, 0, sizeof(addr));
	addr.sin_family = AF_INET;
	memcpy((char *)&(addr.sin_addr.s_addr), (char*)(pServer->h_addr), pServer->h_length);
	addr.sin_port = htons(nPort);

	int nflag = 1;
	if (nType == SOCK_STREAM)
	{
		nErr = setsockopt(m_nSocket, SOL_TCP, TCP_NODELAY, &nflag, sizeof(int));
	}
	nErr = this->SetNonBlocking(true);

	nErr = connect(m_nSocket, (sockaddr*)&addr, sizeof(sockaddr_in));

	if (nErr == 0)
	{ // connected immediately
		m_bConnected = true;
		this->SetNonBlocking(false);
		return 1;
	}
	else
	{
		if (errno != EINPROGRESS)
		{
			close(m_nSocket);
			m_nSocket = -1;
			return -1;
		}
		fd_set rset, wset;
		FD_ZERO(&rset);
		FD_SET(m_nSocket, &rset);
		wset = rset;
		struct timeval tval;
		tval.tv_sec = nTimeout;
		tval.tv_usec = 0;

		if (( nErr = select(m_nSocket + 1, &rset, &wset, NULL,
			nTimeout ? &tval : NULL) ) == 0)
		{
			errno = ETIMEDOUT;
			close(m_nSocket);
			m_nSocket = -1;
			return -1;
		}
		if (FD_ISSET(m_nSocket, &rset) || FD_ISSET(m_nSocket,
&wset))
		{
			int error = 0;
                        mb_socklen_t len = sizeof(error);

		if (getsockopt(m_nSocket, SOL_SOCKET, SO_ERROR, &error,
&len) < 0)
		{
		errno = ETIMEDOUT;
			close(m_nSocket);
			m_nSocket = -1;
			return -1;
		}
		}
	}

	m_bConnected = true;
	this->SetNonBlocking(false);
	return 1;
}

/** Sets multicast packets to only go through the NIC labeled pNIC */
int MBCOMSocket::SetMCastInterface(const char* pNIC)
{
#ifndef __linux__
//#warning WARNING COMSocket::SetMCastInterface is NOT IMPLEMENTED
    return -1;
#else
	struct ip_mreqn mReq;
	memset(&mReq, 0, sizeof(ip_mreq));
	int nErr = -1;
	if (m_nSockType == SOCK_DGRAM)
	{
		mReq.imr_ifindex = if_nametoindex(pNIC);
		nErr = setsockopt(m_nSocket, SOL_IP, IP_MULTICAST_IF,
				&mReq, sizeof(ip_mreqn));
	}
	return ((nErr != -1) - 1);
#endif
}
<|endoftext|>


<commit_before>#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <sstream>

#include "timing.h"
#include "converter.h"
#include "procs.h"
#include "config.h"

namespace Converter {

  Converter::Converter(){
    fillFFMpegEncoders();
  }

  void Converter::fillFFMpegEncoders(){
    std::vector<char*> cmd;
    cmd.reserve(3);
    cmd.push_back((char*)"ffmpeg");
    cmd.push_back((char*)"-encoders");
    cmd.push_back(NULL);
    int outFD = -1;
    Util::Procs::StartPiped("FFMpegInfo", &cmd[0], 0, &outFD, 0);
    while( Util::Procs::isActive("FFMpegInfo")){ Util::sleep(100); }
    FILE * outFile = fdopen( outFD, "r" );
    char * fileBuf = 0;
    size_t fileBufLen = 0;
    while ( !(feof(outFile) || ferror(outFile)) && (getline(&fileBuf, &fileBufLen, outFile) != -1)){
      if (strstr(fileBuf, "aac") || strstr(fileBuf, "AAC")){
        strtok(fileBuf, " \t");
        allCodecs["ffmpeg"][strtok(NULL, " \t")] = "aac";
      }
      if (strstr(fileBuf, "h264") || strstr(fileBuf, "H264")){
        strtok(fileBuf, " \t");
        allCodecs["ffmpeg"][strtok(NULL, " \t")] = "h264";
      }
      if (strstr(fileBuf, "mp3") || strstr(fileBuf, "MP3")){
        strtok(fileBuf, " \t");
        allCodecs["ffmpeg"][strtok(NULL, " \t")] = "mp3";
      }
    }
    fclose( outFile );
  }

  converterInfo & Converter::getCodecs(){
    return allCodecs;
  }

  JSON::Value Converter::getEncoders(){
    JSON::Value result;
    for (converterInfo::iterator convIt = allCodecs.begin(); convIt != allCodecs.end(); convIt++){
      for (codecInfo::iterator codIt = convIt->second.begin(); codIt != convIt->second.end(); codIt++){
        result[convIt->first][codIt->first] = codIt->second;
      }
    }
    return result;
  }

  JSON::Value Converter::queryPath(std::string myPath){
    std::vector<char*> cmd;
    cmd.reserve(3);
    cmd.push_back((char*)"MistInfo");
    cmd.push_back(NULL);
    cmd.push_back(NULL);
    fprintf( stderr, "Querying %s\n", myPath.c_str());
    JSON::Value result;
    DIR * Dirp = opendir(myPath.c_str());
    struct stat StatBuf;
    if (Dirp){
      dirent * entry;
      while ((entry = readdir(Dirp))){
        if (stat(std::string(myPath + "/" + entry->d_name).c_str(), &StatBuf) == -1){
          continue;
        }
        if ((StatBuf.st_mode & S_IFREG) == 0){
          continue;
        }
        std::string fileName = entry->d_name;
        std::string myPath = std::string(myPath + (myPath[myPath.size()-1] == '/' ? "" : "/") +  entry->d_name);
        cmd[1] = (char*)myPath.c_str();
        int outFD = -1;
        Util::Procs::StartPiped("MistInfo", &cmd[0], 0, &outFD, 0);
        while( Util::Procs::isActive("MistInfo")){ Util::sleep(10); }
        FILE * outFile = fdopen( outFD, "r" );
        char * fileBuf = 0;
        size_t fileBufLen = 0;
        getline(&fileBuf, &fileBufLen, outFile);
        std::string line = fileBuf;
        result[fileName] = JSON::fromString(std::string(fileBuf));
        if ( !result[fileName]){
          result.removeMember(fileName);
        }
        fclose( outFile );
      }
    }
    return result;
  }

  void Converter::startConversion(std::string name, JSON::Value parameters) {
    if ( !parameters.isMember("input")){
      statusHistory[name] = "No input file supplied";
      return;
    }
    if ( !parameters.isMember("output")){
      statusHistory[name] = "No output file supplied";
      return;
    }
    if ( !parameters.isMember("encoder")){
      statusHistory[name] = "No encoder specified";
      return;
    }
    if (allCodecs.find(parameters["encoder"]) == allCodecs.end()){
      statusHistory[name] = "Can not find encoder " + parameters["encoder"].asString();
      return;
    }
    if (parameters.isMember("video")){
      if (parameters["video"].isMember("width") && !parameters["video"].isMember("height")){
        statusHistory[name] = "No height parameter given";
        return;
      }
      if (parameters["video"].isMember("height") && !parameters["video"].isMember("width")){
        statusHistory[name] = "No width parameter given";
        return;
      }
    }
    std::stringstream encoderCommand;
    if (parameters["encoder"] == "ffmpeg"){
      encoderCommand << "ffmpeg -i ";
      encoderCommand << parameters["input"].asString() << " ";
      if (parameters.isMember("video")){
        if ( !parameters["video"].isMember("codec") || parameters["video"]["codec"] == "copy"){
          encoderCommand << "-vcodec copy ";
        }else{
          codecInfo::iterator vidCodec = allCodecs["ffmpeg"].find(parameters["video"]["codec"]);
          if (vidCodec == allCodecs["ffmpeg"].end()){
            statusHistory[name] = "Can not find video codec " + parameters["video"]["codec"].asString();
            return;
          }
          encoderCommand << "-vcodec " << vidCodec->first << " ";
          if (parameters["video"].isMember("fpks")){
            encoderCommand << "-r " << parameters["video"]["fpks"].asInt() / 1000 << " ";
          }
          if (parameters["video"].isMember("width")){
            encoderCommand << "-s " << parameters["video"]["width"].asInt() << "x" << parameters["video"]["height"].asInt() << " ";
          }
          ///\todo Keyframe interval (different in older and newer versions of ffmpeg?)
        }
      }else{
        encoderCommand << "-vn ";
      }
      if (parameters.isMember("audio")){
        if ( !parameters["audio"].isMember("codec")){
          encoderCommand << "-acodec copy ";
        }else{
          codecInfo::iterator audCodec = allCodecs["ffmpeg"].find(parameters["audio"]["codec"]);
          if (audCodec == allCodecs["ffmpeg"].end()){
            statusHistory[name] = "Can not find audio codec " + parameters["audio"]["codec"].asString();
            return;
          }
          if (audCodec->second == "aac"){
            encoderCommand << "-strict -2 ";
          }
          encoderCommand << "-acodec " << audCodec->first << " ";
          if (parameters["audio"].isMember("samplerate")){
            encoderCommand << "-ar " << parameters["audio"]["samplerate"].asInt() << " ";
          }
        }
      }else{
        encoderCommand << "-an ";
      }
      encoderCommand << "-f flv -";
    }
    int statusFD = -1;
    Util::Procs::StartPiped2(name,encoderCommand.str(),Util::getMyPath() + "MistFLV2DTSC -o " + parameters["output"].asString(),0,0,&statusFD,0);
    parameters["statusFD"] = statusFD;
    allConversions[name] = parameters;
  }

  void Converter::updateStatus(){
    if (allConversions.size()){
      std::map<std::string,JSON::Value>::iterator cIt;
      bool hasChanged = true;
      while (hasChanged && allConversions.size()){
        hasChanged = false;
        for (cIt = allConversions.begin(); cIt != allConversions.end(); cIt++){
          if (Util::Procs::isActive(cIt->first)){
            int statusFD = dup(cIt->second["statusFD"].asInt());
            fsync( statusFD );
            FILE* statusFile = fdopen( statusFD, "r" );
            char * fileBuf = 0;
            size_t fileBufLen = 0;
            fseek(statusFile,0,SEEK_END);
            std::string line;
            int totalTime = 0;
            do{
              getdelim(&fileBuf, &fileBufLen, '\r', statusFile);
              line = fileBuf;
              if (line.find("Duration") != std::string::npos){
                int curOffset = line.find("Duration: ") + 10;
                totalTime += atoi(line.substr(curOffset, 2).c_str()) * 60 * 60 * 1000;
                totalTime += atoi(line.substr(curOffset+3, 2).c_str()) * 60 * 1000;
                totalTime += atoi(line.substr(curOffset+6, 2).c_str()) *1000;
                totalTime += atoi(line.substr(curOffset+9, 2).c_str()) * 10;
                cIt->second["duration"] = totalTime;
              }
            }while ( !feof(statusFile) && line.find("frame") != 0);//"frame" is the fist word on an actual status line of ffmpeg
            if ( !feof(statusFile)){
              cIt->second["status"] = parseFFMpegStatus( line );
              cIt->second["status"]["duration"] = cIt->second["duration"];
              cIt->second["status"]["progress"] = (cIt->second["status"]["time"].asInt() * 100) / cIt->second["duration"].asInt();
            }else{
              line.erase(line.end()-1);
              line = line.substr( line.rfind("\n") + 1 );
              cIt->second["status"] = line;
            }
            free(fileBuf);
            fclose(statusFile);
          }else{
            if (statusHistory.find( cIt->first ) == statusHistory.end()){
              statusHistory[cIt->first] = "Conversion successful, running DTSCFix";
              Util::Procs::Start(cIt->first+"DTSCFix",Util::getMyPath() + "MistDTSCFix " + cIt->second["output"].asString());
            }
            allConversions.erase(cIt);
            hasChanged = true;
          }
          break;
        }
      }
    }
    if(statusHistory.size()){
      std::map<std::string,std::string>::iterator sIt;
      for (sIt = statusHistory.begin(); sIt != statusHistory.end(); sIt++){
        if (statusHistory[sIt->first].find("DTSCFix") != std::string::npos){
          if (Util::Procs::isActive(sIt->first+"DTSCFIX")){
            continue;
          }
          statusHistory[sIt->first] = "Conversion successful";
        }
      }
    }
  }

  JSON::Value Converter::parseFFMpegStatus(std::string statusLine){
    JSON::Value result;
    int curOffset = statusLine.find("frame=") + 6;
    result["frame"] = atoi(statusLine.substr(curOffset, statusLine.find("fps=") - curOffset).c_str() );
    curOffset = statusLine.find("time=") + 5;
    int myTime = 0;
    myTime += atoi(statusLine.substr(curOffset, 2).c_str()) * 60 * 60 * 1000;
    myTime += atoi(statusLine.substr(curOffset+3, 2).c_str()) * 60 * 1000;
    myTime += atoi(statusLine.substr(curOffset+6, 2).c_str()) *1000;
    myTime += atoi(statusLine.substr(curOffset+9, 2).c_str()) * 10;
    result["time"] = myTime;
    return result;
  }

  JSON::Value Converter::getStatus(){
    updateStatus();
    JSON::Value result;
    if (allConversions.size()){
      for (std::map<std::string,JSON::Value>::iterator cIt = allConversions.begin(); cIt != allConversions.end(); cIt++){
        result[cIt->first] = cIt->second["status"];
      }
    }
    if (statusHistory.size()){
      std::map<std::string,std::string>::iterator sIt;
      for (sIt = statusHistory.begin(); sIt != statusHistory.end(); sIt++){
        result[sIt->first] = sIt->second;
      }
    }
    return result;
  }

  void Converter::clearStatus(){
    statusHistory.clear();
  }
}
<commit_msg>Small fix in converter api<commit_after>#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <sstream>

#include "timing.h"
#include "converter.h"
#include "procs.h"
#include "config.h"

namespace Converter {

  Converter::Converter(){
    fillFFMpegEncoders();
  }

  void Converter::fillFFMpegEncoders(){
    std::vector<char*> cmd;
    cmd.reserve(3);
    cmd.push_back((char*)"ffmpeg");
    cmd.push_back((char*)"-encoders");
    cmd.push_back(NULL);
    int outFD = -1;
    Util::Procs::StartPiped("FFMpegInfo", &cmd[0], 0, &outFD, 0);
    while( Util::Procs::isActive("FFMpegInfo")){ Util::sleep(100); }
    FILE * outFile = fdopen( outFD, "r" );
    char * fileBuf = 0;
    size_t fileBufLen = 0;
    while ( !(feof(outFile) || ferror(outFile)) && (getline(&fileBuf, &fileBufLen, outFile) != -1)){
      if (strstr(fileBuf, "aac") || strstr(fileBuf, "AAC")){
        strtok(fileBuf, " \t");
        allCodecs["ffmpeg"][strtok(NULL, " \t")] = "aac";
      }
      if (strstr(fileBuf, "h264") || strstr(fileBuf, "H264")){
        strtok(fileBuf, " \t");
        allCodecs["ffmpeg"][strtok(NULL, " \t")] = "h264";
      }
      if (strstr(fileBuf, "mp3") || strstr(fileBuf, "MP3")){
        strtok(fileBuf, " \t");
        allCodecs["ffmpeg"][strtok(NULL, " \t")] = "mp3";
      }
    }
    fclose( outFile );
  }

  converterInfo & Converter::getCodecs(){
    return allCodecs;
  }

  JSON::Value Converter::getEncoders(){
    JSON::Value result;
    for (converterInfo::iterator convIt = allCodecs.begin(); convIt != allCodecs.end(); convIt++){
      for (codecInfo::iterator codIt = convIt->second.begin(); codIt != convIt->second.end(); codIt++){
        result[convIt->first][codIt->first] = codIt->second;
      }
    }
    return result;
  }

  JSON::Value Converter::queryPath(std::string myPath){
    std::vector<char*> cmd;
    cmd.reserve(3);
    std::string mistPath = Util::getMyPath() + "MistInfo";
    cmd.push_back((char*)mistPath.c_str());
    cmd.push_back(NULL);
    cmd.push_back(NULL);
    fprintf( stderr, "Querying %s\n", myPath.c_str());
    JSON::Value result;
    DIR * Dirp = opendir(myPath.c_str());
    struct stat StatBuf;
    if (Dirp){
      dirent * entry;
      while ((entry = readdir(Dirp))){
        if (stat(std::string(myPath + "/" + entry->d_name).c_str(), &StatBuf) == -1){
          continue;
        }
        if ((StatBuf.st_mode & S_IFREG) == 0){
          continue;
        }
        std::string fileName = entry->d_name;
        std::string myPath = std::string(myPath + (myPath[myPath.size()-1] == '/' ? "" : "/") +  entry->d_name);
        cmd[1] = (char*)myPath.c_str();
        int outFD = -1;
        Util::Procs::StartPiped("MistInfo", &cmd[0], 0, &outFD, 0);
        while( Util::Procs::isActive("MistInfo")){ Util::sleep(10); }
        FILE * outFile = fdopen( outFD, "r" );
        char * fileBuf = 0;
        size_t fileBufLen = 0;
        getline(&fileBuf, &fileBufLen, outFile);
        std::string line = fileBuf;
        result[fileName] = JSON::fromString(std::string(fileBuf));
        if ( !result[fileName]){
          result.removeMember(fileName);
        }
        fclose( outFile );
      }
    }
    return result;
  }

  void Converter::startConversion(std::string name, JSON::Value parameters) {
    if ( !parameters.isMember("input")){
      statusHistory[name] = "No input file supplied";
      return;
    }
    if ( !parameters.isMember("output")){
      statusHistory[name] = "No output file supplied";
      return;
    }
    if ( !parameters.isMember("encoder")){
      statusHistory[name] = "No encoder specified";
      return;
    }
    if (allCodecs.find(parameters["encoder"]) == allCodecs.end()){
      statusHistory[name] = "Can not find encoder " + parameters["encoder"].asString();
      return;
    }
    if (parameters.isMember("video")){
      if (parameters["video"].isMember("width") && !parameters["video"].isMember("height")){
        statusHistory[name] = "No height parameter given";
        return;
      }
      if (parameters["video"].isMember("height") && !parameters["video"].isMember("width")){
        statusHistory[name] = "No width parameter given";
        return;
      }
    }
    std::stringstream encoderCommand;
    if (parameters["encoder"] == "ffmpeg"){
      encoderCommand << "ffmpeg -i ";
      encoderCommand << parameters["input"].asString() << " ";
      if (parameters.isMember("video")){
        if ( !parameters["video"].isMember("codec") || parameters["video"]["codec"] == "copy"){
          encoderCommand << "-vcodec copy ";
        }else{
          codecInfo::iterator vidCodec = allCodecs["ffmpeg"].find(parameters["video"]["codec"]);
          if (vidCodec == allCodecs["ffmpeg"].end()){
            statusHistory[name] = "Can not find video codec " + parameters["video"]["codec"].asString();
            return;
          }
          encoderCommand << "-vcodec " << vidCodec->first << " ";
          if (parameters["video"].isMember("fpks")){
            encoderCommand << "-r " << parameters["video"]["fpks"].asInt() / 1000 << " ";
          }
          if (parameters["video"].isMember("width")){
            encoderCommand << "-s " << parameters["video"]["width"].asInt() << "x" << parameters["video"]["height"].asInt() << " ";
          }
          ///\todo Keyframe interval (different in older and newer versions of ffmpeg?)
        }
      }else{
        encoderCommand << "-vn ";
      }
      if (parameters.isMember("audio")){
        if ( !parameters["audio"].isMember("codec")){
          encoderCommand << "-acodec copy ";
        }else{
          codecInfo::iterator audCodec = allCodecs["ffmpeg"].find(parameters["audio"]["codec"]);
          if (audCodec == allCodecs["ffmpeg"].end()){
            statusHistory[name] = "Can not find audio codec " + parameters["audio"]["codec"].asString();
            return;
          }
          if (audCodec->second == "aac"){
            encoderCommand << "-strict -2 ";
          }
          encoderCommand << "-acodec " << audCodec->first << " ";
          if (parameters["audio"].isMember("samplerate")){
            encoderCommand << "-ar " << parameters["audio"]["samplerate"].asInt() << " ";
          }
        }
      }else{
        encoderCommand << "-an ";
      }
      encoderCommand << "-f flv -";
    }
    int statusFD = -1;
    Util::Procs::StartPiped2(name,encoderCommand.str(),Util::getMyPath() + "MistFLV2DTSC -o " + parameters["output"].asString(),0,0,&statusFD,0);
    parameters["statusFD"] = statusFD;
    allConversions[name] = parameters;
  }

  void Converter::updateStatus(){
    if (allConversions.size()){
      std::map<std::string,JSON::Value>::iterator cIt;
      bool hasChanged = true;
      while (hasChanged && allConversions.size()){
        hasChanged = false;
        for (cIt = allConversions.begin(); cIt != allConversions.end(); cIt++){
          if (Util::Procs::isActive(cIt->first)){
            int statusFD = dup(cIt->second["statusFD"].asInt());
            fsync( statusFD );
            FILE* statusFile = fdopen( statusFD, "r" );
            char * fileBuf = 0;
            size_t fileBufLen = 0;
            fseek(statusFile,0,SEEK_END);
            std::string line;
            int totalTime = 0;
            do{
              getdelim(&fileBuf, &fileBufLen, '\r', statusFile);
              line = fileBuf;
              if (line.find("Duration") != std::string::npos){
                int curOffset = line.find("Duration: ") + 10;
                totalTime += atoi(line.substr(curOffset, 2).c_str()) * 60 * 60 * 1000;
                totalTime += atoi(line.substr(curOffset+3, 2).c_str()) * 60 * 1000;
                totalTime += atoi(line.substr(curOffset+6, 2).c_str()) *1000;
                totalTime += atoi(line.substr(curOffset+9, 2).c_str()) * 10;
                cIt->second["duration"] = totalTime;
              }
            }while ( !feof(statusFile) && line.find("frame") != 0);//"frame" is the fist word on an actual status line of ffmpeg
            if ( !feof(statusFile)){
              cIt->second["status"] = parseFFMpegStatus( line );
              cIt->second["status"]["duration"] = cIt->second["duration"];
              cIt->second["status"]["progress"] = (cIt->second["status"]["time"].asInt() * 100) / cIt->second["duration"].asInt();
            }else{
              line.erase(line.end()-1);
              line = line.substr( line.rfind("\n") + 1 );
              cIt->second["status"] = line;
            }
            free(fileBuf);
            fclose(statusFile);
          }else{
            if (statusHistory.find( cIt->first ) == statusHistory.end()){
              statusHistory[cIt->first] = "Conversion successful, running DTSCFix";
              Util::Procs::Start(cIt->first+"DTSCFix",Util::getMyPath() + "MistDTSCFix " + cIt->second["output"].asString());
            }
            allConversions.erase(cIt);
            hasChanged = true;
          }
          break;
        }
      }
    }
    if(statusHistory.size()){
      std::map<std::string,std::string>::iterator sIt;
      for (sIt = statusHistory.begin(); sIt != statusHistory.end(); sIt++){
        if (statusHistory[sIt->first].find("DTSCFix") != std::string::npos){
          if (Util::Procs::isActive(sIt->first+"DTSCFIX")){
            continue;
          }
          statusHistory[sIt->first] = "Conversion successful";
        }
      }
    }
  }

  JSON::Value Converter::parseFFMpegStatus(std::string statusLine){
    JSON::Value result;
    int curOffset = statusLine.find("frame=") + 6;
    result["frame"] = atoi(statusLine.substr(curOffset, statusLine.find("fps=") - curOffset).c_str() );
    curOffset = statusLine.find("time=") + 5;
    int myTime = 0;
    myTime += atoi(statusLine.substr(curOffset, 2).c_str()) * 60 * 60 * 1000;
    myTime += atoi(statusLine.substr(curOffset+3, 2).c_str()) * 60 * 1000;
    myTime += atoi(statusLine.substr(curOffset+6, 2).c_str()) *1000;
    myTime += atoi(statusLine.substr(curOffset+9, 2).c_str()) * 10;
    result["time"] = myTime;
    return result;
  }

  JSON::Value Converter::getStatus(){
    updateStatus();
    JSON::Value result;
    if (allConversions.size()){
      for (std::map<std::string,JSON::Value>::iterator cIt = allConversions.begin(); cIt != allConversions.end(); cIt++){
        result[cIt->first] = cIt->second["status"];
      }
    }
    if (statusHistory.size()){
      std::map<std::string,std::string>::iterator sIt;
      for (sIt = statusHistory.begin(); sIt != statusHistory.end(); sIt++){
        result[sIt->first] = sIt->second;
      }
    }
    return result;
  }

  void Converter::clearStatus(){
    statusHistory.clear();
  }
}
<|endoftext|>


<commit_before>#include "drivers/ms5611.hpp"

#include "unit_config.hpp"

#include "chprintf.h"

void MS5611::init() {
  // Reset device.
  txbuf[0] = ms5611::CMD_RESET;
  exchange(1);

  // Wait for 2.8ms reload (DS p. 9)
  chThdSleepMicroseconds(3000);

  // Read factory data and setup
  txbuf[0] = ms5611::CMD_PROM_SETUP | (1<<7);
  exchange(3);
  // TODO(yoos): health check

  // Read calibration data
  txbuf[0] = ms5611::CMD_PROM_C1;
  exchange(3);
  C1 = (rxbuf[1]<<8) | rxbuf[2];

  txbuf[0] = ms5611::CMD_PROM_C1+2;
  exchange(3);
  C2 = (rxbuf[1]<<8) | rxbuf[2];

  txbuf[0] = ms5611::CMD_PROM_C1+4;
  exchange(3);
  C3 = (rxbuf[1]<<8) | rxbuf[2];

  txbuf[0] = ms5611::CMD_PROM_C1+6;
  exchange(3);
  C4 = (rxbuf[1]<<8) | rxbuf[2];

  txbuf[0] = ms5611::CMD_PROM_C1+8;
  exchange(3);
  C5 = (rxbuf[1]<<8) | rxbuf[2];

  txbuf[0] = ms5611::CMD_PROM_C1+10;
  exchange(3);
  C6 = (rxbuf[1]<<8) | rxbuf[2];
}

BarometerReading MS5611::readBar() {
  // Read every 10 loops to leave time for the maximum 9.04 ms conversion time.
  // This assumes DT = 1 ms. We flip-flop between reading pressure and
  // temperature, sending the conversion command for the other measurement type
  // at the end of each loop.
  static int loop = 0;
  static int which = 0;
  if (loop == 0) {
    txbuf[0] = ms5611::CMD_READ;
    exchange(4);
    uint32_t raw = (((uint32_t) rxbuf[1])<<16) | (((uint32_t) rxbuf[2])<<8) | rxbuf[3];

    if (which == 0) {
      D1 = raw;   // Pressure
      txbuf[0] = ms5611::CMD_CONVERT_D2;   // Convert temperature
      exchange(1);
    }
    else {
      D2 = raw;   // Temperature
      txbuf[0] = ms5611::CMD_CONVERT_D1;   // Convert pressure
      exchange(1);

      updatePT();   // Update temperature-compensated pressure
    }
    which = 1-which;
  }
  loop = (loop+1) % 10;

  // Pack data
  BarometerReading reading {
    .pressure = pressure,
    .temperature = temperature
  };

  return reading;
}

void MS5611::updatePT(void) {
  BaseSequentialStream* chp = (BaseSequentialStream*)&SD4;
  // Calculate temperature (-40 to 85 deg C with 0.01 deg resolution)
  int32_t dT = D2 - (C5 << 8);   // Actual temp - Reference temp
  int32_t TEMP = 2000 + ((dT * C6) / 8388608);   // 100x actual temperature

  // Calculate temperature compensation offsets
  int64_t OFF  = (C2 << 16) + ((dT * C4) / 128);   // Offset at actual temp
  int64_t SENS = (C1 << 15) + ((dT * C3) / 256);   // Sensitivity at actual temp

  // Second-order temperature compensation
  uint32_t T2 = 0;
  uint64_t OFF2 = 0;
  uint64_t SENS2 = 0;
  if (TEMP < 2000) {
    T2 = (dT * dT) >> 31;
    OFF2  = (5 * (TEMP - 2000) * (TEMP - 2000)) >> 1;
    SENS2 = OFF2 >> 1;
  }
  if (TEMP < -1500) {
    OFF2  +=   7 * (TEMP + 1500) * (TEMP + 1500);
    SENS2 += (11 * (TEMP + 1500) * (TEMP + 1500)) >> 1;
  }
  TEMP -= T2;
  OFF  -= OFF2;
  SENS -= SENS2;

  // Calculate pressure (10 to 1200 mbar with 0.01 mbar resolution)
  int32_t P = ((D1 * SENS / 2097152) - OFF) / 32768;   // 100x temp-compensated pressure

  pressure = P / 100.;
  temperature = TEMP / 100.;

  chprintf(chp, "%lu %ld %f %f\r\n", D1, P, temperature, pressure);
}

bool MS5611::healthy() {
  return true;
}
<commit_msg>Disable debug printf in MS5611 driver.<commit_after>#include "drivers/ms5611.hpp"

#include "unit_config.hpp"

#include "chprintf.h"

void MS5611::init() {
  // Reset device.
  txbuf[0] = ms5611::CMD_RESET;
  exchange(1);

  // Wait for 2.8ms reload (DS p. 9)
  chThdSleepMicroseconds(3000);

  // Read factory data and setup
  txbuf[0] = ms5611::CMD_PROM_SETUP | (1<<7);
  exchange(3);
  // TODO(yoos): health check

  // Read calibration data
  txbuf[0] = ms5611::CMD_PROM_C1;
  exchange(3);
  C1 = (rxbuf[1]<<8) | rxbuf[2];

  txbuf[0] = ms5611::CMD_PROM_C1+2;
  exchange(3);
  C2 = (rxbuf[1]<<8) | rxbuf[2];

  txbuf[0] = ms5611::CMD_PROM_C1+4;
  exchange(3);
  C3 = (rxbuf[1]<<8) | rxbuf[2];

  txbuf[0] = ms5611::CMD_PROM_C1+6;
  exchange(3);
  C4 = (rxbuf[1]<<8) | rxbuf[2];

  txbuf[0] = ms5611::CMD_PROM_C1+8;
  exchange(3);
  C5 = (rxbuf[1]<<8) | rxbuf[2];

  txbuf[0] = ms5611::CMD_PROM_C1+10;
  exchange(3);
  C6 = (rxbuf[1]<<8) | rxbuf[2];
}

BarometerReading MS5611::readBar() {
  // Read every 10 loops to leave time for the maximum 9.04 ms conversion time.
  // This assumes DT = 1 ms. We flip-flop between reading pressure and
  // temperature, sending the conversion command for the other measurement type
  // at the end of each loop.
  static int loop = 0;
  static int which = 0;
  if (loop == 0) {
    txbuf[0] = ms5611::CMD_READ;
    exchange(4);
    uint32_t raw = (((uint32_t) rxbuf[1])<<16) | (((uint32_t) rxbuf[2])<<8) | rxbuf[3];

    if (which == 0) {
      D1 = raw;   // Pressure
      txbuf[0] = ms5611::CMD_CONVERT_D2;   // Convert temperature
      exchange(1);
    }
    else {
      D2 = raw;   // Temperature
      txbuf[0] = ms5611::CMD_CONVERT_D1;   // Convert pressure
      exchange(1);

      updatePT();   // Update temperature-compensated pressure
    }
    which = 1-which;
  }
  loop = (loop+1) % 10;

  // Pack data
  BarometerReading reading {
    .pressure = pressure,
    .temperature = temperature
  };

  return reading;
}

void MS5611::updatePT(void) {
  BaseSequentialStream* chp = (BaseSequentialStream*)&SD4;
  // Calculate temperature (-40 to 85 deg C with 0.01 deg resolution)
  int32_t dT = D2 - (C5 << 8);   // Actual temp - Reference temp
  int32_t TEMP = 2000 + ((dT * C6) / 8388608);   // 100x actual temperature

  // Calculate temperature compensation offsets
  int64_t OFF  = (C2 << 16) + ((dT * C4) / 128);   // Offset at actual temp
  int64_t SENS = (C1 << 15) + ((dT * C3) / 256);   // Sensitivity at actual temp

  // Second-order temperature compensation
  uint32_t T2 = 0;
  uint64_t OFF2 = 0;
  uint64_t SENS2 = 0;
  if (TEMP < 2000) {
    T2 = (dT * dT) >> 31;
    OFF2  = (5 * (TEMP - 2000) * (TEMP - 2000)) >> 1;
    SENS2 = OFF2 >> 1;
  }
  if (TEMP < -1500) {
    OFF2  +=   7 * (TEMP + 1500) * (TEMP + 1500);
    SENS2 += (11 * (TEMP + 1500) * (TEMP + 1500)) >> 1;
  }
  TEMP -= T2;
  OFF  -= OFF2;
  SENS -= SENS2;

  // Calculate pressure (10 to 1200 mbar with 0.01 mbar resolution)
  int32_t P = ((D1 * SENS / 2097152) - OFF) / 32768;   // 100x temp-compensated pressure

  pressure = P / 100.;
  temperature = TEMP / 100.;

  //chprintf(chp, "%lu %ld %f %f\r\n", D1, P, temperature, pressure);
}

bool MS5611::healthy() {
  return true;
}
<|endoftext|>