<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: NeonPropFindRequest.cxx,v $
 *
 *  $Revision: 1.23 $
 *
 *  last change: $Author: rt $ $Date: 2008-02-19 12:34:43 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_ucb.hxx"

#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

#ifndef _NEONTYPES_HXX_
#include "NeonTypes.hxx"
#endif
#ifndef _DAVEXCEPTION_HXX_
#include "DAVException.hxx"
#endif
#ifndef _DAVPROPERTIES_HXX_
#include "DAVProperties.hxx"
#endif
#ifndef _NEONPROPFINDREQUEST_HXX_
#include "NeonPropFindRequest.hxx"
#endif
#ifndef _LINKSEQUENCE_HXX_
#include "LinkSequence.hxx"
#endif
#ifndef _LOCKSEQUENCE_HXX_
#include "LockSequence.hxx"
#endif
#ifndef _LOCKENTRYSEQUENCE_HXX_
#include "LockEntrySequence.hxx"
#endif
#ifndef _UCBDEADPROPERTYVALUE_HXX_
#include "UCBDeadPropertyValue.hxx"
#endif

using namespace rtl;
using namespace com::sun::star::uno;
using namespace com::sun::star::ucb;
using namespace std;
using namespace webdav_ucp;

// -------------------------------------------------------------------
extern "C" int NPFR_propfind_iter( void* userdata,
                                   const NeonPropName* pname,
                                   const char* value,
                                   const HttpStatus* status )
{
    /*
        HTTP Response Status Classes:

          - 1: Informational - Request received, continuing process

          - 2: Success - The action was successfully received,
          understood, and accepted

        - 3: Redirection - Further action must be taken in order to
          complete the request

        - 4: Client Error - The request contains bad syntax or cannot
          be fulfilled

        - 5: Server Error - The server failed to fulfill an apparently
          valid request
    */

    if ( status->klass > 2 )
        return 0; // Error getting this property. Go on.

    // Create & set the PropertyValue
    DAVPropertyValue thePropertyValue;
    thePropertyValue.IsCaseSensitive = true;

    DAVProperties::createUCBPropName( pname->nspace,
                                        pname->name,
                                        thePropertyValue.Name );
    bool bHasValue = false;
    if ( DAVProperties::isUCBDeadProperty( *pname ) )
    {
        // DAV dead property added by WebDAV UCP?
        if ( UCBDeadPropertyValue::createFromXML(
                                        value, thePropertyValue.Value ) )
            OSL_ENSURE( thePropertyValue.Value.hasValue(),
                        "NeonPropFindRequest::propfind_iter - No value!" );
            bHasValue = true;
    }

    if ( !bHasValue )
    {
        if ( rtl_str_compareIgnoreAsciiCase(
                                    pname->name, "resourcetype" ) == 0 )
        {
            OString aValue( value );
            aValue = aValue.trim(); // #107358# remove leading/trailing spaces
            if ( aValue.getLength() )
            {
                aValue = aValue.toAsciiLowerCase();
                if ( aValue.compareTo(
                        RTL_CONSTASCII_STRINGPARAM( "<collection" ) ) == 0 )
                {
                    thePropertyValue.Value
                        <<= OUString::createFromAscii( "collection" );
                }
            }

            if ( !thePropertyValue.Value.hasValue() )
            {
                // Take over the value exactly as supplied by the server.
                thePropertyValue.Value <<= OUString::createFromAscii( value );
            }
        }
        else if ( rtl_str_compareIgnoreAsciiCase(
                                    pname->name, "supportedlock" ) == 0 )
        {
            Sequence< LockEntry > aEntries;
            LockEntrySequence::createFromXML( value, aEntries );
            thePropertyValue.Value <<= aEntries;
        }
        else if ( rtl_str_compareIgnoreAsciiCase(
                                    pname->name, "lockdiscovery" ) == 0 )
        {
            Sequence< Lock > aLocks;
            LockSequence::createFromXML( value, aLocks );
            thePropertyValue.Value <<= aLocks;
        }
        else if ( rtl_str_compareIgnoreAsciiCase( pname->name, "source" ) == 0 )
        {
            Sequence< Link > aLinks;
            LinkSequence::createFromXML( value, aLinks );
            thePropertyValue.Value <<= aLinks;
        }
        else
        {
            thePropertyValue.Value
                <<= OStringToOUString( value, RTL_TEXTENCODING_UTF8 );
        }
    }

    // Add the newly created PropertyValue
    DAVResource* theResource = static_cast< DAVResource * >( userdata );
    theResource->properties.push_back( thePropertyValue );

    return 0; // Go on.
}

// -------------------------------------------------------------------
extern "C" void NPFR_propfind_results( void* userdata,
#if NEON_VERSION >= 0x0260
                                       const ne_uri* uri,
#else
                                       const char* href,
#endif
                                       const NeonPropFindResultSet* set )
{
    // @@@ href is not the uri! DAVResource ctor wants uri!

#if NEON_VERSION >= 0x0260
    DAVResource theResource(
                        OStringToOUString( uri->path, RTL_TEXTENCODING_UTF8 ) );
#else
    DAVResource theResource(
                        OStringToOUString( href, RTL_TEXTENCODING_UTF8 ) );
#endif

    ne_propset_iterate( set, NPFR_propfind_iter, &theResource );

    // Add entry to resources list.
    vector< DAVResource > * theResources
        = static_cast< vector< DAVResource > * >( userdata );
    theResources->push_back( theResource );
}
// -------------------------------------------------------------------
extern "C" int NPFR_propnames_iter( void* userdata,
                                    const NeonPropName* pname,
                                    const char* /*value*/,
                                    const HttpStatus* /*status*/ )
{
    OUString aFullName;
    DAVProperties::createUCBPropName( pname->nspace,
                                      pname->name,
                                      aFullName );

    DAVResourceInfo* theResource = static_cast< DAVResourceInfo * >( userdata );
    theResource->properties.push_back( aFullName );
    return 0;
}

// -------------------------------------------------------------------
extern "C" void NPFR_propnames_results( void* userdata,
#if NEON_VERSION >= 0x0260
                                        const ne_uri* uri,
#else
                                        const char* href,
#endif
                                        const NeonPropFindResultSet* results )
{
    // @@@ href is not the uri! DAVResourceInfo ctor wants uri!
    // Create entry for the resource.
#if NEON_VERSION >= 0x0260
    DAVResourceInfo theResource(
                        OStringToOUString( uri->path, RTL_TEXTENCODING_UTF8 ) );
#else
    DAVResourceInfo theResource(
                        OStringToOUString( href, RTL_TEXTENCODING_UTF8 ) );
#endif

    // Fill entry.
    ne_propset_iterate( results, NPFR_propnames_iter, &theResource );

    // Add entry to resources list.
    vector< DAVResourceInfo > * theResources
        = static_cast< vector< DAVResourceInfo > * >( userdata );
    theResources->push_back( theResource );
}

// -------------------------------------------------------------------
// Constructor
// -------------------------------------------------------------------

NeonPropFindRequest::NeonPropFindRequest( HttpSession* inSession,
                                          const char* inPath,
                                          const Depth inDepth,
                                          const vector< OUString >& inPropNames,
                                          vector< DAVResource >& ioResources,
                                          int & nError )
{
    // Generate the list of properties we're looking for
    int thePropCount = inPropNames.size();
    if ( thePropCount > 0 )
    {
        NeonPropName* thePropNames = new NeonPropName[ thePropCount + 1 ];
        int theIndex;

        for ( theIndex = 0; theIndex < thePropCount; theIndex ++ )
        {
            // Split fullname into namespace and name!
            DAVProperties::createNeonPropName(
                             inPropNames[ theIndex ], thePropNames[ theIndex ] );
        }
        thePropNames[ theIndex ].nspace = NULL;
        thePropNames[ theIndex ].name   = NULL;

        nError = ne_simple_propfind( inSession,
                                     inPath,
                                     inDepth,
                                     thePropNames,
                                     NPFR_propfind_results,
                                     &ioResources );

        for ( theIndex = 0; theIndex < thePropCount; theIndex ++ )
            free( (void *)thePropNames[ theIndex ].name );

        delete [] thePropNames;
    }
    else
    {
        // ALLPROP
        nError = ne_simple_propfind( inSession,
                                     inPath,
                                     inDepth,
                                     NULL, // 0 == allprop
                                     NPFR_propfind_results,
                                     &ioResources );
    }

    // #87585# - Sometimes neon lies (because some servers lie).
    if ( ( nError == NE_OK ) && ioResources.empty() )
        nError = NE_ERROR;
}

// -------------------------------------------------------------------
// Constructor
// - obtains property names
// -------------------------------------------------------------------

NeonPropFindRequest::NeonPropFindRequest(
                            HttpSession* inSession,
                            const char* inPath,
                                const Depth inDepth,
                            std::vector< DAVResourceInfo > & ioResInfo,
                            int & nError )
{
    nError = ne_propnames( inSession,
                           inPath,
                           inDepth,
                           NPFR_propnames_results,
                           &ioResInfo );

    // #87585# - Sometimes neon lies (because some servers lie).
    if ( ( nError == NE_OK ) && ioResInfo.empty() )
        nError = NE_ERROR;
}

// -------------------------------------------------------------------
// Destructor
// -------------------------------------------------------------------
NeonPropFindRequest::~NeonPropFindRequest( )
{
}
<commit_msg>INTEGRATION: CWS changefileheader (1.23.16); FILE MERGED 2008/04/01 16:02:26 thb 1.23.16.3: #i85898# Stripping all external header guards 2008/04/01 12:58:26 thb 1.23.16.2: #i85898# Stripping all external header guards 2008/03/31 15:30:31 rt 1.23.16.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: NeonPropFindRequest.cxx,v $
 * $Revision: 1.24 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_ucb.hxx"
#include <osl/diagnose.h>
#include "NeonTypes.hxx"
#include "DAVException.hxx"
#include "DAVProperties.hxx"
#include "NeonPropFindRequest.hxx"
#ifndef _LINKSEQUENCE_HXX_
#include "LinkSequence.hxx"
#endif
#include "LockSequence.hxx"
#include "LockEntrySequence.hxx"
#include "UCBDeadPropertyValue.hxx"

using namespace rtl;
using namespace com::sun::star::uno;
using namespace com::sun::star::ucb;
using namespace std;
using namespace webdav_ucp;

// -------------------------------------------------------------------
extern "C" int NPFR_propfind_iter( void* userdata,
                                   const NeonPropName* pname,
                                   const char* value,
                                   const HttpStatus* status )
{
    /*
        HTTP Response Status Classes:

          - 1: Informational - Request received, continuing process

          - 2: Success - The action was successfully received,
          understood, and accepted

        - 3: Redirection - Further action must be taken in order to
          complete the request

        - 4: Client Error - The request contains bad syntax or cannot
          be fulfilled

        - 5: Server Error - The server failed to fulfill an apparently
          valid request
    */

    if ( status->klass > 2 )
        return 0; // Error getting this property. Go on.

    // Create & set the PropertyValue
    DAVPropertyValue thePropertyValue;
    thePropertyValue.IsCaseSensitive = true;

    DAVProperties::createUCBPropName( pname->nspace,
                                        pname->name,
                                        thePropertyValue.Name );
    bool bHasValue = false;
    if ( DAVProperties::isUCBDeadProperty( *pname ) )
    {
        // DAV dead property added by WebDAV UCP?
        if ( UCBDeadPropertyValue::createFromXML(
                                        value, thePropertyValue.Value ) )
            OSL_ENSURE( thePropertyValue.Value.hasValue(),
                        "NeonPropFindRequest::propfind_iter - No value!" );
            bHasValue = true;
    }

    if ( !bHasValue )
    {
        if ( rtl_str_compareIgnoreAsciiCase(
                                    pname->name, "resourcetype" ) == 0 )
        {
            OString aValue( value );
            aValue = aValue.trim(); // #107358# remove leading/trailing spaces
            if ( aValue.getLength() )
            {
                aValue = aValue.toAsciiLowerCase();
                if ( aValue.compareTo(
                        RTL_CONSTASCII_STRINGPARAM( "<collection" ) ) == 0 )
                {
                    thePropertyValue.Value
                        <<= OUString::createFromAscii( "collection" );
                }
            }

            if ( !thePropertyValue.Value.hasValue() )
            {
                // Take over the value exactly as supplied by the server.
                thePropertyValue.Value <<= OUString::createFromAscii( value );
            }
        }
        else if ( rtl_str_compareIgnoreAsciiCase(
                                    pname->name, "supportedlock" ) == 0 )
        {
            Sequence< LockEntry > aEntries;
            LockEntrySequence::createFromXML( value, aEntries );
            thePropertyValue.Value <<= aEntries;
        }
        else if ( rtl_str_compareIgnoreAsciiCase(
                                    pname->name, "lockdiscovery" ) == 0 )
        {
            Sequence< Lock > aLocks;
            LockSequence::createFromXML( value, aLocks );
            thePropertyValue.Value <<= aLocks;
        }
        else if ( rtl_str_compareIgnoreAsciiCase( pname->name, "source" ) == 0 )
        {
            Sequence< Link > aLinks;
            LinkSequence::createFromXML( value, aLinks );
            thePropertyValue.Value <<= aLinks;
        }
        else
        {
            thePropertyValue.Value
                <<= OStringToOUString( value, RTL_TEXTENCODING_UTF8 );
        }
    }

    // Add the newly created PropertyValue
    DAVResource* theResource = static_cast< DAVResource * >( userdata );
    theResource->properties.push_back( thePropertyValue );

    return 0; // Go on.
}

// -------------------------------------------------------------------
extern "C" void NPFR_propfind_results( void* userdata,
#if NEON_VERSION >= 0x0260
                                       const ne_uri* uri,
#else
                                       const char* href,
#endif
                                       const NeonPropFindResultSet* set )
{
    // @@@ href is not the uri! DAVResource ctor wants uri!

#if NEON_VERSION >= 0x0260
    DAVResource theResource(
                        OStringToOUString( uri->path, RTL_TEXTENCODING_UTF8 ) );
#else
    DAVResource theResource(
                        OStringToOUString( href, RTL_TEXTENCODING_UTF8 ) );
#endif

    ne_propset_iterate( set, NPFR_propfind_iter, &theResource );

    // Add entry to resources list.
    vector< DAVResource > * theResources
        = static_cast< vector< DAVResource > * >( userdata );
    theResources->push_back( theResource );
}
// -------------------------------------------------------------------
extern "C" int NPFR_propnames_iter( void* userdata,
                                    const NeonPropName* pname,
                                    const char* /*value*/,
                                    const HttpStatus* /*status*/ )
{
    OUString aFullName;
    DAVProperties::createUCBPropName( pname->nspace,
                                      pname->name,
                                      aFullName );

    DAVResourceInfo* theResource = static_cast< DAVResourceInfo * >( userdata );
    theResource->properties.push_back( aFullName );
    return 0;
}

// -------------------------------------------------------------------
extern "C" void NPFR_propnames_results( void* userdata,
#if NEON_VERSION >= 0x0260
                                        const ne_uri* uri,
#else
                                        const char* href,
#endif
                                        const NeonPropFindResultSet* results )
{
    // @@@ href is not the uri! DAVResourceInfo ctor wants uri!
    // Create entry for the resource.
#if NEON_VERSION >= 0x0260
    DAVResourceInfo theResource(
                        OStringToOUString( uri->path, RTL_TEXTENCODING_UTF8 ) );
#else
    DAVResourceInfo theResource(
                        OStringToOUString( href, RTL_TEXTENCODING_UTF8 ) );
#endif

    // Fill entry.
    ne_propset_iterate( results, NPFR_propnames_iter, &theResource );

    // Add entry to resources list.
    vector< DAVResourceInfo > * theResources
        = static_cast< vector< DAVResourceInfo > * >( userdata );
    theResources->push_back( theResource );
}

// -------------------------------------------------------------------
// Constructor
// -------------------------------------------------------------------

NeonPropFindRequest::NeonPropFindRequest( HttpSession* inSession,
                                          const char* inPath,
                                          const Depth inDepth,
                                          const vector< OUString >& inPropNames,
                                          vector< DAVResource >& ioResources,
                                          int & nError )
{
    // Generate the list of properties we're looking for
    int thePropCount = inPropNames.size();
    if ( thePropCount > 0 )
    {
        NeonPropName* thePropNames = new NeonPropName[ thePropCount + 1 ];
        int theIndex;

        for ( theIndex = 0; theIndex < thePropCount; theIndex ++ )
        {
            // Split fullname into namespace and name!
            DAVProperties::createNeonPropName(
                             inPropNames[ theIndex ], thePropNames[ theIndex ] );
        }
        thePropNames[ theIndex ].nspace = NULL;
        thePropNames[ theIndex ].name   = NULL;

        nError = ne_simple_propfind( inSession,
                                     inPath,
                                     inDepth,
                                     thePropNames,
                                     NPFR_propfind_results,
                                     &ioResources );

        for ( theIndex = 0; theIndex < thePropCount; theIndex ++ )
            free( (void *)thePropNames[ theIndex ].name );

        delete [] thePropNames;
    }
    else
    {
        // ALLPROP
        nError = ne_simple_propfind( inSession,
                                     inPath,
                                     inDepth,
                                     NULL, // 0 == allprop
                                     NPFR_propfind_results,
                                     &ioResources );
    }

    // #87585# - Sometimes neon lies (because some servers lie).
    if ( ( nError == NE_OK ) && ioResources.empty() )
        nError = NE_ERROR;
}

// -------------------------------------------------------------------
// Constructor
// - obtains property names
// -------------------------------------------------------------------

NeonPropFindRequest::NeonPropFindRequest(
                            HttpSession* inSession,
                            const char* inPath,
                                const Depth inDepth,
                            std::vector< DAVResourceInfo > & ioResInfo,
                            int & nError )
{
    nError = ne_propnames( inSession,
                           inPath,
                           inDepth,
                           NPFR_propnames_results,
                           &ioResInfo );

    // #87585# - Sometimes neon lies (because some servers lie).
    if ( ( nError == NE_OK ) && ioResInfo.empty() )
        nError = NE_ERROR;
}

// -------------------------------------------------------------------
// Destructor
// -------------------------------------------------------------------
NeonPropFindRequest::~NeonPropFindRequest( )
{
}
<|endoftext|>


<commit_before>/*
 * Super Entity Game Server Project
 * http://segs.sf.net/
 * Copyright (c) 2006 - 2016 Super Entity Game Server Team (see Authors.txt)
 * This software is licensed! (See License.txt for details)
 *
 */

// segs includes

#include "CharacterDatabase.h"
#include "AccountInfo.h"
#include "AdminServer.h"
#include "Character.h"
#include "Costume.h"

#include <ace/Log_Msg.h>
#include <QtSql/QSqlDatabase>
#include <QtSql/QSqlDriver>
#include <QtCore/QDebug>
#include <QtSql/QSqlError>
#include <cstdlib>
#include <cstdio>
using namespace std;

CharacterDatabase::~CharacterDatabase()
{
    if(m_db)
        m_db->close();
}
static bool prepQuery(QSqlQuery &qr,const QString &txt) {
    if(!qr.prepare(txt)) {
        qDebug() << "SQL_ERROR:"<<qr.lastError();
        return false;
    }
    return true;
}
static bool doIt(QSqlQuery &qr) {
    if(!qr.exec()) {
        qDebug() << "SQL_ERROR:"<<qr.lastError();
        return false;
    }
    return true;
}
void CharacterDatabase::on_connected(QSqlDatabase *db)
{
    m_db = db;
    if(!db)
        return;

    m_prepared_fill = QSqlQuery(*db);
    m_prepared_account_insert = QSqlQuery(*db);
    m_prepared_char_insert = QSqlQuery(*db);
    m_prepared_costume_insert = QSqlQuery(*db);
    m_prepared_char_select = QSqlQuery(*db);
    m_prepared_account_select = QSqlQuery(*db);
    m_prepared_char_exists = QSqlQuery(*db);
    m_prepared_char_delete = QSqlQuery(*db);

    prepQuery(m_prepared_fill,"SELECT * FROM costume WHERE character_id=? AND costume_index=?");
    prepQuery(m_prepared_account_insert,"INSERT INTO accounts  (account_id,max_slots) VALUES (?,?)");
    prepQuery(m_prepared_char_insert,
                "INSERT INTO characters  "
                "(char_level,slot_index,account_id,char_name,archetype,origin,bodytype,current_map) "
                "VALUES "
                "(?,?,?,?,?,?,?,?)");
    prepQuery(m_prepared_costume_insert,
                "INSERT INTO costume (character_id,costume_index,skin_color,parts) VALUES "
                "(?,?,?,?)");
    prepQuery(m_prepared_char_select,"SELECT * FROM characters WHERE account_id=? AND slot_index=?");
    prepQuery(m_prepared_account_select,"SELECT * FROM accounts WHERE account_id=?");
    prepQuery(m_prepared_char_exists,"SELECT exists (SELECT 1 FROM characters WHERE char_name = $1 LIMIT 1)");
    prepQuery(m_prepared_char_delete,"DELETE FROM characters WHERE account_id=? AND slot_index=?");
}

// UserToken,
bool CharacterDatabase::remove_character(AccountInfo *c,int8_t slot_idx)
{
    assert(c!=nullptr);
    m_prepared_char_delete.bindValue(0,quint64(c->account_server_id()));
    m_prepared_char_delete.bindValue(1,(uint32_t)slot_idx);
    if(!doIt(m_prepared_char_delete))
        return false;
    return true;
}
bool CharacterDatabase::named_character_exists(const QString &name)
{
    m_prepared_char_exists.bindValue(0,name);
    if(!doIt(m_prepared_char_exists))
        return false;

    if(!m_prepared_char_exists.next())
        return false;
    // TODO: handle case of multiple accounts with same name ?
    return m_prepared_char_exists.value(0).toBool();
}
bool CharacterDatabase::fill( AccountInfo *c )
{
    assert(c&&c->account_server_id());

    m_prepared_account_select.bindValue(0,quint64(c->account_server_id()));
    if(!doIt(m_prepared_account_select))
        return false;

    if(!m_prepared_account_select.next())
        return false;
    // TODO: handle case of multiple accounts with same name ?

    c->max_slots(m_prepared_account_select.value("max_slots").toUInt());
    c->game_server_id(m_prepared_account_select.value("id").toULongLong());

    ACE_DEBUG((LM_INFO,"CharacterClient id: %i\n",c->account_server_id()));
    ACE_DEBUG((LM_INFO,"CharacterClient slots: %i\n",c->max_slots()));
    return true;
}
#define STR_OR_EMPTY(c) ((!c.isEmpty()) ? c:"EMPTY")
#define STR_OR_VERY_EMPTY(c) ((c!=0) ? c:"")
bool CharacterDatabase::fill( Character *c)
{
    assert(c&&c->getAccountId());

    m_prepared_char_select.bindValue(0,quint64(c->getAccountId()));
    m_prepared_char_select.bindValue(1,(uint16_t)c->getIndex());
    if(!doIt(m_prepared_char_select))
        return false;

    if(!m_prepared_char_select.next())
    {
        c->reset(); // empty slot
        return true;
    }
//    else if (results.num_rows()>1)
//        ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT ("(%P|%t) CharacterDatabase::fill query returned wrong number of results. %s failed.\n"), query.str().c_str()),false);

    c->setLevel((uint8_t)m_prepared_char_select.value("char_level").toUInt());
    c->setName(STR_OR_EMPTY(m_prepared_char_select.value("char_name").toString()));
    c->m_class_name = (STR_OR_EMPTY(m_prepared_char_select.value("archetype").toString()));
    c->m_origin_name= (STR_OR_EMPTY(m_prepared_char_select.value("origin").toString()));

    CharacterCostume *main_costume = new CharacterCostume;
    // appearance related.
    main_costume->m_body_type = m_prepared_char_select.value("bodytype").toUInt(); // 0
    c->setMapName("Some map name"); // "V_City_00_01.txt" STR_OR_EMPTY(r.getColString("current_map"))
    c->setLastCostumeId(m_prepared_char_select.value("last_costume_id").toUInt());
    main_costume->setSlotIndex(0);
    main_costume->setCharacterId(m_prepared_char_select.value("id").toULongLong());
    c->m_costumes.push_back(main_costume);
    return fill(main_costume);
}
#ifndef ARRAYSIZE
#define ARRAYSIZE(x) (sizeof(x)/sizeof(x[1]))
#define DEFINED_ARRAYSIZE
#endif
bool CharacterDatabase::fill( CharacterCostume *c)
{
    assert(c&&c->getCharacterId());

    m_prepared_fill.bindValue(0,quint64(c->getCharacterId()));
    m_prepared_fill.bindValue(1,(uint16_t)c->getSlotIndex());
    if(!doIt(m_prepared_fill))
        return false;

    if(!m_prepared_fill.next()) // retry with the first one
    {
        m_prepared_fill.bindValue(0,quint64(c->getCharacterId()));
        m_prepared_fill.bindValue(1,0); // get first costume

        if(!doIt(m_prepared_fill))
            return false;
        if(!m_prepared_fill.next()) {
            ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT ("(%P|%t) CharacterDatabase::fill no costumes.\n")),false);
            return false;
        }
    }
    c->skin_color = m_prepared_fill.value("skin_color").toUInt();
    QString serialized_parts= m_prepared_fill.value("parts").toString();
    c->serializeFromDb(serialized_parts);
    c->m_non_default_costme_p = false;
    return true;
}

bool CharacterDatabase::CreateLinkedAccount( uint64_t auth_account_id,const std::string &username,int max_account_slots )
{
    //assert(auth_account_id>0);  sqlite3 autogenerated values start from 0
    assert(username.size()>2);
    m_prepared_account_insert.bindValue(0,quint64(auth_account_id));
    m_prepared_account_insert.bindValue(1,max_account_slots);

    if(!doIt(m_prepared_account_insert))
        return false;
    return true;
}

int CharacterDatabase::remove_account( uint64_t /*acc_serv_id*/ )
{
    return 0;
}
//TODO: SQL String sanitization
bool CharacterDatabase::create( uint64_t gid,uint8_t slot,Character *c )
{
    assert(m_db->driver()->hasFeature(QSqlDriver::LastInsertId));
    assert(gid>0);
    assert(c);
    assert(slot<8);
    Costume *cst = c->getCurrentCostume();
    if(!cst) {
        ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("(%P|%t) CharacterDatabase::create cannot insert char without costume.\n"))
                         ,false);
    }
    m_prepared_char_insert.bindValue(0, c->m_level);
    m_prepared_char_insert.bindValue(1, uint32_t(slot));
    m_prepared_char_insert.bindValue(2, quint64(gid));
    m_prepared_char_insert.bindValue(3, c->m_name);
    m_prepared_char_insert.bindValue(4, c->m_class_name);
    m_prepared_char_insert.bindValue(5, c->m_origin_name);
    m_prepared_char_insert.bindValue(6, c->getCurrentCostume()->m_body_type);
    m_prepared_char_insert.bindValue(7, c->m_mapName);
    if(!doIt(m_prepared_char_insert))
        return false;
    int64_t char_id = m_prepared_char_insert.lastInsertId().toLongLong();

    // create costume

    QString costume_parts;
    cst->serializeToDb(costume_parts);
    m_prepared_costume_insert.bindValue(0,quint64(char_id));
    m_prepared_costume_insert.bindValue(1,uint32_t(0));
    m_prepared_costume_insert.bindValue(2,uint32_t(cst->skin_color));
    m_prepared_costume_insert.bindValue(3,costume_parts);

    if(!doIt(m_prepared_costume_insert))
        return false;
    return true;
}
#ifdef DEFINED_ARRAYSIZE
#undef DEFINED_ARRAYSIZE
#undef ARRAYSIZE
#endif
<commit_msg>First steps towards showing current_map on character select screen<commit_after>/*
 * Super Entity Game Server Project
 * http://segs.sf.net/
 * Copyright (c) 2006 - 2016 Super Entity Game Server Team (see Authors.txt)
 * This software is licensed! (See License.txt for details)
 *
 */

// segs includes

#include "CharacterDatabase.h"
#include "AccountInfo.h"
#include "AdminServer.h"
#include "Character.h"
#include "Costume.h"

#include <ace/Log_Msg.h>
#include <QtSql/QSqlDatabase>
#include <QtSql/QSqlDriver>
#include <QtCore/QDebug>
#include <QtSql/QSqlError>
#include <cstdlib>
#include <cstdio>
using namespace std;

CharacterDatabase::~CharacterDatabase()
{
    if(m_db)
        m_db->close();
}
static bool prepQuery(QSqlQuery &qr,const QString &txt) {
    if(!qr.prepare(txt)) {
        qDebug() << "SQL_ERROR:"<<qr.lastError();
        return false;
    }
    return true;
}
static bool doIt(QSqlQuery &qr) {
    if(!qr.exec()) {
        qDebug() << "SQL_ERROR:"<<qr.lastError();
        return false;
    }
    return true;
}
void CharacterDatabase::on_connected(QSqlDatabase *db)
{
    m_db = db;
    if(!db)
        return;

    m_prepared_fill = QSqlQuery(*db);
    m_prepared_account_insert = QSqlQuery(*db);
    m_prepared_char_insert = QSqlQuery(*db);
    m_prepared_costume_insert = QSqlQuery(*db);
    m_prepared_char_select = QSqlQuery(*db);
    m_prepared_account_select = QSqlQuery(*db);
    m_prepared_char_exists = QSqlQuery(*db);
    m_prepared_char_delete = QSqlQuery(*db);

    prepQuery(m_prepared_fill,"SELECT * FROM costume WHERE character_id=? AND costume_index=?");
    prepQuery(m_prepared_account_insert,"INSERT INTO accounts  (account_id,max_slots) VALUES (?,?)");
    prepQuery(m_prepared_char_insert,
                "INSERT INTO characters  "
                "(char_level,slot_index,account_id,char_name,archetype,origin,bodytype,current_map) "
                "VALUES "
                "(?,?,?,?,?,?,?,?)");
    prepQuery(m_prepared_costume_insert,
                "INSERT INTO costume (character_id,costume_index,skin_color,parts) VALUES "
                "(?,?,?,?)");
    prepQuery(m_prepared_char_select,"SELECT * FROM characters WHERE account_id=? AND slot_index=?");
    prepQuery(m_prepared_account_select,"SELECT * FROM accounts WHERE account_id=?");
    prepQuery(m_prepared_char_exists,"SELECT exists (SELECT 1 FROM characters WHERE char_name = $1 LIMIT 1)");
    prepQuery(m_prepared_char_delete,"DELETE FROM characters WHERE account_id=? AND slot_index=?");
}

// UserToken,
bool CharacterDatabase::remove_character(AccountInfo *c,int8_t slot_idx)
{
    assert(c!=nullptr);
    m_prepared_char_delete.bindValue(0,quint64(c->account_server_id()));
    m_prepared_char_delete.bindValue(1,(uint32_t)slot_idx);
    if(!doIt(m_prepared_char_delete))
        return false;
    return true;
}
bool CharacterDatabase::named_character_exists(const QString &name)
{
    m_prepared_char_exists.bindValue(0,name);
    if(!doIt(m_prepared_char_exists))
        return false;

    if(!m_prepared_char_exists.next())
        return false;
    // TODO: handle case of multiple accounts with same name ?
    return m_prepared_char_exists.value(0).toBool();
}
bool CharacterDatabase::fill( AccountInfo *c )
{
    assert(c&&c->account_server_id());

    m_prepared_account_select.bindValue(0,quint64(c->account_server_id()));
    if(!doIt(m_prepared_account_select))
        return false;

    if(!m_prepared_account_select.next())
        return false;
    // TODO: handle case of multiple accounts with same name ?

    c->max_slots(m_prepared_account_select.value("max_slots").toUInt());
    c->game_server_id(m_prepared_account_select.value("id").toULongLong());

    ACE_DEBUG((LM_INFO,"CharacterClient id: %i\n",c->account_server_id()));
    ACE_DEBUG((LM_INFO,"CharacterClient slots: %i\n",c->max_slots()));
    return true;
}
#define STR_OR_EMPTY(c) ((!c.isEmpty()) ? c:"EMPTY")
#define STR_OR_VERY_EMPTY(c) ((c!=0) ? c:"")
bool CharacterDatabase::fill( Character *c)
{
    assert(c&&c->getAccountId());

    m_prepared_char_select.bindValue(0,quint64(c->getAccountId()));
    m_prepared_char_select.bindValue(1,(uint16_t)c->getIndex());
    if(!doIt(m_prepared_char_select))
        return false;

    if(!m_prepared_char_select.next())
    {
        c->reset(); // empty slot
        return true;
    }
//    else if (results.num_rows()>1)
//        ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT ("(%P|%t) CharacterDatabase::fill query returned wrong number of results. %s failed.\n"), query.str().c_str()),false);

    c->setLevel((uint8_t)m_prepared_char_select.value("char_level").toUInt());
    c->setName(STR_OR_EMPTY(m_prepared_char_select.value("char_name").toString()));
    c->m_class_name = (STR_OR_EMPTY(m_prepared_char_select.value("archetype").toString()));
    c->m_origin_name= (STR_OR_EMPTY(m_prepared_char_select.value("origin").toString()));

    CharacterCostume *main_costume = new CharacterCostume;
    // appearance related.
    main_costume->m_body_type = m_prepared_char_select.value("bodytype").toUInt(); // 0
    c->setMapName(STR_OR_EMPTY(m_prepared_char_select.value("current_map").toString()));
    c->setLastCostumeId(m_prepared_char_select.value("last_costume_id").toUInt());
    main_costume->setSlotIndex(0);
    main_costume->setCharacterId(m_prepared_char_select.value("id").toULongLong());
    c->m_costumes.push_back(main_costume);
    return fill(main_costume);
}
#ifndef ARRAYSIZE
#define ARRAYSIZE(x) (sizeof(x)/sizeof(x[1]))
#define DEFINED_ARRAYSIZE
#endif
bool CharacterDatabase::fill( CharacterCostume *c)
{
    assert(c&&c->getCharacterId());

    m_prepared_fill.bindValue(0,quint64(c->getCharacterId()));
    m_prepared_fill.bindValue(1,(uint16_t)c->getSlotIndex());
    if(!doIt(m_prepared_fill))
        return false;

    if(!m_prepared_fill.next()) // retry with the first one
    {
        m_prepared_fill.bindValue(0,quint64(c->getCharacterId()));
        m_prepared_fill.bindValue(1,0); // get first costume

        if(!doIt(m_prepared_fill))
            return false;
        if(!m_prepared_fill.next()) {
            ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT ("(%P|%t) CharacterDatabase::fill no costumes.\n")),false);
            return false;
        }
    }
    c->skin_color = m_prepared_fill.value("skin_color").toUInt();
    QString serialized_parts= m_prepared_fill.value("parts").toString();
    c->serializeFromDb(serialized_parts);
    c->m_non_default_costme_p = false;
    return true;
}

bool CharacterDatabase::CreateLinkedAccount( uint64_t auth_account_id,const std::string &username,int max_account_slots )
{
    //assert(auth_account_id>0);  sqlite3 autogenerated values start from 0
    assert(username.size()>2);
    m_prepared_account_insert.bindValue(0,quint64(auth_account_id));
    m_prepared_account_insert.bindValue(1,max_account_slots);

    if(!doIt(m_prepared_account_insert))
        return false;
    return true;
}

int CharacterDatabase::remove_account( uint64_t /*acc_serv_id*/ )
{
    return 0;
}
//TODO: SQL String sanitization
bool CharacterDatabase::create( uint64_t gid,uint8_t slot,Character *c )
{
    assert(m_db->driver()->hasFeature(QSqlDriver::LastInsertId));
    assert(gid>0);
    assert(c);
    assert(slot<8);
    Costume *cst = c->getCurrentCostume();
    if(!cst) {
        ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("(%P|%t) CharacterDatabase::create cannot insert char without costume.\n"))
                         ,false);
    }
    m_prepared_char_insert.bindValue(0, c->m_level);
    m_prepared_char_insert.bindValue(1, uint32_t(slot));
    m_prepared_char_insert.bindValue(2, quint64(gid));
    m_prepared_char_insert.bindValue(3, c->m_name);
    m_prepared_char_insert.bindValue(4, c->m_class_name);
    m_prepared_char_insert.bindValue(5, c->m_origin_name);
    m_prepared_char_insert.bindValue(6, c->getCurrentCostume()->m_body_type);
    m_prepared_char_insert.bindValue(7, c->m_mapName);
    if(!doIt(m_prepared_char_insert))
        return false;
    int64_t char_id = m_prepared_char_insert.lastInsertId().toLongLong();

    // create costume

    QString costume_parts;
    cst->serializeToDb(costume_parts);
    m_prepared_costume_insert.bindValue(0,quint64(char_id));
    m_prepared_costume_insert.bindValue(1,uint32_t(0));
    m_prepared_costume_insert.bindValue(2,uint32_t(cst->skin_color));
    m_prepared_costume_insert.bindValue(3,costume_parts);

    if(!doIt(m_prepared_costume_insert))
        return false;
    return true;
}
#ifdef DEFINED_ARRAYSIZE
#undef DEFINED_ARRAYSIZE
#undef ARRAYSIZE
#endif
<|endoftext|>


<commit_before>/* mbed Microcontroller Library
 * Copyright (c) 2018 ARM Limited
 *
 * 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.
 */

#include <stdio.h>
#include <algorithm>

#include "driver/CordioHCITransportDriver.h"
#include "driver/CordioHCIDriver.h"
#include "hci_defs.h"
#include "rtos/EventFlags.h"

#include "greentea-client/test_env.h"
#include "utest/utest.h"
#include "unity/unity.h"

using namespace utest::v1;

using ble::vendor::cordio::CordioHCIDriver;
using ble::vendor::cordio::CordioHCITransportDriver;

extern ble::vendor::cordio::CordioHCIDriver& ble_cordio_get_hci_driver();

namespace ble {
namespace vendor {
namespace cordio {

struct CordioHCIHook {
    static CordioHCIDriver& get_driver() {
        return ble_cordio_get_hci_driver();
    }

    static CordioHCITransportDriver& get_transport_driver() {
        return get_driver()._transport_driver;
    }

    static void set_data_received_handler(void (*handler)(uint8_t*, uint8_t)) {
        get_transport_driver().set_data_received_handler(handler);
    }
};

} // namespace cordio
} // namespace vendor
} // namespace ble

using ble::vendor::cordio::CordioHCIHook;

//
// Handle signal mechanism
//
#define RESET_COMMAND_TIMEOUT (10 * 1000)

static const uint32_t RESET_RECEIVED_FLAG = 1 << 0;
static const uint32_t RECEPTION_ERROR_FLAG = 1 << 1;
static const uint32_t RESET_STATUS_ERROR_FLAG = 1 << 2;

static const uint32_t WAITING_FLAGS =
    RESET_RECEIVED_FLAG | RECEPTION_ERROR_FLAG | RESET_STATUS_ERROR_FLAG;

static rtos::EventFlags event_channel;

static void signal_flag(uint32_t flag) {
    if (!(event_channel.get() & flag)) {
        event_channel.set(flag);
    }
}

uint32_t wait_for_event() {
    // clear reception flags
    uint32_t flags = event_channel.get();
    event_channel.clear(flags & ~RESET_RECEIVED_FLAG);

    return event_channel.wait_any(
        WAITING_FLAGS,
        /* timeout */ RESET_COMMAND_TIMEOUT,
        /* clear */ false
    );
}

//
// Handle reset command reception
//

#define RESET_PARAMETER_LENGTH  4
#define RESET_EXPECTED_STATUS  0
#define HCI_OPCODE_RESET_LSB (HCI_OPCODE_RESET & 0xFF)
#define HCI_OPCODE_RESET_MSB (HCI_OPCODE_RESET >> 8)
#define RESET_PACKET_LENGTH (1 + HCI_EVT_HDR_LEN + RESET_PARAMETER_LENGTH)
#define RESET_STATUS_INDEX 6

static bool is_reset_event(const uint8_t* data, uint16_t len) {
    if (len != RESET_PACKET_LENGTH) {
        return false;
    }

    if (*data++ != HCI_EVT_TYPE) {
        return false;
    }

    if (*data++ != HCI_CMD_CMPL_EVT) {
        return false;
    }

    if (*data++ != RESET_PARAMETER_LENGTH) {
        return false;
    }

    // Note skip num of HCI packet as this is controller dependent
    data++;

    if (*data++ != HCI_OPCODE_RESET_LSB) {
        return false;
    }

    if (*data++ != HCI_OPCODE_RESET_MSB) {
        return false;
    }

    return true;
}

static void hci_driver_rx_reset_handler(uint8_t* data, uint8_t len) {
    enum packet_state_t {
        WAITING_FOR_PACKET_TYPE,
        WAITING_FOR_HEADER_COMPLETE,
        WAITING_FOR_DATA_COMPLETE,
        SYNCHRONIZATION_ERROR,
        STATUS_ERROR
    };

    static uint8_t packet[256] = { 0 };
    static uint16_t position = 0;
    static uint16_t packet_length;
    static packet_state_t reception_state = WAITING_FOR_PACKET_TYPE;

    while (len) {
        switch (reception_state) {
            case WAITING_FOR_PACKET_TYPE:
                if (*data != HCI_EVT_TYPE) {
                    reception_state = SYNCHRONIZATION_ERROR;
                    signal_flag(RECEPTION_ERROR_FLAG);
                    return;
                }

                packet[position++] = *data++;
                --len;
                packet_length = 1 + HCI_EVT_HDR_LEN;
                reception_state = WAITING_FOR_HEADER_COMPLETE;
                break;

            case WAITING_FOR_HEADER_COMPLETE:
            case WAITING_FOR_DATA_COMPLETE: {
                uint16_t step = std::min((uint16_t) len, (uint16_t) (packet_length - position));
                memcpy(packet + position, data, step);
                position+= step;
                data += step;
                len -= step;

                if (reception_state == WAITING_FOR_HEADER_COMPLETE &&
                    position == packet_length
                ) {
                    reception_state = WAITING_FOR_DATA_COMPLETE;
                    packet_length += packet[HCI_EVT_HDR_LEN];
                }
            }   break;

            // dead end; we never exit from the error state; just asignal it again.
            case SYNCHRONIZATION_ERROR:
                signal_flag(RECEPTION_ERROR_FLAG);
                return;

            case STATUS_ERROR:
                signal_flag(RESET_STATUS_ERROR_FLAG);
                return;
        }

        bool packet_complete = (reception_state == WAITING_FOR_DATA_COMPLETE) &&
            (position == packet_length);

        if (packet_complete) {
            if (is_reset_event(packet, packet_length)) {
                if (packet[RESET_STATUS_INDEX] != RESET_EXPECTED_STATUS) {
                    reception_state = STATUS_ERROR;
                    signal_flag(RESET_STATUS_ERROR_FLAG);
                    return;
                } else {
                    signal_flag(RESET_RECEIVED_FLAG);
                }
            }

            reception_state = WAITING_FOR_PACKET_TYPE;
            position = 0;
            packet_length = 1;
        }
    }
}

static uint8_t reset_cmd[] = {
    HCI_OPCODE_RESET_LSB, HCI_OPCODE_RESET_MSB,  // reset opcode
    0 // parameter length
};

void test_reset_command() {
    CordioHCIDriver& driver = CordioHCIHook::get_driver();
    CordioHCITransportDriver& transport_driver = CordioHCIHook::get_transport_driver();

    driver.initialize();

    CordioHCIHook::set_data_received_handler(hci_driver_rx_reset_handler);

    transport_driver.write(HCI_CMD_TYPE, sizeof(reset_cmd), reset_cmd);
    uint32_t events = wait_for_event();

    TEST_ASSERT_EQUAL(RESET_RECEIVED_FLAG, events);

    driver.terminate();
}

#define EXPECTED_CONSECUTIVE_RESET   10

void test_multiple_reset_command() {
    CordioHCIDriver& driver = CordioHCIHook::get_driver();
    CordioHCITransportDriver& transport_driver = CordioHCIHook::get_transport_driver();

    driver.initialize();

    CordioHCIHook::set_data_received_handler(hci_driver_rx_reset_handler);

    for (size_t i = 0; i < EXPECTED_CONSECUTIVE_RESET; ++i) {
        transport_driver.write(HCI_CMD_TYPE, sizeof(reset_cmd), reset_cmd);
        uint32_t events = wait_for_event();
        TEST_ASSERT_EQUAL(RESET_RECEIVED_FLAG, events);
        if (events != RESET_RECEIVED_FLAG) {
            break;
        }
    }

    driver.terminate();
}

Case cases[] = {
    Case("Test reset command", test_reset_command),
    Case("Test multiple reset commands", test_multiple_reset_command)
};

utest::v1::status_t greentea_test_setup(const size_t number_of_cases) {
    GREENTEA_SETUP(15, "default_auto");
    return verbose_test_setup_handler(number_of_cases);
}

Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);

int main() {
    return !Harness::run(specification);
}
<commit_msg>exculde test<commit_after>/* mbed Microcontroller Library
 * Copyright (c) 2018 ARM Limited
 *
 * 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.
 */

#include <stdio.h>
#include <algorithm>

#include "driver/CordioHCITransportDriver.h"
#include "driver/CordioHCIDriver.h"
#include "hci_defs.h"
#include "rtos/EventFlags.h"

#include "greentea-client/test_env.h"
#include "utest/utest.h"
#include "unity/unity.h"

using namespace utest::v1;

using ble::vendor::cordio::CordioHCIDriver;
using ble::vendor::cordio::CordioHCITransportDriver;

extern ble::vendor::cordio::CordioHCIDriver& ble_cordio_get_hci_driver();

#if CORDIO_ZERO_COPY_HCI
#error [NOT_SUPPORTED] Test not relevant for zero copy hci.
#endif

namespace ble {
namespace vendor {
namespace cordio {

struct CordioHCIHook {
    static CordioHCIDriver& get_driver() {
        return ble_cordio_get_hci_driver();
    }

    static CordioHCITransportDriver& get_transport_driver() {
        return get_driver()._transport_driver;
    }

    static void set_data_received_handler(void (*handler)(uint8_t*, uint8_t)) {
        get_transport_driver().set_data_received_handler(handler);
    }
};

} // namespace cordio
} // namespace vendor
} // namespace ble

using ble::vendor::cordio::CordioHCIHook;

//
// Handle signal mechanism
//
#define RESET_COMMAND_TIMEOUT (10 * 1000)

static const uint32_t RESET_RECEIVED_FLAG = 1 << 0;
static const uint32_t RECEPTION_ERROR_FLAG = 1 << 1;
static const uint32_t RESET_STATUS_ERROR_FLAG = 1 << 2;

static const uint32_t WAITING_FLAGS =
    RESET_RECEIVED_FLAG | RECEPTION_ERROR_FLAG | RESET_STATUS_ERROR_FLAG;

static rtos::EventFlags event_channel;

static void signal_flag(uint32_t flag) {
    if (!(event_channel.get() & flag)) {
        event_channel.set(flag);
    }
}

uint32_t wait_for_event() {
    // clear reception flags
    uint32_t flags = event_channel.get();
    event_channel.clear(flags & ~RESET_RECEIVED_FLAG);

    return event_channel.wait_any(
        WAITING_FLAGS,
        /* timeout */ RESET_COMMAND_TIMEOUT,
        /* clear */ false
    );
}

//
// Handle reset command reception
//

#define RESET_PARAMETER_LENGTH  4
#define RESET_EXPECTED_STATUS  0
#define HCI_OPCODE_RESET_LSB (HCI_OPCODE_RESET & 0xFF)
#define HCI_OPCODE_RESET_MSB (HCI_OPCODE_RESET >> 8)
#define RESET_PACKET_LENGTH (1 + HCI_EVT_HDR_LEN + RESET_PARAMETER_LENGTH)
#define RESET_STATUS_INDEX 6

static bool is_reset_event(const uint8_t* data, uint16_t len) {
    if (len != RESET_PACKET_LENGTH) {
        return false;
    }

    if (*data++ != HCI_EVT_TYPE) {
        return false;
    }

    if (*data++ != HCI_CMD_CMPL_EVT) {
        return false;
    }

    if (*data++ != RESET_PARAMETER_LENGTH) {
        return false;
    }

    // Note skip num of HCI packet as this is controller dependent
    data++;

    if (*data++ != HCI_OPCODE_RESET_LSB) {
        return false;
    }

    if (*data++ != HCI_OPCODE_RESET_MSB) {
        return false;
    }

    return true;
}

static void hci_driver_rx_reset_handler(uint8_t* data, uint8_t len) {
    enum packet_state_t {
        WAITING_FOR_PACKET_TYPE,
        WAITING_FOR_HEADER_COMPLETE,
        WAITING_FOR_DATA_COMPLETE,
        SYNCHRONIZATION_ERROR,
        STATUS_ERROR
    };

    static uint8_t packet[256] = { 0 };
    static uint16_t position = 0;
    static uint16_t packet_length;
    static packet_state_t reception_state = WAITING_FOR_PACKET_TYPE;

    while (len) {
        switch (reception_state) {
            case WAITING_FOR_PACKET_TYPE:
                if (*data != HCI_EVT_TYPE) {
                    reception_state = SYNCHRONIZATION_ERROR;
                    signal_flag(RECEPTION_ERROR_FLAG);
                    return;
                }

                packet[position++] = *data++;
                --len;
                packet_length = 1 + HCI_EVT_HDR_LEN;
                reception_state = WAITING_FOR_HEADER_COMPLETE;
                break;

            case WAITING_FOR_HEADER_COMPLETE:
            case WAITING_FOR_DATA_COMPLETE: {
                uint16_t step = std::min((uint16_t) len, (uint16_t) (packet_length - position));
                memcpy(packet + position, data, step);
                position+= step;
                data += step;
                len -= step;

                if (reception_state == WAITING_FOR_HEADER_COMPLETE &&
                    position == packet_length
                ) {
                    reception_state = WAITING_FOR_DATA_COMPLETE;
                    packet_length += packet[HCI_EVT_HDR_LEN];
                }
            }   break;

            // dead end; we never exit from the error state; just asignal it again.
            case SYNCHRONIZATION_ERROR:
                signal_flag(RECEPTION_ERROR_FLAG);
                return;

            case STATUS_ERROR:
                signal_flag(RESET_STATUS_ERROR_FLAG);
                return;
        }

        bool packet_complete = (reception_state == WAITING_FOR_DATA_COMPLETE) &&
            (position == packet_length);

        if (packet_complete) {
            if (is_reset_event(packet, packet_length)) {
                if (packet[RESET_STATUS_INDEX] != RESET_EXPECTED_STATUS) {
                    reception_state = STATUS_ERROR;
                    signal_flag(RESET_STATUS_ERROR_FLAG);
                    return;
                } else {
                    signal_flag(RESET_RECEIVED_FLAG);
                }
            }

            reception_state = WAITING_FOR_PACKET_TYPE;
            position = 0;
            packet_length = 1;
        }
    }
}

static uint8_t reset_cmd[] = {
    HCI_OPCODE_RESET_LSB, HCI_OPCODE_RESET_MSB,  // reset opcode
    0 // parameter length
};

void test_reset_command() {
    CordioHCIDriver& driver = CordioHCIHook::get_driver();
    CordioHCITransportDriver& transport_driver = CordioHCIHook::get_transport_driver();

    driver.initialize();

    CordioHCIHook::set_data_received_handler(hci_driver_rx_reset_handler);

    transport_driver.write(HCI_CMD_TYPE, sizeof(reset_cmd), reset_cmd);
    uint32_t events = wait_for_event();

    TEST_ASSERT_EQUAL(RESET_RECEIVED_FLAG, events);

    driver.terminate();
}

#define EXPECTED_CONSECUTIVE_RESET   10

void test_multiple_reset_command() {
    CordioHCIDriver& driver = CordioHCIHook::get_driver();
    CordioHCITransportDriver& transport_driver = CordioHCIHook::get_transport_driver();

    driver.initialize();

    CordioHCIHook::set_data_received_handler(hci_driver_rx_reset_handler);

    for (size_t i = 0; i < EXPECTED_CONSECUTIVE_RESET; ++i) {
        transport_driver.write(HCI_CMD_TYPE, sizeof(reset_cmd), reset_cmd);
        uint32_t events = wait_for_event();
        TEST_ASSERT_EQUAL(RESET_RECEIVED_FLAG, events);
        if (events != RESET_RECEIVED_FLAG) {
            break;
        }
    }

    driver.terminate();
}

Case cases[] = {
    Case("Test reset command", test_reset_command),
    Case("Test multiple reset commands", test_multiple_reset_command)
};

utest::v1::status_t greentea_test_setup(const size_t number_of_cases) {
    GREENTEA_SETUP(15, "default_auto");
    return verbose_test_setup_handler(number_of_cases);
}

Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);

int main() {
    return !Harness::run(specification);
}
<|endoftext|>


<commit_before>#include "arc.h"

#include "objs/net.h"

spnp::Arc::Arc():AbstractData()
{
    this->place = -1;
    this->transition = -1;
    this->fromPlaceToTransition = false;
    this->multiplicity = "1";
    this->isFluid = false;
    this->isInhibitor = false;
}

spnp::Arc::Arc(std::string name, std::string place,
               std::string transition, bool fromPlaceToTransition,
               std::string multiplicity, bool isFluid, bool isInhibitor, bool isConstant):AbstractData(name)
{
    this->place = place;
    this->transition = transition;
    this->fromPlaceToTransition = fromPlaceToTransition;
    this->multiplicity = multiplicity;
    this->isFluid = isFluid;
    this->isInhibitor = isInhibitor;
    this->isConstant = isConstant;
}

spnp::Arc::~Arc()
{

}

XMLNode *spnp::Arc::toXML()
{
    XMLNode* node = AbstractData::toXML();
    node->setAttribute("place", this->place);
    node->setAttribute("transition", this->transition);
    node->setAttribute("ptot", this->fromPlaceToTransition);
    node->setAttribute("multiplicity", this->multiplicity);
    node->setAttribute("fluid", this->isFluid);
    node->setAttribute("inhibitor", this->isInhibitor);
    node->setAttribute("const", this->isConstant);
    return node;
}

void spnp::Arc::fromXML(XMLNode *xml)
{
    AbstractData::fromXML(xml);
    this->place = xml->getAttributeS("place");
    this->transition = xml->getAttributeS("transition");
    this->fromPlaceToTransition = xml->getAttributeB("ptot");
    this->multiplicity = xml->getAttributeS("multiplicity");
    this->isFluid = xml->getAttributeB("fluid");
    this->isInhibitor = xml->getAttributeB("inhibitor");
    this->isConstant = xml->getAttributeB("const");
}

std::string spnp::Arc::getPlaceId() const
{
    return this->place;
}

std::string spnp::Arc::getTransitionId() const
{
    return this->transition;
}

bool spnp::Arc::getFromPlaceToTransition() const
{
    return this->fromPlaceToTransition;
}

std::string spnp::Arc::getMultiplicity() const
{
    return this->multiplicity;
}

bool spnp::Arc::getIsFluid() const
{
    return this->isFluid;
}

bool spnp::Arc::getIsInhibitor() const
{
    return this->isInhibitor;
}

bool spnp::Arc::getIsConstant() const
{
    return this->isConstant;
}

void spnp::Arc::setPlace(const std::string id)
{
    this->place = id;
}

void spnp::Arc::setTransition(const std::string id)
{
    this->transition = id;
}

void spnp::Arc::setFromPlaceToTransition(const bool b)
{
    this->fromPlaceToTransition = b;
}

void spnp::Arc::setMultiplicity(const std::string m)
{
    this->multiplicity = m;
}

void spnp::Arc::setIsFluid(const bool b)
{
    this->isFluid = b;
}

void spnp::Arc::setIsInhibitor(const bool b)
{
    this->isInhibitor = b;
}

void spnp::Arc::setIsConstant(const bool b)
{
    this->isConstant = b;
}

std::string spnp::Arc::c_str(IData *data) const
{
    (void)data;
    std::stringstream ss;

    spnp::Net* net = static_cast<Net*>(data);

    if(this->fromPlaceToTransition)
    {
        if(this->multiplicity.compare("1")!=0)
            ss << "oarc(\"" << net->getTransition(transition)->getName() << "\", \"" << net->getPlace(place)->getName() << "\");\n";
        else
            ss << "moarc(\"" << net->getTransition(transition)->getName() << "\", \"" << net->getPlace(place)->getName() << "\", " << this->multiplicity <<");\n";

    }
    else
    {
        if(this->multiplicity.compare("1")!=0)
            ss << "iarc(\"" << net->getTransition(transition)->getName() << "\", \"" << net->getPlace(place)->getName() << "\");\n";
        else
            ss << "iarc(\"" << net->getTransition(transition)->getName() << "\", \"" << net->getPlace(place)->getName() << "\", " << this->multiplicity <<");\n";
    }

    return ss.str();
}

std::string spnp::Arc::getClassNodeName()
{
    return "arc";
}
<commit_msg>arc -> cspn fix<commit_after>#include "arc.h"

#include "objs/net.h"

spnp::Arc::Arc():AbstractData()
{
    this->place = -1;
    this->transition = -1;
    this->fromPlaceToTransition = false;
    this->multiplicity = "1";
    this->isFluid = false;
    this->isInhibitor = false;
}

spnp::Arc::Arc(std::string name, std::string place,
               std::string transition, bool fromPlaceToTransition,
               std::string multiplicity, bool isFluid, bool isInhibitor, bool isConstant):AbstractData(name)
{
    this->place = place;
    this->transition = transition;
    this->fromPlaceToTransition = fromPlaceToTransition;
    this->multiplicity = multiplicity;
    this->isFluid = isFluid;
    this->isInhibitor = isInhibitor;
    this->isConstant = isConstant;
}

spnp::Arc::~Arc()
{

}

XMLNode *spnp::Arc::toXML()
{
    XMLNode* node = AbstractData::toXML();
    node->setAttribute("place", this->place);
    node->setAttribute("transition", this->transition);
    node->setAttribute("ptot", this->fromPlaceToTransition);
    node->setAttribute("multiplicity", this->multiplicity);
    node->setAttribute("fluid", this->isFluid);
    node->setAttribute("inhibitor", this->isInhibitor);
    node->setAttribute("const", this->isConstant);
    return node;
}

void spnp::Arc::fromXML(XMLNode *xml)
{
    AbstractData::fromXML(xml);
    this->place = xml->getAttributeS("place");
    this->transition = xml->getAttributeS("transition");
    this->fromPlaceToTransition = xml->getAttributeB("ptot");
    this->multiplicity = xml->getAttributeS("multiplicity");
    this->isFluid = xml->getAttributeB("fluid");
    this->isInhibitor = xml->getAttributeB("inhibitor");
    this->isConstant = xml->getAttributeB("const");
}

std::string spnp::Arc::getPlaceId() const
{
    return this->place;
}

std::string spnp::Arc::getTransitionId() const
{
    return this->transition;
}

bool spnp::Arc::getFromPlaceToTransition() const
{
    return this->fromPlaceToTransition;
}

std::string spnp::Arc::getMultiplicity() const
{
    return this->multiplicity;
}

bool spnp::Arc::getIsFluid() const
{
    return this->isFluid;
}

bool spnp::Arc::getIsInhibitor() const
{
    return this->isInhibitor;
}

bool spnp::Arc::getIsConstant() const
{
    return this->isConstant;
}

void spnp::Arc::setPlace(const std::string id)
{
    this->place = id;
}

void spnp::Arc::setTransition(const std::string id)
{
    this->transition = id;
}

void spnp::Arc::setFromPlaceToTransition(const bool b)
{
    this->fromPlaceToTransition = b;
}

void spnp::Arc::setMultiplicity(const std::string m)
{
    this->multiplicity = m;
}

void spnp::Arc::setIsFluid(const bool b)
{
    this->isFluid = b;
}

void spnp::Arc::setIsInhibitor(const bool b)
{
    this->isInhibitor = b;
}

void spnp::Arc::setIsConstant(const bool b)
{
    this->isConstant = b;
}

std::string spnp::Arc::c_str(IData *data) const
{
    (void)data;
    std::stringstream ss;

    spnp::Net* net = static_cast<Net*>(data);

    if(this->fromPlaceToTransition)
    {
        if(this->multiplicity.compare("1")!=0)
            ss << "oarc(\"" << net->getTransition(transition)->getName() << "\", \"" << net->getPlace(place)->getName() << "\");\n";
        else
            ss << "moarc(\"" << net->getTransition(transition)->getName() << "\", \"" << net->getPlace(place)->getName() << "\", " << this->multiplicity <<");\n";

    }
    else
    {
        if(this->multiplicity.compare("1")!=0)
            ss << "iarc(\"" << net->getTransition(transition)->getName() << "\", \"" << net->getPlace(place)->getName() << "\");\n";
        else
            ss << "miarc(\"" << net->getTransition(transition)->getName() << "\", \"" << net->getPlace(place)->getName() << "\", " << this->multiplicity <<");\n";
    }

    return ss.str();
}

std::string spnp::Arc::getClassNodeName()
{
    return "arc";
}
<|endoftext|>


<commit_before>//
//  WOZ.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 23/04/2018.
//  Copyright 2018 Thomas Harte. All rights reserved.
//

#include "WOZ.hpp"

#include "../../Track/PCMTrack.hpp"

using namespace Storage::Disk;

WOZ::WOZ(const std::string &file_name) :
	file_(file_name) {

	const char signature[8] = {
		'W', 'O', 'Z', '1',
		static_cast<char>(0xff), 0x0a, 0x0d, 0x0a
	};
	if(!file_.check_signature(signature, 8)) throw Error::InvalidFormat;

	// TODO: check CRC32, instead of skipping it.
	file_.seek(4, SEEK_CUR);

	// Parse all chunks up front.
	bool has_tmap = false;
	while(true) {
		const uint32_t chunk_id = file_.get32le();
		const uint32_t chunk_size = file_.get32le();
		if(file_.eof()) break;

		long end_of_chunk = file_.tell() + static_cast<long>(chunk_size);

		#define CK(str) (str[0] | (str[1] << 8) | (str[2] << 16) | (str[3] << 24))
		switch(chunk_id) {
			case CK("INFO"): {
				const uint8_t version = file_.get8();
				if(version != 1) break;
				is_3_5_disk_ = file_.get8() == 2;
				is_read_only_ = file_.get8() == 1;
				/* Ignored:
					1 byte: Synchronized; 1 = Cross track sync was used during imaging.
					1 byte: Cleaned; 1 = MC3470 fake bits have been removed.
					32 bytes: Cretor; a UTF-8 string.
				*/
			} break;

			case CK("TMAP"): {
				file_.read(track_map_, 160);
				has_tmap = true;
			} break;

			case CK("TRKS"): {
				tracks_offset_ = file_.tell();
			} break;

			// TODO: parse META chunks.

			default:
			break;
		}
		#undef CK

		file_.seek(end_of_chunk, SEEK_SET);
	}

	if(tracks_offset_ == -1 || !has_tmap) throw Error::InvalidFormat;
}

HeadPosition WOZ::get_maximum_head_position() {
	return is_3_5_disk_ ? HeadPosition(80) : HeadPosition(160, 4);
}

int WOZ::get_head_count() {
	return is_3_5_disk_ ? 2 : 1;
}

std::shared_ptr<Track> WOZ::get_track_at_position(Track::Address address) {
	// Calculate table position; if this track is defined to be unformatted, return no track.
	const int table_position = address.head * (is_3_5_disk_ ? 80 : 160) + (is_3_5_disk_ ? address.position.as_int() : address.position.as_quarter());
	if(track_map_[table_position] == 0xff) return nullptr;

	// Seek to the real track.
	file_.seek(tracks_offset_ + track_map_[table_position] * 6656, SEEK_SET);

	PCMSegment track_contents;
	track_contents.data = file_.read(6646);
	track_contents.data.resize(file_.get16le());
	track_contents.number_of_bits = file_.get16le();

	const uint16_t splice_point = file_.get16le();
	if(splice_point != 0xffff) {
		// TODO: expand track from splice_point?
	}

	return std::shared_ptr<PCMTrack>(new PCMTrack(track_contents));
}
<commit_msg>Adds WOZ CRC checking.<commit_after>//
//  WOZ.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 23/04/2018.
//  Copyright 2018 Thomas Harte. All rights reserved.
//

#include "WOZ.hpp"

#include "../../Track/PCMTrack.hpp"
#include "../../../../NumberTheory/CRC.hpp"

using namespace Storage::Disk;

WOZ::WOZ(const std::string &file_name) :
	file_(file_name) {

	const char signature[8] = {
		'W', 'O', 'Z', '1',
		static_cast<char>(0xff), 0x0a, 0x0d, 0x0a
	};
	if(!file_.check_signature(signature, 8)) throw Error::InvalidFormat;

	// Check the file's CRC32, instead of skipping it.
	const uint32_t crc = file_.get32le();
	CRC::CRC32 crc_generator;
	while(true) {
		uint8_t next = file_.get8();
		if(file_.eof()) break;
		crc_generator.add(next);
	}
	if(crc != crc_generator.get_value()) {
		 throw Error::InvalidFormat;
	}

	// Retreat to the first byte after the CRC.
	file_.seek(12, SEEK_SET);

	// Parse all chunks up front.
	bool has_tmap = false;
	while(true) {
		const uint32_t chunk_id = file_.get32le();
		const uint32_t chunk_size = file_.get32le();
		if(file_.eof()) break;

		long end_of_chunk = file_.tell() + static_cast<long>(chunk_size);

		#define CK(str) (str[0] | (str[1] << 8) | (str[2] << 16) | (str[3] << 24))
		switch(chunk_id) {
			case CK("INFO"): {
				const uint8_t version = file_.get8();
				if(version != 1) break;
				is_3_5_disk_ = file_.get8() == 2;
				is_read_only_ = file_.get8() == 1;
				/* Ignored:
					1 byte: Synchronized; 1 = Cross track sync was used during imaging.
					1 byte: Cleaned; 1 = MC3470 fake bits have been removed.
					32 bytes: Cretor; a UTF-8 string.
				*/
			} break;

			case CK("TMAP"): {
				file_.read(track_map_, 160);
				has_tmap = true;
			} break;

			case CK("TRKS"): {
				tracks_offset_ = file_.tell();
			} break;

			// TODO: parse META chunks.

			default:
			break;
		}
		#undef CK

		file_.seek(end_of_chunk, SEEK_SET);
	}

	if(tracks_offset_ == -1 || !has_tmap) throw Error::InvalidFormat;
}

HeadPosition WOZ::get_maximum_head_position() {
	return is_3_5_disk_ ? HeadPosition(80) : HeadPosition(160, 4);
}

int WOZ::get_head_count() {
	return is_3_5_disk_ ? 2 : 1;
}

std::shared_ptr<Track> WOZ::get_track_at_position(Track::Address address) {
	// Calculate table position; if this track is defined to be unformatted, return no track.
	const int table_position = address.head * (is_3_5_disk_ ? 80 : 160) + (is_3_5_disk_ ? address.position.as_int() : address.position.as_quarter());
	if(track_map_[table_position] == 0xff) return nullptr;

	// Seek to the real track.
	file_.seek(tracks_offset_ + track_map_[table_position] * 6656, SEEK_SET);

	PCMSegment track_contents;
	track_contents.data = file_.read(6646);
	track_contents.data.resize(file_.get16le());
	track_contents.number_of_bits = file_.get16le();

	const uint16_t splice_point = file_.get16le();
	if(splice_point != 0xffff) {
		// TODO: expand track from splice_point?
	}

	return std::shared_ptr<PCMTrack>(new PCMTrack(track_contents));
}
<|endoftext|>


<commit_before>/*
Highly Optimized Object-oriented Many-particle Dynamics -- Blue Edition
(HOOMD-blue) Open Source Software License Copyright 2009-2014 The Regents of
the University of Michigan All rights reserved.

HOOMD-blue may contain modifications ("Contributions") provided, and to which
copyright is held, by various Contributors who have granted The Regents of the
University of Michigan the right to modify and/or distribute such Contributions.

You may redistribute, use, and create derivate works of HOOMD-blue, in source
and binary forms, provided you abide by the following conditions:

* Redistributions of source code must retain the above copyright notice, this
list of conditions, and the following disclaimer both in the code and
prominently in any materials provided with the distribution.

* 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.

* All publications and presentations based on HOOMD-blue, including any reports
or published results obtained, in whole or in part, with HOOMD-blue, will
acknowledge its use according to the terms posted at the time of submission on:
http://codeblue.umich.edu/hoomd-blue/citations.html

* Any electronic documents citing HOOMD-Blue will link to the HOOMD-Blue website:
http://codeblue.umich.edu/hoomd-blue/

* Apart from the above required attributions, neither the name of the copyright
holder nor the names of HOOMD-blue's contributors may be used to endorse or
promote products derived from this software without specific prior written
permission.

Disclaimer

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND/OR ANY
WARRANTIES THAT THIS SOFTWARE IS FREE OF INFRINGEMENT ARE DISCLAIMED.

IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
*/

// Maintainer: joaander

/*! \file Messenger.cc
    \brief Defines the Messenger class
*/

#include "ExecutionConfiguration.h"
#include "Messenger.h"

#ifdef ENABLE_MPI
#include "HOOMDMPI.h"
#endif

#include <assert.h>
using namespace std;

#include <boost/python.hpp>

using namespace boost::python;

/*! \post Warning and error streams are set to cerr
    \post The notice stream is set to cout
    \post The notice level is set to 2
    \post prefixes are "error!!!!" , "warning!!" and "notice"
*/
Messenger::Messenger()
    {
    m_err_stream = &cerr;
    m_warning_stream = &cerr;
    m_notice_stream = &cout;
    m_nullstream = boost::shared_ptr<nullstream>(new nullstream());
    m_notice_level = 2;
    m_err_prefix     = "**ERROR**";
    m_warning_prefix = "*Warning*";
    m_notice_prefix  = "notice";

#ifdef ENABLE_MPI
    // initial value
    m_mpi_comm = MPI_COMM_WORLD;
    m_error_flag = NULL;
    m_has_lock = false;
    initializeSharedMem();
    m_shared_filename = "";
#endif

    // preliminarily initialize rank and partiton
    #ifdef ENABLE_MPI
    setRank(ExecutionConfiguration::getRankGlobal(),0);
    #else
    setRank(0,0);
    #endif
    }

Messenger::Messenger(const Messenger& msg)
    {
    m_err_stream = msg.m_err_stream;
    m_warning_stream = msg.m_warning_stream;
    m_notice_stream = msg.m_notice_stream;
    m_nullstream = msg.m_nullstream;
    m_file = msg.m_file;
    m_err_prefix = msg.m_err_prefix;
    m_warning_prefix = msg.m_warning_prefix;
    m_notice_prefix = msg.m_notice_prefix;
    m_notice_level = msg.m_notice_level;

    m_rank = msg.m_rank;
    m_partition = msg.m_partition;
    m_nranks = msg.m_nranks;

    #ifdef ENABLE_MPI
    m_shared_filename = msg.m_shared_filename;
    m_mpi_comm = msg.m_mpi_comm;
    m_error_flag = NULL;
    m_has_lock = false;
    initializeSharedMem();
    #endif
    }

Messenger& Messenger::operator=(Messenger& msg)
    {
    #ifdef ENABLE_MPI
    releaseSharedMem();
    #endif

    m_err_stream = msg.m_err_stream;
    m_warning_stream = msg.m_warning_stream;
    m_notice_stream = msg.m_notice_stream;
    m_nullstream = msg.m_nullstream;
    m_file = msg.m_file;
    m_err_prefix = msg.m_err_prefix;
    m_warning_prefix = msg.m_warning_prefix;
    m_notice_prefix = msg.m_notice_prefix;
    m_notice_level = msg.m_notice_level;

    m_rank = msg.m_rank;
    m_partition = msg.m_partition;
    m_nranks = msg.m_nranks;

    #ifdef ENABLE_MPI
    m_shared_filename = msg.m_shared_filename;
    m_mpi_comm = msg.m_mpi_comm;
    m_error_flag = NULL;
    m_has_lock = false;
    initializeSharedMem();
    #endif

    return *this;
    }

Messenger::~Messenger()
    {
    // set pointers to NULL
    m_err_stream = NULL;
    m_warning_stream = NULL;
    m_notice_stream = NULL;

    #ifdef ENABLE_MPI
    releaseSharedMem();
    #endif
    }

/*! \returns The error stream for use in printing error messages
    \post If the error prefix is not the empty string, the message is preceded with
    "${error_prefix}: ".
*/
std::ostream& Messenger::error() const
    {
    assert(m_err_stream);
    #ifdef ENABLE_MPI
    assert(m_error_flag);
    if (m_nranks > 1)
        {
        int one = 1;
        int flag;
        // atomically increment flag
        MPI_Win_lock(MPI_LOCK_EXCLUSIVE, 0,0, m_mpi_win);
        MPI_Accumulate(&one, 1, MPI_INT, 0, 0, 1, MPI_INT, MPI_SUM, m_mpi_win);
        MPI_Get(&flag, 1, MPI_INT, 0, 0, 1, MPI_INT, m_mpi_win);
        MPI_Win_unlock(0, m_mpi_win);

        // we have access to stdout if we are the first process to access the counter
        m_has_lock = m_has_lock || (flag == 1);

        // if we do not have exclusive access to stdout, return NULL stream
        if (! m_has_lock) return *m_nullstream;
        }
    #endif
    if (m_err_prefix != string(""))
        *m_err_stream << m_err_prefix << ": ";
    if (m_nranks > 1)
        *m_err_stream << " (Rank " << m_rank << "): ";
    return *m_err_stream;
    }

/*! \param msg Message to print
    \sa error()
*/
void Messenger::errorStr(const std::string& msg) const
    {
    error() << msg;
    }

/*! \returns The warning stream for use in printing warning messages
    \post If the warning prefix is not the empty string, the message is preceded with
    "${warning_prefix}: ".
*/
std::ostream& Messenger::warning() const
    {
    assert(m_warning_stream);
    if (m_warning_prefix != string(""))
        *m_warning_stream << m_warning_prefix << ": ";
   if (m_nranks > 1)
        *m_err_stream << " (Rank " << m_rank << "): ";
    return *m_warning_stream;
    }

/*! \param msg Message to print
    \sa warning()
*/
void Messenger::warningStr(const std::string& msg) const
    {
    warning() << msg;
    }

/*! \returns The notice stream for use in printing notice messages
    \post If the notice prefix is not the empty string and the level is greater than 1 the message is preceded with
    "${notice_prefix}(n): ".

    If level is greater than the notice level, a null stream is returned so that the output is not printed.
*/
std::ostream& Messenger::notice(unsigned int level) const
    {
    assert(m_notice_stream);
    if (level <= m_notice_level)
        {
        if (m_notice_prefix != string("") && level > 1)
            *m_notice_stream << m_notice_prefix << "(" << level << "): ";
        return *m_notice_stream;
        }
    else
        {
        return *m_nullstream;
        }
    }

/*! Outputs the the collective notice string on the processor with rank zero, in rank order.

 \param level The notice level
 \param msg Content of the notice
 */
void Messenger::collectiveNoticeStr(unsigned int level, const std::string& msg) const
    {
    std::vector<std::string> rank_notices;

    #ifdef ENABLE_MPI
    gather_v(msg, rank_notices, 0, m_mpi_comm);
    #else
    rank_notices.push_back(msg);
    #endif

    #ifdef ENABLE_MPI
    if (m_rank == 0)
        {
        if (rank_notices.size() > 1)
            {
            // Output notices in rank order, combining similar ones
            std::vector<std::string>::iterator notice_it;
            std::string last_msg = rank_notices[0];
            int last_output_rank = -1;
            for (notice_it = rank_notices.begin(); notice_it != rank_notices.end() + 1; notice_it++)
                {
                if (notice_it == rank_notices.end() || *notice_it != last_msg)
                    {
                    int rank = notice_it - rank_notices.begin();
                    // output message for accumulated ranks
                    if (last_output_rank+1 == rank-1)
                        notice(level) << "Rank " << last_output_rank + 1 << ": " << last_msg;
                    else
                        notice(level) << "Ranks " << last_output_rank + 1 << "-" << rank-1 << ": " << last_msg;

                    if (notice_it != rank_notices.end())
                        {
                        last_msg = *notice_it;
                        last_output_rank = rank-1;
                        }
                    }
                }
            }
        else
    #endif
            {
            // output without prefix
            notice(level) << rank_notices[0];
            }
    #ifdef ENABLE_MPI
        }
    #endif
    }

/*! \param level Notice level
    \param msg Message to print
    \sa notice()
*/
void Messenger::noticeStr(unsigned int level, const std::string& msg) const
    {
    notice(level) << msg;
    }

/*! \param fname File name
    The file is ovewritten if it exists. If there is an error opening the file, all level's streams are left
    as is and an error() is issued.
*/
void Messenger::openFile(const std::string& fname)
    {
    m_file = boost::shared_ptr<std::ostream>(new ofstream(fname.c_str()));
    m_err_stream = m_file.get();
    m_warning_stream = m_file.get();
    m_notice_stream = m_file.get();
    }

#ifdef ENABLE_MPI
/*! Open a shared file for error, warning, and notice streams

    A suffix .rank (where rank is the partition number)
    is appended to the filename
*/
void Messenger::openSharedFile()
    {
    std::ostringstream oss;
    oss << m_shared_filename << "." << m_partition;
    boost::iostreams::stream<mpi_io> *mpi_ios = new boost::iostreams::stream<mpi_io>((const MPI_Comm&) m_mpi_comm, oss.str());

    // now update the error, warning, and notice streams
    m_file = boost::shared_ptr<std::ostream>(mpi_ios);
    m_err_stream = m_file.get();
    m_warning_stream = m_file.get();
    m_notice_stream = m_file.get();
    }
#endif

/*! Any open file is closed. stdout is opened again for notices and stderr for warnings and errors.
*/
void Messenger::openStd()
    {
    m_file = boost::shared_ptr<std::ostream>();
    m_err_stream = &cerr;
    m_warning_stream = &cerr;
    m_notice_stream = &cout;
    }

#ifdef ENABLE_MPI
/*! \param filename The output filename
    \param mpi_comm The MPI communicator to use for MPI file IO
 */
mpi_io::mpi_io(const MPI_Comm& mpi_comm, const std::string& filename)
    : m_mpi_comm(mpi_comm),  m_file_open(false)
    {
    assert(m_mpi_comm);

    unsigned int len = filename.size();
    char cfilename[len+1];
    filename.copy(cfilename,len);
    cfilename[len] = '\0';

    // overwrite old file
    MPI_File_delete(cfilename, MPI_INFO_NULL);

    // open the log file
    int ret = MPI_File_open(m_mpi_comm, cfilename,  MPI_MODE_CREATE | MPI_MODE_WRONLY | MPI_MODE_UNIQUE_OPEN, MPI_INFO_NULL, &m_file);

    if (ret == 0)
        m_file_open = true;
    }

std::streamsize mpi_io::write(const char *s,  std::streamsize n)
    {
    assert(m_file_open);

    char out_data[n];
    strncpy(out_data, s, n);

    // write value to log file using MPI-IO
    MPI_Status status;
    MPI_File_write_shared(m_file, out_data, n, MPI_CHAR, &status);
    return n;
    }

void mpi_io::close()
    {
    if (m_file_open)
        MPI_File_close(&m_file);

    m_file_open = false;
    }

void Messenger::initializeSharedMem()
    {
    // allocate memory for counter
    MPI_Alloc_mem(sizeof(int), MPI_INFO_NULL, &m_error_flag);

    // reset to zero
    *m_error_flag = 0;

    // create window for exclusive access to the error stream
    MPI_Win_create(m_error_flag, sizeof(int), sizeof(int), MPI_INFO_NULL, m_mpi_comm, &m_mpi_win);
    }

void Messenger::releaseSharedMem()
    {
    MPI_Win_free(&m_mpi_win);
    MPI_Free_mem(m_error_flag);
    }

#endif

void export_Messenger()
    {
    class_<Messenger, boost::shared_ptr<Messenger>, boost::noncopyable >
         ("Messenger", init< >())
         .def("error", &Messenger::errorStr)
         .def("warning", &Messenger::warningStr)
         .def("notice", &Messenger::noticeStr)
         .def("getNoticeLevel", &Messenger::getNoticeLevel)
         .def("setNoticeLevel", &Messenger::setNoticeLevel)
         .def("getErrorPrefix", &Messenger::getErrorPrefix, return_value_policy<copy_const_reference>())
         .def("setErrorPrefix", &Messenger::setErrorPrefix)
         .def("getWarningPrefix", &Messenger::getWarningPrefix, return_value_policy<copy_const_reference>())
         .def("setWarningPrefix", &Messenger::setWarningPrefix)
         .def("getNoticePrefix", &Messenger::getNoticePrefix, return_value_policy<copy_const_reference>())
         .def("setWarningPrefix", &Messenger::setWarningPrefix)
         .def("openFile", &Messenger::openFile)
#ifdef ENABLE_MPI
         .def("setSharedFile", &Messenger::setSharedFile)
#endif
         .def("openStd", &Messenger::openStd)
         ;
    }
<commit_msg>Suppress warnings on non-zero ranks<commit_after>/*
Highly Optimized Object-oriented Many-particle Dynamics -- Blue Edition
(HOOMD-blue) Open Source Software License Copyright 2009-2014 The Regents of
the University of Michigan All rights reserved.

HOOMD-blue may contain modifications ("Contributions") provided, and to which
copyright is held, by various Contributors who have granted The Regents of the
University of Michigan the right to modify and/or distribute such Contributions.

You may redistribute, use, and create derivate works of HOOMD-blue, in source
and binary forms, provided you abide by the following conditions:

* Redistributions of source code must retain the above copyright notice, this
list of conditions, and the following disclaimer both in the code and
prominently in any materials provided with the distribution.

* 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.

* All publications and presentations based on HOOMD-blue, including any reports
or published results obtained, in whole or in part, with HOOMD-blue, will
acknowledge its use according to the terms posted at the time of submission on:
http://codeblue.umich.edu/hoomd-blue/citations.html

* Any electronic documents citing HOOMD-Blue will link to the HOOMD-Blue website:
http://codeblue.umich.edu/hoomd-blue/

* Apart from the above required attributions, neither the name of the copyright
holder nor the names of HOOMD-blue's contributors may be used to endorse or
promote products derived from this software without specific prior written
permission.

Disclaimer

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND/OR ANY
WARRANTIES THAT THIS SOFTWARE IS FREE OF INFRINGEMENT ARE DISCLAIMED.

IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
*/

// Maintainer: joaander

/*! \file Messenger.cc
    \brief Defines the Messenger class
*/

#include "ExecutionConfiguration.h"
#include "Messenger.h"

#ifdef ENABLE_MPI
#include "HOOMDMPI.h"
#endif

#include <assert.h>
using namespace std;

#include <boost/python.hpp>

using namespace boost::python;

/*! \post Warning and error streams are set to cerr
    \post The notice stream is set to cout
    \post The notice level is set to 2
    \post prefixes are "error!!!!" , "warning!!" and "notice"
*/
Messenger::Messenger()
    {
    m_err_stream = &cerr;
    m_warning_stream = &cerr;
    m_notice_stream = &cout;
    m_nullstream = boost::shared_ptr<nullstream>(new nullstream());
    m_notice_level = 2;
    m_err_prefix     = "**ERROR**";
    m_warning_prefix = "*Warning*";
    m_notice_prefix  = "notice";

#ifdef ENABLE_MPI
    // initial value
    m_mpi_comm = MPI_COMM_WORLD;
    m_error_flag = NULL;
    m_has_lock = false;
    initializeSharedMem();
    m_shared_filename = "";
#endif

    // preliminarily initialize rank and partiton
    #ifdef ENABLE_MPI
    setRank(ExecutionConfiguration::getRankGlobal(),0);
    #else
    setRank(0,0);
    #endif
    }

Messenger::Messenger(const Messenger& msg)
    {
    m_err_stream = msg.m_err_stream;
    m_warning_stream = msg.m_warning_stream;
    m_notice_stream = msg.m_notice_stream;
    m_nullstream = msg.m_nullstream;
    m_file = msg.m_file;
    m_err_prefix = msg.m_err_prefix;
    m_warning_prefix = msg.m_warning_prefix;
    m_notice_prefix = msg.m_notice_prefix;
    m_notice_level = msg.m_notice_level;

    m_rank = msg.m_rank;
    m_partition = msg.m_partition;
    m_nranks = msg.m_nranks;

    #ifdef ENABLE_MPI
    m_shared_filename = msg.m_shared_filename;
    m_mpi_comm = msg.m_mpi_comm;
    m_error_flag = NULL;
    m_has_lock = false;
    initializeSharedMem();
    #endif
    }

Messenger& Messenger::operator=(Messenger& msg)
    {
    #ifdef ENABLE_MPI
    releaseSharedMem();
    #endif

    m_err_stream = msg.m_err_stream;
    m_warning_stream = msg.m_warning_stream;
    m_notice_stream = msg.m_notice_stream;
    m_nullstream = msg.m_nullstream;
    m_file = msg.m_file;
    m_err_prefix = msg.m_err_prefix;
    m_warning_prefix = msg.m_warning_prefix;
    m_notice_prefix = msg.m_notice_prefix;
    m_notice_level = msg.m_notice_level;

    m_rank = msg.m_rank;
    m_partition = msg.m_partition;
    m_nranks = msg.m_nranks;

    #ifdef ENABLE_MPI
    m_shared_filename = msg.m_shared_filename;
    m_mpi_comm = msg.m_mpi_comm;
    m_error_flag = NULL;
    m_has_lock = false;
    initializeSharedMem();
    #endif

    return *this;
    }

Messenger::~Messenger()
    {
    // set pointers to NULL
    m_err_stream = NULL;
    m_warning_stream = NULL;
    m_notice_stream = NULL;

    #ifdef ENABLE_MPI
    releaseSharedMem();
    #endif
    }

/*! \returns The error stream for use in printing error messages
    \post If the error prefix is not the empty string, the message is preceded with
    "${error_prefix}: ".
*/
std::ostream& Messenger::error() const
    {
    assert(m_err_stream);
    #ifdef ENABLE_MPI
    assert(m_error_flag);
    if (m_nranks > 1)
        {
        int one = 1;
        int flag;
        // atomically increment flag
        MPI_Win_lock(MPI_LOCK_EXCLUSIVE, 0,0, m_mpi_win);
        MPI_Accumulate(&one, 1, MPI_INT, 0, 0, 1, MPI_INT, MPI_SUM, m_mpi_win);
        MPI_Get(&flag, 1, MPI_INT, 0, 0, 1, MPI_INT, m_mpi_win);
        MPI_Win_unlock(0, m_mpi_win);

        // we have access to stdout if we are the first process to access the counter
        m_has_lock = m_has_lock || (flag == 1);

        // if we do not have exclusive access to stdout, return NULL stream
        if (! m_has_lock) return *m_nullstream;
        }
    #endif
    if (m_err_prefix != string(""))
        *m_err_stream << m_err_prefix << ": ";
    if (m_nranks > 1)
        *m_err_stream << " (Rank " << m_rank << "): ";
    return *m_err_stream;
    }

/*! \param msg Message to print
    \sa error()
*/
void Messenger::errorStr(const std::string& msg) const
    {
    error() << msg;
    }

/*! \returns The warning stream for use in printing warning messages
    \post If the warning prefix is not the empty string, the message is preceded with
    "${warning_prefix}: ".
*/
std::ostream& Messenger::warning() const
    {
    if (m_rank != 0) return *m_nullstream;

    assert(m_warning_stream);
    if (m_warning_prefix != string(""))
        *m_warning_stream << m_warning_prefix << ": ";
    return *m_warning_stream;
    }

/*! \param msg Message to print
    \sa warning()
*/
void Messenger::warningStr(const std::string& msg) const
    {
    warning() << msg;
    }

/*! \returns The notice stream for use in printing notice messages
    \post If the notice prefix is not the empty string and the level is greater than 1 the message is preceded with
    "${notice_prefix}(n): ".

    If level is greater than the notice level, a null stream is returned so that the output is not printed.
*/
std::ostream& Messenger::notice(unsigned int level) const
    {
    assert(m_notice_stream);
    if (level <= m_notice_level)
        {
        if (m_notice_prefix != string("") && level > 1)
            *m_notice_stream << m_notice_prefix << "(" << level << "): ";
        return *m_notice_stream;
        }
    else
        {
        return *m_nullstream;
        }
    }

/*! Outputs the the collective notice string on the processor with rank zero, in rank order.

 \param level The notice level
 \param msg Content of the notice
 */
void Messenger::collectiveNoticeStr(unsigned int level, const std::string& msg) const
    {
    std::vector<std::string> rank_notices;

    #ifdef ENABLE_MPI
    gather_v(msg, rank_notices, 0, m_mpi_comm);
    #else
    rank_notices.push_back(msg);
    #endif

    #ifdef ENABLE_MPI
    if (m_rank == 0)
        {
        if (rank_notices.size() > 1)
            {
            // Output notices in rank order, combining similar ones
            std::vector<std::string>::iterator notice_it;
            std::string last_msg = rank_notices[0];
            int last_output_rank = -1;
            for (notice_it = rank_notices.begin(); notice_it != rank_notices.end() + 1; notice_it++)
                {
                if (notice_it == rank_notices.end() || *notice_it != last_msg)
                    {
                    int rank = notice_it - rank_notices.begin();
                    // output message for accumulated ranks
                    if (last_output_rank+1 == rank-1)
                        notice(level) << "Rank " << last_output_rank + 1 << ": " << last_msg;
                    else
                        notice(level) << "Ranks " << last_output_rank + 1 << "-" << rank-1 << ": " << last_msg;

                    if (notice_it != rank_notices.end())
                        {
                        last_msg = *notice_it;
                        last_output_rank = rank-1;
                        }
                    }
                }
            }
        else
    #endif
            {
            // output without prefix
            notice(level) << rank_notices[0];
            }
    #ifdef ENABLE_MPI
        }
    #endif
    }

/*! \param level Notice level
    \param msg Message to print
    \sa notice()
*/
void Messenger::noticeStr(unsigned int level, const std::string& msg) const
    {
    notice(level) << msg;
    }

/*! \param fname File name
    The file is ovewritten if it exists. If there is an error opening the file, all level's streams are left
    as is and an error() is issued.
*/
void Messenger::openFile(const std::string& fname)
    {
    m_file = boost::shared_ptr<std::ostream>(new ofstream(fname.c_str()));
    m_err_stream = m_file.get();
    m_warning_stream = m_file.get();
    m_notice_stream = m_file.get();
    }

#ifdef ENABLE_MPI
/*! Open a shared file for error, warning, and notice streams

    A suffix .rank (where rank is the partition number)
    is appended to the filename
*/
void Messenger::openSharedFile()
    {
    std::ostringstream oss;
    oss << m_shared_filename << "." << m_partition;
    boost::iostreams::stream<mpi_io> *mpi_ios = new boost::iostreams::stream<mpi_io>((const MPI_Comm&) m_mpi_comm, oss.str());

    // now update the error, warning, and notice streams
    m_file = boost::shared_ptr<std::ostream>(mpi_ios);
    m_err_stream = m_file.get();
    m_warning_stream = m_file.get();
    m_notice_stream = m_file.get();
    }
#endif

/*! Any open file is closed. stdout is opened again for notices and stderr for warnings and errors.
*/
void Messenger::openStd()
    {
    m_file = boost::shared_ptr<std::ostream>();
    m_err_stream = &cerr;
    m_warning_stream = &cerr;
    m_notice_stream = &cout;
    }

#ifdef ENABLE_MPI
/*! \param filename The output filename
    \param mpi_comm The MPI communicator to use for MPI file IO
 */
mpi_io::mpi_io(const MPI_Comm& mpi_comm, const std::string& filename)
    : m_mpi_comm(mpi_comm),  m_file_open(false)
    {
    assert(m_mpi_comm);

    unsigned int len = filename.size();
    char cfilename[len+1];
    filename.copy(cfilename,len);
    cfilename[len] = '\0';

    // overwrite old file
    MPI_File_delete(cfilename, MPI_INFO_NULL);

    // open the log file
    int ret = MPI_File_open(m_mpi_comm, cfilename,  MPI_MODE_CREATE | MPI_MODE_WRONLY | MPI_MODE_UNIQUE_OPEN, MPI_INFO_NULL, &m_file);

    if (ret == 0)
        m_file_open = true;
    }

std::streamsize mpi_io::write(const char *s,  std::streamsize n)
    {
    assert(m_file_open);

    char out_data[n];
    strncpy(out_data, s, n);

    // write value to log file using MPI-IO
    MPI_Status status;
    MPI_File_write_shared(m_file, out_data, n, MPI_CHAR, &status);
    return n;
    }

void mpi_io::close()
    {
    if (m_file_open)
        MPI_File_close(&m_file);

    m_file_open = false;
    }

void Messenger::initializeSharedMem()
    {
    // allocate memory for counter
    MPI_Alloc_mem(sizeof(int), MPI_INFO_NULL, &m_error_flag);

    // reset to zero
    *m_error_flag = 0;

    // create window for exclusive access to the error stream
    MPI_Win_create(m_error_flag, sizeof(int), sizeof(int), MPI_INFO_NULL, m_mpi_comm, &m_mpi_win);
    }

void Messenger::releaseSharedMem()
    {
    MPI_Win_free(&m_mpi_win);
    MPI_Free_mem(m_error_flag);
    }

#endif

void export_Messenger()
    {
    class_<Messenger, boost::shared_ptr<Messenger>, boost::noncopyable >
         ("Messenger", init< >())
         .def("error", &Messenger::errorStr)
         .def("warning", &Messenger::warningStr)
         .def("notice", &Messenger::noticeStr)
         .def("getNoticeLevel", &Messenger::getNoticeLevel)
         .def("setNoticeLevel", &Messenger::setNoticeLevel)
         .def("getErrorPrefix", &Messenger::getErrorPrefix, return_value_policy<copy_const_reference>())
         .def("setErrorPrefix", &Messenger::setErrorPrefix)
         .def("getWarningPrefix", &Messenger::getWarningPrefix, return_value_policy<copy_const_reference>())
         .def("setWarningPrefix", &Messenger::setWarningPrefix)
         .def("getNoticePrefix", &Messenger::getNoticePrefix, return_value_policy<copy_const_reference>())
         .def("setWarningPrefix", &Messenger::setWarningPrefix)
         .def("openFile", &Messenger::openFile)
#ifdef ENABLE_MPI
         .def("setSharedFile", &Messenger::setSharedFile)
#endif
         .def("openStd", &Messenger::openStd)
         ;
    }
<|endoftext|>


<commit_before>/*
 * CADIOS.cpp
 *
 *  Created on: Sep 29, 2016
 *      Author: William F Godoy
 *
 */

#include <fstream>

#include "include/CADIOS.h"

namespace adios
{

//here assign default values of non-primitives
CADIOS::CADIOS( )
{ }

CADIOS::CADIOS( const std::string xmlConfigFile ):
    m_XMLConfigFile( xmlConfigFile )
{ }

CADIOS::CADIOS( const std::string xmlConfigFile, const MPI_Comm& mpiComm  ):
    m_XMLConfigFile( xmlConfigFile ),
    m_IsUsingMPI( true ),
	m_MPIComm( mpiComm )
{ }

void CADIOS::Init( )
{
    if( m_IsUsingMPI == false )
    {
        InitSerial( );
    }
    else
    {
        InitMPI( );
    }
}

void CADIOS::InitSerial( )
{
    ReadXMLConfigFile( );
}

void CADIOS::InitMPI( )
{

}

void CADIOS::ReadXMLConfigFile( )
{
    std::ifstream xmlConfigStream( m_XMLConfigFile );

    if( xmlConfigStream.good() == false ) //check file
    {
        const std::string errorMessage( "XML Config file " + m_XMLConfigFile + " could not be opened. "
                                        "Check permissions or file existence\n");
        throw std::ios_base::failure( errorMessage );
    }

}

}

<commit_msg>Updating ADIOS.cpp for MPI testing<commit_after>/*
 * ADIOS.cpp
 *
 *  Created on: Sep 29, 2016
 *      Author: William F Godoy
 *
 */

#include <fstream>
#include <iostream>

#include "ADIOS.h"

namespace adios
{

//here assign default values of non-primitives
ADIOS::ADIOS( )
{ }

ADIOS::ADIOS( const std::string xmlConfigFile ):
    m_XMLConfigFile{ xmlConfigFile }
{ }

//#ifdef USE_MPI
ADIOS::ADIOS( const std::string xmlConfigFile, const MPI_Comm& mpiComm  ):
    m_XMLConfigFile{ xmlConfigFile },
    m_IsUsingMPI{ true },
	m_MPIComm{ mpiComm }
{ }
//#endif

void ADIOS::Init( )
{
    if( m_IsUsingMPI == false && m_XMLConfigFile.empty() == false )
    {
        InitNoMPI( );
    }
    else
    {
        //#ifdef USE_MPI
        InitMPI( );
        //#endif
    }
}

void ADIOS::InitNoMPI( )
{
    ReadXMLConfigFile( );
}

//#ifdef USE_MPI
void ADIOS::InitMPI( )
{
    //here just say hello from MPI processes

    int size;
    MPI_Comm_size( *m_MPIComm, &size );

    int rank;
    MPI_Comm_rank( *m_MPIComm, &rank );

    std::cout << " Hello World from processor " << rank << "/" << size << "\n";
}
//#endif

void ADIOS::ReadXMLConfigFile( )
{
    std::ifstream xmlConfigStream( m_XMLConfigFile );

    if( xmlConfigStream.good() == false ) //check file
    {
        const std::string errorMessage( "XML Config file " + m_XMLConfigFile + " could not be opened. "
                                        "Check permissions or file existence\n");
        throw std::ios_base::failure( errorMessage );
    }
    //here fill SMetadata...

    xmlConfigStream.close();
}

} //end namespace

<|endoftext|>