<commit_before>/**
* \file      main.cc
* \brief     Program for giving an indication when a RFID card has been
* detected, a database connection has been made and a string has been encrypted
* \author    Tim IJntema, Stefan de Beer, Arco Gelderblom, Rik Honcoop, Koen de
* Groot, Ricardo Bouwman, Philippe Zwietering, Luuk Steeman, Leo Jenneskens,
* Jeremy Ruijzenaars
* \copyright Copyright (c) 2017, The R2D2 Team
* \license   See LICENSE
*/

#include "config-file-parser.hh"
#include "database-manager.hh"
#include "led-controller.hh"
#include "matrix-keypad.hh"
#include "mfrc522.hh"

#include <wiringPiSPI.h>

#include <iomanip>

int main(int argc, char **argv) {
#define USING_PIN // Comment out this rule if not using a pin code on your
    // application
    std::string ip;
    std::string username;
    std::string password;

    ConfigFileParser factory("database-config.txt");
    factory.loadDatabaseSettings(ip, username, password);

    MySql connection;

    std::cout << "Made connection to the database\n";
    wiringPiSetup();
    wiringPiSPISetup(0, 10000000); // max speed for mfrc522 is 10Mhz
    MFRC522 rfid;
    rfid.PCD_Init();

    // Keypad pinSetup
    const int keypadRow[] = {15, 16, 1, 4};
    const int keypadColumn[] = {8, 9, 7, 2};

    // Keypad objects
    MatrixKeypad keypad(keypadRow, keypadColumn, 4);

    LedController redLed(0);
    LedController greenLed(11);
    DatabaseManager information;
    information.connectTo(ip, username, password);
    information.selectDatabase("R2D2");
    while (true) {
        delay(1000);
        std::cout << "\n\nWaiting for RFID tag: \n";

        if (!rfid.PICC_IsNewCardPresent())
            continue;

        if (!rfid.PICC_ReadCardSerial())
            continue;

        std::string id;
        for (byte i = 0; i < rfid.uid.size; ++i) {
            std::stringstream ss;
            ss << std::hex << (int) rfid.uid.uidByte[i];
            std::string res(ss.str());
            id += res;
            if (i != rfid.uid.size - 1) {
                id += ' ';
            }
        }

        bool inDatabase;
        std::cout << id << " is the presented ID\n";
        if (!information.isCardInDatabase(id)) {
            std::cout << "This ID is in the database\n";
            inDatabase = 1;
        } else {
            std::cout << "This ID is NOT in the database\n";
            inDatabase = 0;
        }

#ifdef USING_PIN
        MFRC522::MIFARE_Key key = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};
        if (1 !=
            rfid.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A,
                                  (byte) 0x05, &key, &rfid.uid))
            continue;

        // read pin code
        byte bufferSize = (byte) 18;
        byte readArray[18] = {0, 0, 0, 0, 0, 0, 0, 0, 0,
                              0, 0, 0, 0, 0, 0, 0, 0, 0};
        rfid.MIFARE_Read((byte) 0x05, readArray, &bufferSize);
        std::cout << "Read array contains: \n";
        for (int i = 0; i < 18; i++) {
            std::cout << (int) readArray[i] << ' ';
        }

        // enter pin code
        std::cout << "\nInput PIN and finish with #\n";
        std::string value = keypad.getString();

        // write pin code
        byte writeArray[16] = {0, 0, 0, 0, 0, 0, 0, 0,
                               0, 0, 0, 0, 0, 0, 0, 0};
        int index = 0;
        for (auto c : value) {
            if (c > 47 && c < 58) {
                int number = c - 48;
                writeArray[index++] = (byte) number;
            }
        }
        rfid.MIFARE_Write((byte) 0x05, writeArray, (byte) 16);
        std::cout << "Write array contains: \n";
        for (int i = 0; i < 16; i++) {
            std::cout << (int) writeArray[i] << ' ';
        }

#endif
        rfid.PCD_StopCrypto1();
        if (inDatabase) {
            greenLed.blinkLed(3000);
        } else {
            redLed.blinkLed(3000);
        }
    }
}
<commit_msg>[RFID-03]: Merge branch 'feat-rfid-new' of https://github.com/R2D2-2017/R2D2-2017 into feat-rfid-new<commit_after>/**
* \file      main.cc
* \brief     Program for giving an indication when a RFID card has been
* detected, a database connection has been made and a string has been encrypted
* \author    Tim IJntema, Stefan de Beer, Arco Gelderblom, Rik Honcoop, Koen de
* Groot, Ricardo Bouwman, Philippe Zwietering, Luuk Steeman, Leo Jenneskens,
* Jeremy Ruijzenaars
* \copyright Copyright (c) 2017, The R2D2 Team
* \license   See LICENSE
*/

#include "config-file-parser.hh"
#include "database-manager.hh"
#include "led-controller.hh"
#include "matrix-keypad.hh"
#include "mfrc522.hh"

#include <wiringPiSPI.h>

#include <iomanip>
#include <string>

// Keypad pinSetup
const int keypadRow[] = {15, 16, 1, 4};
const int keypadColumn[] = {8, 9, 7, 2};

// Magic number declarations
const int redLedPin = 0;
const int greenLedPin = 11;
const int maxSpeedWiringSPI = 10000000; // max speed for mfrc522 is 10Mhz
const int keypadColumnSize = 4;
const int blockSizeWithCrc = 18;
const int blockSize = 16;
const int zeroAscii = 47;
const int nineAscii = 58;
const int blinkTime = 3000;

int main(int argc, char **argv) {

    if(argc != 2 || std::string(argv[1]) != "pin" && std::string(argv[1]) != "no-pin") {
        std::cerr << "Please only put in 'pin' or 'no-pin' as parameter, nothing else." << std::endl
                  << "Your function will then either look like './rfid pin' or './rfid no-pin'" << std::endl;
    }

    // Keypad objects
    MatrixKeypad keypad(keypadRow, keypadColumn, keypadColumnSize);

    LedController redLed(redLedPin);
    LedController greenLed(greenLedPin);

    std::string ip;
    std::string username;
    std::string password;

    ConfigFileParser factory("database-config.txt");
    factory.loadDatabaseSettings(ip, username, password);
    DatabaseManager information;
    information.connectTo(ip, username, password);
    information.selectDatabase("R2D2");

    std::cout << "Made connection to the database\n";
    wiringPiSetup();
    wiringPiSPISetup(0, maxSpeedWiringSPI);

    MFRC522 rfid;
    rfid.PCD_Init();

    while (true) {
        delay(1000);
        std::cout << "\n\nWaiting for RFID tag: \n";

        if (!rfid.PICC_IsNewCardPresent())
            continue;

        if (!rfid.PICC_ReadCardSerial())
            continue;

        std::string id;
        for (byte i = 0; i < rfid.uid.size; ++i) {
            std::stringstream ss;
            ss << std::hex << (int) rfid.uid.uidByte[i];
            id += ss.str();
            if (i != rfid.uid.size - 1) {
                id += ' ';
            }
        }

        bool inDatabase;
        std::cout << id << " is the presented ID\n";
        if (!information.isCardInDatabase(id)) {
            std::cout << "This ID is in the database\n";
            inDatabase = 1;
        } else {
            std::cout << "This ID is NOT in the database\n";
            inDatabase = 0;
        }

        if(std::string(argv[1]) == "pin") {
            MFRC522::MIFARE_Key key = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};
            if (rfid.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A,
                                      (byte) 0x05, &key, &rfid.uid) != 1)
                continue;

            // read pin code
            byte bufferSize = (byte) blockSizeWithCrc;
            byte readArray[blockSizeWithCrc] = {};
            rfid.MIFARE_Read((byte) 0x05, readArray, &bufferSize);
            std::cout << "Read array contains: \n";
            for (int i = 0; i < blockSizeWithCrc; i++) {
                std::cout << (int) readArray[i] << ' ';
            }

            // enter pin code
            std::cout << "\nInput PIN and finish with #\n";
            std::string value = keypad.getString();

            // write pin code
            byte writeArray[blockSize] = {};
            int index = 0;
            for (const auto c : value) {
                if (c > zeroAscii && c < nineAscii) {
                    int number = c - (zeroAscii+1);
                    writeArray[index++] = (byte) number;
                }
            }
            rfid.MIFARE_Write((byte) 0x05, writeArray, (byte) blockSize);
            std::cout << "Write array contains: \n";
            for (int i = 0; i < blockSize; i++) {
                std::cout << (int) writeArray[i] << ' ';
            }
        }

        rfid.PCD_StopCrypto1();
        if (inDatabase) {
            greenLed.blinkLed(blinkTime);
        } else {
            redLed.blinkLed(blinkTime);
        }
    }
}
<|endoftext|>


<commit_before>/******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2017 Baldur Karlsson
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 ******************************************************************************/

#include <arpa/inet.h>
#include "os/os_specific.h"
#include "os/posix/posix_network.h"

namespace Network
{
uint32_t Socket::GetRemoteIP() const
{
  // Android uses abstract sockets which are only "localhost" accessible
  return ntohl(MakeIP(127, 0, 0, 1));
}

Socket *CreateServerSocket(const char * /* bindaddr */, uint16_t port, int queuesize)
{
  return CreateAbstractServerSocket(port, queuesize);
}
};
<commit_msg>Remove ntohl from GetRemoteIP on android (Thanks @cnorthrop for catch)<commit_after>/******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2017 Baldur Karlsson
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 ******************************************************************************/

#include <arpa/inet.h>
#include "os/os_specific.h"
#include "os/posix/posix_network.h"

namespace Network
{
uint32_t Socket::GetRemoteIP() const
{
  // Android uses abstract sockets which are only "localhost" accessible
  return MakeIP(127, 0, 0, 1);
}

Socket *CreateServerSocket(const char * /* bindaddr */, uint16_t port, int queuesize)
{
  return CreateAbstractServerSocket(port, queuesize);
}
};
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ReportVisitor.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2007-07-09 11:56:14 $
 *
 *  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
 *
 ************************************************************************/
#include "ReportVisitor.hxx"
namespace reportdesign
{
using namespace com::sun::star;

OReportVisitor::OReportVisitor(ITraverseReport* _pTraverseReport)
                       :m_pTraverseReport(_pTraverseReport)
{
    OSL_ENSURE(m_pTraverseReport,"ReportDefintion must be not NULL!");
}
// -----------------------------------------------------------------------------
void OReportVisitor::start(const uno::Reference< report::XReportDefinition>& _xReportDefinition)
{
    OSL_ENSURE(_xReportDefinition.is(),"ReportDefinition is NULL!");
    if ( !_xReportDefinition.is() )
        return;

    m_pTraverseReport->traverseReport(_xReportDefinition);
    m_pTraverseReport->traverseReportFunctions(_xReportDefinition->getFunctions());
    if ( _xReportDefinition->getPageHeaderOn() )
        m_pTraverseReport->traversePageHeader(_xReportDefinition->getPageHeader());
    if ( _xReportDefinition->getReportHeaderOn() )
        m_pTraverseReport->traverseReportHeader(_xReportDefinition->getReportHeader());

    uno::Reference< report::XGroups > xGroups = _xReportDefinition->getGroups();
    m_pTraverseReport->traverseGroups(xGroups);
    const sal_Int32 nCount = xGroups->getCount();
    sal_Int32 i = 0;
    for (;i<nCount ; ++i)
    {
        uno::Reference< report::XGroup > xGroup(xGroups->getByIndex(i),uno::UNO_QUERY);
        m_pTraverseReport->traverseGroup(xGroup);
        m_pTraverseReport->traverseGroupFunctions(xGroup->getFunctions());
        if ( xGroup->getHeaderOn() )
            m_pTraverseReport->traverseGroupHeader(xGroup->getHeader());
    }

    m_pTraverseReport->traverseDetail(_xReportDefinition->getDetail());

    for (i = 0;i<nCount ; ++i)
    {
        uno::Reference< report::XGroup > xGroup(xGroups->getByIndex(i),uno::UNO_QUERY);
        if ( xGroup->getFooterOn() )
            m_pTraverseReport->traverseGroupFooter(xGroup->getFooter());
    }

    if ( _xReportDefinition->getPageFooterOn() )
        m_pTraverseReport->traversePageFooter(_xReportDefinition->getPageFooter());
    if ( _xReportDefinition->getReportFooterOn() )
        m_pTraverseReport->traverseReportFooter(_xReportDefinition->getReportFooter());
}
// -----------------------------------------------------------------------------
void OReportVisitor::start(const uno::Reference< report::XGroup>& _xGroup)
{
    OSL_ENSURE(_xGroup.is(),"Group is NULL!");
    if ( !_xGroup.is() )
        return;
    m_pTraverseReport->traverseGroup(_xGroup);
    m_pTraverseReport->traverseGroupFunctions(_xGroup->getFunctions());
    if ( _xGroup->getHeaderOn() )
        m_pTraverseReport->traverseGroupHeader(_xGroup->getHeader());
    if ( _xGroup->getFooterOn() )
        m_pTraverseReport->traverseGroupFooter(_xGroup->getFooter());
}
// =============================================================================
} // namespace reportdesign
// =============================================================================
<commit_msg>INTEGRATION: CWS changefileheader (1.2.104); FILE MERGED 2008/03/31 13:32:01 rt 1.2.104.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: ReportVisitor.cxx,v $
 * $Revision: 1.3 $
 *
 * 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.
 *
 ************************************************************************/
#include "ReportVisitor.hxx"
namespace reportdesign
{
using namespace com::sun::star;

OReportVisitor::OReportVisitor(ITraverseReport* _pTraverseReport)
                       :m_pTraverseReport(_pTraverseReport)
{
    OSL_ENSURE(m_pTraverseReport,"ReportDefintion must be not NULL!");
}
// -----------------------------------------------------------------------------
void OReportVisitor::start(const uno::Reference< report::XReportDefinition>& _xReportDefinition)
{
    OSL_ENSURE(_xReportDefinition.is(),"ReportDefinition is NULL!");
    if ( !_xReportDefinition.is() )
        return;

    m_pTraverseReport->traverseReport(_xReportDefinition);
    m_pTraverseReport->traverseReportFunctions(_xReportDefinition->getFunctions());
    if ( _xReportDefinition->getPageHeaderOn() )
        m_pTraverseReport->traversePageHeader(_xReportDefinition->getPageHeader());
    if ( _xReportDefinition->getReportHeaderOn() )
        m_pTraverseReport->traverseReportHeader(_xReportDefinition->getReportHeader());

    uno::Reference< report::XGroups > xGroups = _xReportDefinition->getGroups();
    m_pTraverseReport->traverseGroups(xGroups);
    const sal_Int32 nCount = xGroups->getCount();
    sal_Int32 i = 0;
    for (;i<nCount ; ++i)
    {
        uno::Reference< report::XGroup > xGroup(xGroups->getByIndex(i),uno::UNO_QUERY);
        m_pTraverseReport->traverseGroup(xGroup);
        m_pTraverseReport->traverseGroupFunctions(xGroup->getFunctions());
        if ( xGroup->getHeaderOn() )
            m_pTraverseReport->traverseGroupHeader(xGroup->getHeader());
    }

    m_pTraverseReport->traverseDetail(_xReportDefinition->getDetail());

    for (i = 0;i<nCount ; ++i)
    {
        uno::Reference< report::XGroup > xGroup(xGroups->getByIndex(i),uno::UNO_QUERY);
        if ( xGroup->getFooterOn() )
            m_pTraverseReport->traverseGroupFooter(xGroup->getFooter());
    }

    if ( _xReportDefinition->getPageFooterOn() )
        m_pTraverseReport->traversePageFooter(_xReportDefinition->getPageFooter());
    if ( _xReportDefinition->getReportFooterOn() )
        m_pTraverseReport->traverseReportFooter(_xReportDefinition->getReportFooter());
}
// -----------------------------------------------------------------------------
void OReportVisitor::start(const uno::Reference< report::XGroup>& _xGroup)
{
    OSL_ENSURE(_xGroup.is(),"Group is NULL!");
    if ( !_xGroup.is() )
        return;
    m_pTraverseReport->traverseGroup(_xGroup);
    m_pTraverseReport->traverseGroupFunctions(_xGroup->getFunctions());
    if ( _xGroup->getHeaderOn() )
        m_pTraverseReport->traverseGroupHeader(_xGroup->getHeader());
    if ( _xGroup->getFooterOn() )
        m_pTraverseReport->traverseGroupFooter(_xGroup->getFooter());
}
// =============================================================================
} // namespace reportdesign
// =============================================================================
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: mediadescriptor.hxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: kz $ $Date: 2005-03-21 13:45:01 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _COMPHELPER_MEDIADESCRIPTOR_HXX_
#define _COMPHELPER_MEDIADESCRIPTOR_HXX_

//_______________________________________________
// includes

#ifndef __COM_SUN_STAR_IO_XINPUTSTREAM_HPP__
#include <com/sun/star/io/XInputStream.hpp>
#endif

#ifndef _COMPHELPER_SEQUENCEASHASHMAP_HXX_
#include <comphelper/sequenceashashmap.hxx>
#endif

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif
#ifndef INCLUDED_COMPHELPERDLLAPI_H
#include "comphelper/comphelperdllapi.h"
#endif

//_______________________________________________
// namespace

namespace comphelper{

//_______________________________________________
// definitions

/** @short  can be used to work with a <type scope="::com::sun::star::document">MediaDescriptor</type>
            struct.

    @descr  It wraps a ::std::hash_map around the Sequence< css::beans::PropertyValue >, which
            represent the MediaDescriptor item.
            Further this helper defines often used functions (as e.g. open of the required streams,
            consistent checks etcpp.) and it defines all useable property names.

    @attention  This class isnt threadsafe and must be guarded from outside!
 */
class COMPHELPER_DLLPUBLIC MediaDescriptor : public SequenceAsHashMap
{
    //-------------------------------------------
    // const
    public:

        //---------------------------------------
        /** @short  these methods can be used to get the different property names
                    as static const OUString values.

            @descr  Because definition and declaration of static const class members
                    does not work as expected under windows (under unix it works as well)
                    these way must be used :-(
          */
        static const ::rtl::OUString& PROP_ASTEMPLATE();
        static const ::rtl::OUString& PROP_CHARACTERSET();
        static const ::rtl::OUString& PROP_DEEPDETECTION();
        static const ::rtl::OUString& PROP_DETECTSERVICE();
        static const ::rtl::OUString& PROP_DOCUMENTSERVICE();
        static const ::rtl::OUString& PROP_EXTENSION();
        static const ::rtl::OUString& PROP_FILENAME();
        static const ::rtl::OUString& PROP_FILTERNAME();
        static const ::rtl::OUString& PROP_FILTEROPTIONS();
        static const ::rtl::OUString& PROP_FORMAT();
        static const ::rtl::OUString& PROP_FRAMENAME();
        static const ::rtl::OUString& PROP_HIDDEN();
        static const ::rtl::OUString& PROP_INPUTSTREAM();
        static const ::rtl::OUString& PROP_INTERACTIONHANDLER();
        static const ::rtl::OUString& PROP_JUMPMARK();
        static const ::rtl::OUString& PROP_MACROEXECUTIONMODE();
        static const ::rtl::OUString& PROP_MEDIATYPE();
        static const ::rtl::OUString& PROP_MINIMIZED();
        static const ::rtl::OUString& PROP_OPENNEWVIEW();
        static const ::rtl::OUString& PROP_OUTPUTSTREAM();
        static const ::rtl::OUString& PROP_PASSWORD();
        static const ::rtl::OUString& PROP_PATTERN();
        static const ::rtl::OUString& PROP_POSSIZE();
        static const ::rtl::OUString& PROP_POSTDATA();
        static const ::rtl::OUString& PROP_POSTSTRING();
        static const ::rtl::OUString& PROP_PREVIEW();
        static const ::rtl::OUString& PROP_READONLY();
        static const ::rtl::OUString& PROP_REFERRER();
        static const ::rtl::OUString& PROP_SALVAGEDFILE();
        static const ::rtl::OUString& PROP_SILENT();
        static const ::rtl::OUString& PROP_STATUSINDICATOR();
        static const ::rtl::OUString& PROP_STREAM();
        static const ::rtl::OUString& PROP_TEMPLATENAME();
        static const ::rtl::OUString& PROP_TEMPLATEREGIONNAME();
        static const ::rtl::OUString& PROP_TITLE();
        static const ::rtl::OUString& PROP_TYPENAME();
        static const ::rtl::OUString& PROP_UCBCONTENT();
        static const ::rtl::OUString& PROP_UPDATEDOCMODE();
        static const ::rtl::OUString& PROP_URL();
        static const ::rtl::OUString& PROP_VERSION();
        static const ::rtl::OUString& PROP_VIEWID();
        static const ::rtl::OUString& PROP_REPAIRPACKAGE();
        static const ::rtl::OUString& PROP_DOCUMENTTITLE();
        static const ::rtl::OUString& PROP_MODEL();
        static const ::rtl::OUString& PROP_VIEWONLY();

    //-------------------------------------------
    // interface
    public:

        //---------------------------------------
        /** @short  these ctors do nothing - excepting that they forward
                    the given parameters to the base class ctors.

            @descr  The ctros must be overwritten to resolve conflicts with
                    the default ctors of the compiler :-(.
         */
        MediaDescriptor();
        MediaDescriptor(const ::com::sun::star::uno::Any& aSource);
        MediaDescriptor(const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lSource);
        MediaDescriptor(const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& lSource);

        //---------------------------------------
        /** @short  it checks if the descriptor already has a valid
                    InputStream item and creates a new one, if not.

            @descr  This method uses the current items of this MediaDescriptor,
                    to open the stream (as e.g. URL, ReadOnly, PostData etcpp.).
                    It creates a seekable stream and put it into the descriptor.

                    A might existing InteractionHandler will be used automaticly,
                    to solve problems!

            @return TRUE, if the stream was already part of the descriptor or could
                    be created as new item. FALSE otherwhise.
         */
        sal_Bool addInputStream();

        //---------------------------------------
        /** @short  it checks if the descriptor describes a readonly stream.

            @descr  The descriptor itself isnt changed doing so.
                    It's only checked if the stream seems to be based
                    of a real readonly file.

            @Attention
                    We dont check the property "ReadOnly" here. Because
                    this property can be set from outside and overwrites
                    the readonly state of  the stream.
                    If e.g. the stream could be opened read/write ...
                    but "ReadOnly" property is set to TRUE, this means:
                    show a readonly UI on top of this read/write stream.

            @return TRUE, if the stream must be interpreted as readonly ...
                    FALSE otherwhise.
         */
        sal_Bool isStreamReadOnly() const;

    //-------------------------------------------
    // helper
    private:

        //---------------------------------------
        /** @short  tries to open a stream by using the given PostData stream.

            @descr  The stream is used directly ...

                    The MediaDescriptor itself is changed inside this method.
                    Means: the stream is added internal and not returned by a value.

            @param  xPostData
                    the PostData stream.

            @return TRUE if the stream could be added successfully.
                    Note: If FALSE is returned, the error was already handled inside!

            @throw  [css::uno::RuntimeException]
                    if the MediaDescriptor seems to be invalid!
         */
        COMPHELPER_DLLPRIVATE sal_Bool impl_openStreamWithPostData(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& xPostData)
            throw(::com::sun::star::uno::RuntimeException);

        //---------------------------------------
        /** @short  tries to open a stream by using the given URL.

            @descr  First it tries to open the content in r/w mode (if its
                    allowed to do so). Only in case its not allowed or it failed
                    the stream will be tried to open in readonly mode.

                    The MediaDescriptor itself is changed inside this method.
                    Means: the stream is added internal and not returned by a value.

            @param  sURL
                    the URL for open.

            @return TRUE if the stream could be added successfully.
                    Note: If FALSE is returned, the error was already handled inside!

            @throw  [css::uno::RuntimeException]
                    if the MediaDescriptor seems to be invalid!
         */
        COMPHELPER_DLLPRIVATE sal_Bool impl_openStreamWithURL(const ::rtl::OUString& sURL)
            throw(::com::sun::star::uno::RuntimeException);

        //---------------------------------------
        /** @short  some URL parts can make trouble for opening streams (e.g. jumpmarks.)
                    An URL should be "normalized" before its used.

            @param  sURL
                    the original URL (e.g. including a jumpmark)

            @return [string]
                    the "normalized" URL (e.g. without jumpmark)
         */
        COMPHELPER_DLLPRIVATE ::rtl::OUString impl_normalizeURL(const ::rtl::OUString& sURL);
};

} // namespace comphelper

#endif // _COMPHELPER_MEDIADESCRIPTOR_HXX_
<commit_msg>INTEGRATION: CWS ooo19126 (1.7.44); FILE MERGED 2005/09/05 15:23:43 rt 1.7.44.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: mediadescriptor.hxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 02:32:50 $
 *
 *  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
 *
 ************************************************************************/

#ifndef _COMPHELPER_MEDIADESCRIPTOR_HXX_
#define _COMPHELPER_MEDIADESCRIPTOR_HXX_

//_______________________________________________
// includes

#ifndef __COM_SUN_STAR_IO_XINPUTSTREAM_HPP__
#include <com/sun/star/io/XInputStream.hpp>
#endif

#ifndef _COMPHELPER_SEQUENCEASHASHMAP_HXX_
#include <comphelper/sequenceashashmap.hxx>
#endif

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif
#ifndef INCLUDED_COMPHELPERDLLAPI_H
#include "comphelper/comphelperdllapi.h"
#endif

//_______________________________________________
// namespace

namespace comphelper{

//_______________________________________________
// definitions

/** @short  can be used to work with a <type scope="::com::sun::star::document">MediaDescriptor</type>
            struct.

    @descr  It wraps a ::std::hash_map around the Sequence< css::beans::PropertyValue >, which
            represent the MediaDescriptor item.
            Further this helper defines often used functions (as e.g. open of the required streams,
            consistent checks etcpp.) and it defines all useable property names.

    @attention  This class isnt threadsafe and must be guarded from outside!
 */
class COMPHELPER_DLLPUBLIC MediaDescriptor : public SequenceAsHashMap
{
    //-------------------------------------------
    // const
    public:

        //---------------------------------------
        /** @short  these methods can be used to get the different property names
                    as static const OUString values.

            @descr  Because definition and declaration of static const class members
                    does not work as expected under windows (under unix it works as well)
                    these way must be used :-(
          */
        static const ::rtl::OUString& PROP_ASTEMPLATE();
        static const ::rtl::OUString& PROP_CHARACTERSET();
        static const ::rtl::OUString& PROP_DEEPDETECTION();
        static const ::rtl::OUString& PROP_DETECTSERVICE();
        static const ::rtl::OUString& PROP_DOCUMENTSERVICE();
        static const ::rtl::OUString& PROP_EXTENSION();
        static const ::rtl::OUString& PROP_FILENAME();
        static const ::rtl::OUString& PROP_FILTERNAME();
        static const ::rtl::OUString& PROP_FILTEROPTIONS();
        static const ::rtl::OUString& PROP_FORMAT();
        static const ::rtl::OUString& PROP_FRAMENAME();
        static const ::rtl::OUString& PROP_HIDDEN();
        static const ::rtl::OUString& PROP_INPUTSTREAM();
        static const ::rtl::OUString& PROP_INTERACTIONHANDLER();
        static const ::rtl::OUString& PROP_JUMPMARK();
        static const ::rtl::OUString& PROP_MACROEXECUTIONMODE();
        static const ::rtl::OUString& PROP_MEDIATYPE();
        static const ::rtl::OUString& PROP_MINIMIZED();
        static const ::rtl::OUString& PROP_OPENNEWVIEW();
        static const ::rtl::OUString& PROP_OUTPUTSTREAM();
        static const ::rtl::OUString& PROP_PASSWORD();
        static const ::rtl::OUString& PROP_PATTERN();
        static const ::rtl::OUString& PROP_POSSIZE();
        static const ::rtl::OUString& PROP_POSTDATA();
        static const ::rtl::OUString& PROP_POSTSTRING();
        static const ::rtl::OUString& PROP_PREVIEW();
        static const ::rtl::OUString& PROP_READONLY();
        static const ::rtl::OUString& PROP_REFERRER();
        static const ::rtl::OUString& PROP_SALVAGEDFILE();
        static const ::rtl::OUString& PROP_SILENT();
        static const ::rtl::OUString& PROP_STATUSINDICATOR();
        static const ::rtl::OUString& PROP_STREAM();
        static const ::rtl::OUString& PROP_TEMPLATENAME();
        static const ::rtl::OUString& PROP_TEMPLATEREGIONNAME();
        static const ::rtl::OUString& PROP_TITLE();
        static const ::rtl::OUString& PROP_TYPENAME();
        static const ::rtl::OUString& PROP_UCBCONTENT();
        static const ::rtl::OUString& PROP_UPDATEDOCMODE();
        static const ::rtl::OUString& PROP_URL();
        static const ::rtl::OUString& PROP_VERSION();
        static const ::rtl::OUString& PROP_VIEWID();
        static const ::rtl::OUString& PROP_REPAIRPACKAGE();
        static const ::rtl::OUString& PROP_DOCUMENTTITLE();
        static const ::rtl::OUString& PROP_MODEL();
        static const ::rtl::OUString& PROP_VIEWONLY();

    //-------------------------------------------
    // interface
    public:

        //---------------------------------------
        /** @short  these ctors do nothing - excepting that they forward
                    the given parameters to the base class ctors.

            @descr  The ctros must be overwritten to resolve conflicts with
                    the default ctors of the compiler :-(.
         */
        MediaDescriptor();
        MediaDescriptor(const ::com::sun::star::uno::Any& aSource);
        MediaDescriptor(const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lSource);
        MediaDescriptor(const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& lSource);

        //---------------------------------------
        /** @short  it checks if the descriptor already has a valid
                    InputStream item and creates a new one, if not.

            @descr  This method uses the current items of this MediaDescriptor,
                    to open the stream (as e.g. URL, ReadOnly, PostData etcpp.).
                    It creates a seekable stream and put it into the descriptor.

                    A might existing InteractionHandler will be used automaticly,
                    to solve problems!

            @return TRUE, if the stream was already part of the descriptor or could
                    be created as new item. FALSE otherwhise.
         */
        sal_Bool addInputStream();

        //---------------------------------------
        /** @short  it checks if the descriptor describes a readonly stream.

            @descr  The descriptor itself isnt changed doing so.
                    It's only checked if the stream seems to be based
                    of a real readonly file.

            @Attention
                    We dont check the property "ReadOnly" here. Because
                    this property can be set from outside and overwrites
                    the readonly state of  the stream.
                    If e.g. the stream could be opened read/write ...
                    but "ReadOnly" property is set to TRUE, this means:
                    show a readonly UI on top of this read/write stream.

            @return TRUE, if the stream must be interpreted as readonly ...
                    FALSE otherwhise.
         */
        sal_Bool isStreamReadOnly() const;

    //-------------------------------------------
    // helper
    private:

        //---------------------------------------
        /** @short  tries to open a stream by using the given PostData stream.

            @descr  The stream is used directly ...

                    The MediaDescriptor itself is changed inside this method.
                    Means: the stream is added internal and not returned by a value.

            @param  xPostData
                    the PostData stream.

            @return TRUE if the stream could be added successfully.
                    Note: If FALSE is returned, the error was already handled inside!

            @throw  [css::uno::RuntimeException]
                    if the MediaDescriptor seems to be invalid!
         */
        COMPHELPER_DLLPRIVATE sal_Bool impl_openStreamWithPostData(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& xPostData)
            throw(::com::sun::star::uno::RuntimeException);

        //---------------------------------------
        /** @short  tries to open a stream by using the given URL.

            @descr  First it tries to open the content in r/w mode (if its
                    allowed to do so). Only in case its not allowed or it failed
                    the stream will be tried to open in readonly mode.

                    The MediaDescriptor itself is changed inside this method.
                    Means: the stream is added internal and not returned by a value.

            @param  sURL
                    the URL for open.

            @return TRUE if the stream could be added successfully.
                    Note: If FALSE is returned, the error was already handled inside!

            @throw  [css::uno::RuntimeException]
                    if the MediaDescriptor seems to be invalid!
         */
        COMPHELPER_DLLPRIVATE sal_Bool impl_openStreamWithURL(const ::rtl::OUString& sURL)
            throw(::com::sun::star::uno::RuntimeException);

        //---------------------------------------
        /** @short  some URL parts can make trouble for opening streams (e.g. jumpmarks.)
                    An URL should be "normalized" before its used.

            @param  sURL
                    the original URL (e.g. including a jumpmark)

            @return [string]
                    the "normalized" URL (e.g. without jumpmark)
         */
        COMPHELPER_DLLPRIVATE ::rtl::OUString impl_normalizeURL(const ::rtl::OUString& sURL);
};

} // namespace comphelper

#endif // _COMPHELPER_MEDIADESCRIPTOR_HXX_
<|endoftext|>


<commit_before>#pragma once
#ifndef OPENGM_EDITABLEDATASET_HXX
#define OPENGM_EDITABLEDATASET_HXX

#include <vector>
#include <cstdlib>

#include <opengm/learning/dataset/dataset.hxx>
#include <opengm/graphicalmodel/graphicalmodel_hdf5.hxx>
#include "../../graphicalmodel/weights.hxx"
#include "../loss/noloss.hxx"

namespace opengm {
   namespace datasets{

     template<class GM, class LOSS>
      class EditableDataset : public Dataset<GM, LOSS>{
      public:
         typedef GM                     GMType;
         typedef GM                     GMWITHLOSS;
         typedef LOSS                   LossType;
         typedef typename LOSS::Parameter LossParameterType;
         typedef typename GM::ValueType ValueType;
         typedef typename GM::IndexType IndexType;
         typedef typename GM::LabelType LabelType;
         typedef opengm::learning::Weights<ValueType> Weights;
         typedef std::vector<LabelType> GTVector;

         EditableDataset(size_t numInstances=0) : Dataset<GM, LOSS>(numInstances) {}
         EditableDataset(std::vector<GM>& gms, std::vector<GTVector >& gts, std::vector<LossParameterType>& lossParams);

         void setInstance(const size_t i, const GM& gm, const GTVector& gt, const LossParameterType& p=LossParameterType());
         void pushBackInstance(const GM& gm, const GTVector& gt, const LossParameterType& p=LossParameterType());
         void setWeights(Weights& w);
      };

    template<class GM, class LOSS>
    EditableDataset<GM, LOSS>::EditableDataset(std::vector<GM>& gms,
                                               std::vector<GTVector >& gts,
                                               std::vector<LossParameterType>& lossParams)
        : Dataset<GM, LOSS>(gms.size())
    {
        for(size_t i=0; i<gms.size(); ++i){
            setInstance(i, gms[i], gts[i], lossParams[i]);
            this->buildModelWithLoss(i);
        }
    }

    template<class GM, class LOSS>
    void EditableDataset<GM, LOSS>::setInstance(const size_t i, const GM& gm, const GTVector& gt, const LossParameterType& p) {
        OPENGM_CHECK_OP(i, <, this->gms_.size(),"");
        OPENGM_CHECK_OP(i, <, this->gts_.size(),"");
        OPENGM_CHECK_OP(i, <, this->lossParams_.size(),"");
        OPENGM_CHECK_OP(i, <, this->gmsWithLoss_.size(),"");
        this->gms_[i] = gm;
        this->gts_[i] = gt;
        this->lossParams_[i] = p;
        this->buildModelWithLoss(i);
    }

    template<class GM, class LOSS>
    void EditableDataset<GM, LOSS>::pushBackInstance(const GM& gm, const GTVector& gt, const LossParameterType& p) {
        this->gms_.push_back(gm);
        this->gts_.push_back(gt);
        this->lossParams_.push_back(p);
        this->gmsWithLoss_.resize(this->gts_.size());
        this->buildModelWithLoss(this->gts_.size()-1);
        OPENGM_CHECK_OP(this->gms_.size(), ==, this->gts_.size(),"");
        OPENGM_CHECK_OP(this->gms_.size(), ==, this->lossParams_.size(),"");
        OPENGM_CHECK_OP(this->gms_.size(), ==, this->gmsWithLoss_.size(),"");
    }

    template<class GM, class LOSS>
    void EditableDataset<GM, LOSS>::setWeights(Weights& w) {
        this->weights_ = w;
    }

   } // namespace datasets
} // namespace opengm

#endif
<commit_msg>fixed: resize count_ and isCached_ vector for EditableDataset<commit_after>#pragma once
#ifndef OPENGM_EDITABLEDATASET_HXX
#define OPENGM_EDITABLEDATASET_HXX

#include <vector>
#include <cstdlib>

#include <opengm/learning/dataset/dataset.hxx>
#include <opengm/graphicalmodel/graphicalmodel_hdf5.hxx>
#include "../../graphicalmodel/weights.hxx"
#include "../loss/noloss.hxx"

namespace opengm {
   namespace datasets{

     template<class GM, class LOSS>
      class EditableDataset : public Dataset<GM, LOSS>{
      public:
         typedef GM                     GMType;
         typedef GM                     GMWITHLOSS;
         typedef LOSS                   LossType;
         typedef typename LOSS::Parameter LossParameterType;
         typedef typename GM::ValueType ValueType;
         typedef typename GM::IndexType IndexType;
         typedef typename GM::LabelType LabelType;
         typedef opengm::learning::Weights<ValueType> Weights;
         typedef std::vector<LabelType> GTVector;

         EditableDataset(size_t numInstances=0) : Dataset<GM, LOSS>(numInstances) {}
         EditableDataset(std::vector<GM>& gms, std::vector<GTVector >& gts, std::vector<LossParameterType>& lossParams);

         void setInstance(const size_t i, const GM& gm, const GTVector& gt, const LossParameterType& p=LossParameterType());
         void pushBackInstance(const GM& gm, const GTVector& gt, const LossParameterType& p=LossParameterType());
         void setWeights(Weights& w);
      };

    template<class GM, class LOSS>
    EditableDataset<GM, LOSS>::EditableDataset(std::vector<GM>& gms,
                                               std::vector<GTVector >& gts,
                                               std::vector<LossParameterType>& lossParams)
        : Dataset<GM, LOSS>(gms.size())
    {
        for(size_t i=0; i<gms.size(); ++i){
            setInstance(i, gms[i], gts[i], lossParams[i]);
            this->buildModelWithLoss(i);
        }
    }

    template<class GM, class LOSS>
    void EditableDataset<GM, LOSS>::setInstance(const size_t i, const GM& gm, const GTVector& gt, const LossParameterType& p) {
        OPENGM_CHECK_OP(i, <, this->gms_.size(),"");
        OPENGM_CHECK_OP(i, <, this->gts_.size(),"");
        OPENGM_CHECK_OP(i, <, this->lossParams_.size(),"");
        OPENGM_CHECK_OP(i, <, this->gmsWithLoss_.size(),"");
        this->gms_[i] = gm;
        this->gts_[i] = gt;
        this->lossParams_[i] = p;
        this->buildModelWithLoss(i);
    }

    template<class GM, class LOSS>
    void EditableDataset<GM, LOSS>::pushBackInstance(const GM& gm, const GTVector& gt, const LossParameterType& p) {
        this->gms_.push_back(gm);
        this->gts_.push_back(gt);
        this->lossParams_.push_back(p);
        this->gmsWithLoss_.resize(this->gts_.size());
        this->buildModelWithLoss(this->gts_.size()-1);
        this->count_.push_back(0);
        this->isCached_.push_back(bool());
        OPENGM_CHECK_OP(this->gms_.size(), ==, this->gts_.size(),"");
        OPENGM_CHECK_OP(this->gms_.size(), ==, this->lossParams_.size(),"");
        OPENGM_CHECK_OP(this->gms_.size(), ==, this->gmsWithLoss_.size(),"");
    }

    template<class GM, class LOSS>
    void EditableDataset<GM, LOSS>::setWeights(Weights& w) {
        this->weights_ = w;
    }

   } // namespace datasets
} // namespace opengm

#endif
<|endoftext|>


<commit_before><commit_msg>slightly reduce the overhead of 'EXT-5601: Linux: volume adjustment of web-based media / Flash'<commit_after><|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS aquavcl08 (1.25.8); FILE MERGED 2008/05/15 12:54:14 cloph 1.25.8.1: Issue number: #i88987# increase java VM version for Mac OSX<commit_after><|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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 <unistd.h>

#include <map>
#include <string>

#include <mesos/mesos.hpp>

#include <mesos/module/container_logger.hpp>

#include <mesos/slave/container_logger.hpp>

#include <process/dispatch.hpp>
#include <process/future.hpp>
#include <process/process.hpp>
#include <process/subprocess.hpp>

#include <stout/bytes.hpp>
#include <stout/error.hpp>
#include <stout/try.hpp>
#include <stout/none.hpp>
#include <stout/nothing.hpp>
#include <stout/path.hpp>

#include <stout/os/environment.hpp>
#include <stout/os/fcntl.hpp>
#include <stout/os/killtree.hpp>

#include "slave/container_loggers/logrotate.hpp"
#include "slave/container_loggers/lib_logrotate.hpp"

using namespace mesos;
using namespace process;

using mesos::slave::ContainerLogger;

namespace mesos {
namespace internal {
namespace logger {

using SubprocessInfo = ContainerLogger::SubprocessInfo;

class LogrotateContainerLoggerProcess :
  public Process<LogrotateContainerLoggerProcess>
{
public:
  LogrotateContainerLoggerProcess(const Flags& _flags) : flags(_flags) {}

  Future<Nothing> recover(
      const ExecutorInfo& executorInfo,
      const std::string& sandboxDirectory)
  {
    // No state to recover.
    return Nothing();
  }

  // Spawns two subprocesses that read from their stdin and write to
  // "stdout" and "stderr" files in the sandbox.  The subprocesses will rotate
  // the files according to the configured maximum size and number of files.
  Future<SubprocessInfo> prepare(
      const ExecutorInfo& executorInfo,
      const std::string& sandboxDirectory)
  {
    // Inherit most, but not all of the agent's environment.
    // Since the subprocess links to libmesos, it will need some of the
    // same environment used to launch the agent (also uses libmesos).
    // The libprocess port is explicitly removed because this
    // will conflict with the already-running agent.
    std::map<std::string, std::string> environment = os::environment();
    environment.erase("LIBPROCESS_PORT");
    environment.erase("LIBPROCESS_ADVERTISE_PORT");

    // NOTE: We manually construct a pipe here instead of using
    // `Subprocess::PIPE` so that the ownership of the FDs is properly
    // represented.  The `Subprocess` spawned below owns the read-end
    // of the pipe and will be solely responsible for closing that end.
    // The ownership of the write-end will be passed to the caller
    // of this function.
    int pipefd[2];
    if (::pipe(pipefd) == -1) {
      return Failure(ErrnoError("Failed to create pipe").message);
    }

    Subprocess::IO::InputFileDescriptors outfds;
    outfds.read = pipefd[0];
    outfds.write = pipefd[1];

    // NOTE: We need to `cloexec` this FD so that it will be closed when
    // the child subprocess is spawned and so that the FD will not be
    // inherited by the second child for stderr.
    Try<Nothing> cloexec = os::cloexec(outfds.write.get());
    if (cloexec.isError()) {
      os::close(outfds.read);
      os::close(outfds.write.get());
      return Failure("Failed to cloexec: " + cloexec.error());
    }

    // Spawn a process to handle stdout.
    mesos::internal::logger::rotate::Flags outFlags;
    outFlags.max_size = flags.max_stdout_size;
    outFlags.logrotate_options = flags.logrotate_stdout_options;
    outFlags.log_filename = path::join(sandboxDirectory, "stdout");
    outFlags.logrotate_path = flags.logrotate_path;

    Try<Subprocess> outProcess = subprocess(
        path::join(flags.launcher_dir, mesos::internal::logger::rotate::NAME),
        {mesos::internal::logger::rotate::NAME},
        Subprocess::FD(outfds.read, Subprocess::IO::OWNED),
        Subprocess::PATH("/dev/null"),
        Subprocess::FD(STDERR_FILENO),
        outFlags,
        environment);

    if (outProcess.isError()) {
      os::close(outfds.write.get());
      return Failure("Failed to create logger process: " + outProcess.error());
    }

    // NOTE: We manually construct a pipe here to properly express
    // ownership of the FDs.  See the NOTE above.
    if (::pipe(pipefd) == -1) {
      os::close(outfds.write.get());
      os::killtree(outProcess.get().pid(), SIGKILL);
      return Failure(ErrnoError("Failed to create pipe").message);
    }

    Subprocess::IO::InputFileDescriptors errfds;
    errfds.read = pipefd[0];
    errfds.write = pipefd[1];

    // NOTE: We need to `cloexec` this FD so that it will be closed when
    // the child subprocess is spawned.
    cloexec = os::cloexec(errfds.write.get());
    if (cloexec.isError()) {
      os::close(outfds.write.get());
      os::close(errfds.read);
      os::close(errfds.write.get());
      os::killtree(outProcess.get().pid(), SIGKILL);
      return Failure("Failed to cloexec: " + cloexec.error());
    }

    // Spawn a process to handle stderr.
    mesos::internal::logger::rotate::Flags errFlags;
    errFlags.max_size = flags.max_stderr_size;
    errFlags.logrotate_options = flags.logrotate_stderr_options;
    errFlags.log_filename = path::join(sandboxDirectory, "stderr");
    errFlags.logrotate_path = flags.logrotate_path;

    Try<Subprocess> errProcess = subprocess(
        path::join(flags.launcher_dir, mesos::internal::logger::rotate::NAME),
        {mesos::internal::logger::rotate::NAME},
        Subprocess::FD(errfds.read, Subprocess::IO::OWNED),
        Subprocess::PATH("/dev/null"),
        Subprocess::FD(STDERR_FILENO),
        errFlags,
        environment);

    if (errProcess.isError()) {
      os::close(outfds.write.get());
      os::close(errfds.write.get());
      os::killtree(outProcess.get().pid(), SIGKILL);
      return Failure("Failed to create logger process: " + errProcess.error());
    }

    // NOTE: The ownership of these FDs is given to the caller of this function.
    ContainerLogger::SubprocessInfo info;
    info.out = SubprocessInfo::IO::FD(outfds.write.get());
    info.err = SubprocessInfo::IO::FD(errfds.write.get());
    return info;
  }

protected:
  Flags flags;
};

LogrotateContainerLogger::LogrotateContainerLogger(const Flags& _flags)
  : flags(_flags),
    process(new LogrotateContainerLoggerProcess(flags))
{
  // Spawn and pass validated parameters to the process.
  spawn(process.get());
}

LogrotateContainerLogger::~LogrotateContainerLogger()
{
  terminate(process.get());
  wait(process.get());
}

Try<Nothing> LogrotateContainerLogger::initialize()
{
  return Nothing();
}

Future<Nothing> LogrotateContainerLogger::recover(
    const ExecutorInfo& executorInfo,
    const std::string& sandboxDirectory)
{
  return dispatch(
      process.get(),
      &LogrotateContainerLoggerProcess::recover,
      executorInfo,
      sandboxDirectory);
}

Future<SubprocessInfo> LogrotateContainerLogger::prepare(
    const ExecutorInfo& executorInfo,
    const std::string& sandboxDirectory)
{
  return dispatch(
      process.get(),
      &LogrotateContainerLoggerProcess::prepare,
      executorInfo,
      sandboxDirectory);
}

} // namespace logger {
} // namespace internal {
} // namespace mesos {

mesos::modules::Module<ContainerLogger>
org_apache_mesos_LogrotateContainerLogger(
    MESOS_MODULE_API_VERSION,
    MESOS_VERSION,
    "Apache Mesos",
    "modules@mesos.apache.org",
    "Logrotate Container Logger module.",
    NULL,
    [](const Parameters& parameters) -> ContainerLogger* {
      // Convert `parameters` into a map.
      std::map<std::string, std::string> values;
      foreach (const Parameter& parameter, parameters.parameter()) {
        values[parameter.key()] = parameter.value();
      }

      // Load and validate flags from the map.
      mesos::internal::logger::Flags flags;
      Try<Nothing> load = flags.load(values);

      if (load.isError()) {
        LOG(ERROR) << "Failed to parse parameters: " << load.error();
        return NULL;
      }

      return new mesos::internal::logger::LogrotateContainerLogger(flags);
    });
<commit_msg>Extended life of logrotate processes on systemd.<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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 <unistd.h>

#include <map>
#include <string>

#include <mesos/mesos.hpp>

#include <mesos/module/container_logger.hpp>

#include <mesos/slave/container_logger.hpp>

#include <process/dispatch.hpp>
#include <process/future.hpp>
#include <process/process.hpp>
#include <process/subprocess.hpp>

#include <stout/bytes.hpp>
#include <stout/error.hpp>
#include <stout/try.hpp>
#include <stout/none.hpp>
#include <stout/nothing.hpp>
#include <stout/path.hpp>

#include <stout/os/environment.hpp>
#include <stout/os/fcntl.hpp>
#include <stout/os/killtree.hpp>

#ifdef __linux__
#include "linux/systemd.hpp"
#endif // __linux__

#include "slave/container_loggers/logrotate.hpp"
#include "slave/container_loggers/lib_logrotate.hpp"

using namespace mesos;
using namespace process;

using mesos::slave::ContainerLogger;

namespace mesos {
namespace internal {
namespace logger {

using SubprocessInfo = ContainerLogger::SubprocessInfo;

class LogrotateContainerLoggerProcess :
  public Process<LogrotateContainerLoggerProcess>
{
public:
  LogrotateContainerLoggerProcess(const Flags& _flags) : flags(_flags) {}

  Future<Nothing> recover(
      const ExecutorInfo& executorInfo,
      const std::string& sandboxDirectory)
  {
    // No state to recover.
    return Nothing();
  }

  // Spawns two subprocesses that read from their stdin and write to
  // "stdout" and "stderr" files in the sandbox.  The subprocesses will rotate
  // the files according to the configured maximum size and number of files.
  Future<SubprocessInfo> prepare(
      const ExecutorInfo& executorInfo,
      const std::string& sandboxDirectory)
  {
    // Inherit most, but not all of the agent's environment.
    // Since the subprocess links to libmesos, it will need some of the
    // same environment used to launch the agent (also uses libmesos).
    // The libprocess port is explicitly removed because this
    // will conflict with the already-running agent.
    std::map<std::string, std::string> environment = os::environment();
    environment.erase("LIBPROCESS_PORT");
    environment.erase("LIBPROCESS_ADVERTISE_PORT");

    // NOTE: We manually construct a pipe here instead of using
    // `Subprocess::PIPE` so that the ownership of the FDs is properly
    // represented.  The `Subprocess` spawned below owns the read-end
    // of the pipe and will be solely responsible for closing that end.
    // The ownership of the write-end will be passed to the caller
    // of this function.
    int pipefd[2];
    if (::pipe(pipefd) == -1) {
      return Failure(ErrnoError("Failed to create pipe").message);
    }

    Subprocess::IO::InputFileDescriptors outfds;
    outfds.read = pipefd[0];
    outfds.write = pipefd[1];

    // NOTE: We need to `cloexec` this FD so that it will be closed when
    // the child subprocess is spawned and so that the FD will not be
    // inherited by the second child for stderr.
    Try<Nothing> cloexec = os::cloexec(outfds.write.get());
    if (cloexec.isError()) {
      os::close(outfds.read);
      os::close(outfds.write.get());
      return Failure("Failed to cloexec: " + cloexec.error());
    }

    // Spawn a process to handle stdout.
    mesos::internal::logger::rotate::Flags outFlags;
    outFlags.max_size = flags.max_stdout_size;
    outFlags.logrotate_options = flags.logrotate_stdout_options;
    outFlags.log_filename = path::join(sandboxDirectory, "stdout");
    outFlags.logrotate_path = flags.logrotate_path;

    // If we are on systemd, then extend the life of the process as we
    // do with the executor. Any grandchildren's lives will also be
    // extended.
    std::vector<Subprocess::Hook> parentHooks;
#ifdef __linux__
    if (systemd::enabled()) {
      parentHooks.emplace_back(Subprocess::Hook(
          &systemd::mesos::extendLifetime));
    }
#endif // __linux__

    Try<Subprocess> outProcess = subprocess(
        path::join(flags.launcher_dir, mesos::internal::logger::rotate::NAME),
        {mesos::internal::logger::rotate::NAME},
        Subprocess::FD(outfds.read, Subprocess::IO::OWNED),
        Subprocess::PATH("/dev/null"),
        Subprocess::FD(STDERR_FILENO),
        outFlags,
        environment,
        None(),
        None(),
        parentHooks);

    if (outProcess.isError()) {
      os::close(outfds.write.get());
      return Failure("Failed to create logger process: " + outProcess.error());
    }

    // NOTE: We manually construct a pipe here to properly express
    // ownership of the FDs.  See the NOTE above.
    if (::pipe(pipefd) == -1) {
      os::close(outfds.write.get());
      os::killtree(outProcess.get().pid(), SIGKILL);
      return Failure(ErrnoError("Failed to create pipe").message);
    }

    Subprocess::IO::InputFileDescriptors errfds;
    errfds.read = pipefd[0];
    errfds.write = pipefd[1];

    // NOTE: We need to `cloexec` this FD so that it will be closed when
    // the child subprocess is spawned.
    cloexec = os::cloexec(errfds.write.get());
    if (cloexec.isError()) {
      os::close(outfds.write.get());
      os::close(errfds.read);
      os::close(errfds.write.get());
      os::killtree(outProcess.get().pid(), SIGKILL);
      return Failure("Failed to cloexec: " + cloexec.error());
    }

    // Spawn a process to handle stderr.
    mesos::internal::logger::rotate::Flags errFlags;
    errFlags.max_size = flags.max_stderr_size;
    errFlags.logrotate_options = flags.logrotate_stderr_options;
    errFlags.log_filename = path::join(sandboxDirectory, "stderr");
    errFlags.logrotate_path = flags.logrotate_path;

    Try<Subprocess> errProcess = subprocess(
        path::join(flags.launcher_dir, mesos::internal::logger::rotate::NAME),
        {mesos::internal::logger::rotate::NAME},
        Subprocess::FD(errfds.read, Subprocess::IO::OWNED),
        Subprocess::PATH("/dev/null"),
        Subprocess::FD(STDERR_FILENO),
        errFlags,
        environment,
        None(),
        None(),
        parentHooks);

    if (errProcess.isError()) {
      os::close(outfds.write.get());
      os::close(errfds.write.get());
      os::killtree(outProcess.get().pid(), SIGKILL);
      return Failure("Failed to create logger process: " + errProcess.error());
    }

    // NOTE: The ownership of these FDs is given to the caller of this function.
    ContainerLogger::SubprocessInfo info;
    info.out = SubprocessInfo::IO::FD(outfds.write.get());
    info.err = SubprocessInfo::IO::FD(errfds.write.get());
    return info;
  }

protected:
  Flags flags;
};

LogrotateContainerLogger::LogrotateContainerLogger(const Flags& _flags)
  : flags(_flags),
    process(new LogrotateContainerLoggerProcess(flags))
{
  // Spawn and pass validated parameters to the process.
  spawn(process.get());
}

LogrotateContainerLogger::~LogrotateContainerLogger()
{
  terminate(process.get());
  wait(process.get());
}

Try<Nothing> LogrotateContainerLogger::initialize()
{
  return Nothing();
}

Future<Nothing> LogrotateContainerLogger::recover(
    const ExecutorInfo& executorInfo,
    const std::string& sandboxDirectory)
{
  return dispatch(
      process.get(),
      &LogrotateContainerLoggerProcess::recover,
      executorInfo,
      sandboxDirectory);
}

Future<SubprocessInfo> LogrotateContainerLogger::prepare(
    const ExecutorInfo& executorInfo,
    const std::string& sandboxDirectory)
{
  return dispatch(
      process.get(),
      &LogrotateContainerLoggerProcess::prepare,
      executorInfo,
      sandboxDirectory);
}

} // namespace logger {
} // namespace internal {
} // namespace mesos {

mesos::modules::Module<ContainerLogger>
org_apache_mesos_LogrotateContainerLogger(
    MESOS_MODULE_API_VERSION,
    MESOS_VERSION,
    "Apache Mesos",
    "modules@mesos.apache.org",
    "Logrotate Container Logger module.",
    NULL,
    [](const Parameters& parameters) -> ContainerLogger* {
      // Convert `parameters` into a map.
      std::map<std::string, std::string> values;
      foreach (const Parameter& parameter, parameters.parameter()) {
        values[parameter.key()] = parameter.value();
      }

      // Load and validate flags from the map.
      mesos::internal::logger::Flags flags;
      Try<Nothing> load = flags.load(values);

      if (load.isError()) {
        LOG(ERROR) << "Failed to parse parameters: " << load.error();
        return NULL;
      }

      return new mesos::internal::logger::LogrotateContainerLogger(flags);
    });
<|endoftext|>


<commit_before>/******************************************************************************
 *
 *  File : preprocessorinstance.cpp
 *  Creation date : Sat 18 Jul 2009 02:50:39
 *
 *  Copyright (c) 2009 Szymon Stefanek <s.stefanek at gmail dot com>
 *
 *  This library is free software; you can redistribute it and/or modify it
 *  under the terms of the GNU Library General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or (at your
 *  option) any later version.
 *
 *  This library is distributed in the hope that it will be useful, but WITHOUT
 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
 *  License for more details.
 *
 *  You should have received a copy of the GNU Library General Public License
 *  along with this library; see the file COPYING.LIB.  If not, write to the
 *  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *  MA, 02110-1301, USA.
 *
 *****************************************************************************/

#include "preprocessorinstance.h"
#include "preprocessorinterface.h"
#include "preprocessormanager.h"

#include "entities.h"

#include "agentcontrolinterface.h"
#include "agentmanagerinterface.h"

#include "tracer.h"

#include <QtCore/QTimer>

namespace Akonadi
{

PreprocessorInstance::PreprocessorInstance( const QString &id )
  : QObject(), mId( id ), mInterface( 0 )
{
  Q_ASSERT( !id.isEmpty() );

  mBusy = false;
}

PreprocessorInstance::~PreprocessorInstance()
{
}

bool PreprocessorInstance::init()
{
  Q_ASSERT( !mBusy ); // must be called very early
  Q_ASSERT( !mInterface );

  mInterface = new OrgFreedesktopAkonadiPreprocessorInterface(
      QLatin1String( "org.freedesktop.Akonadi.Preprocessor." ) + mId,
      QLatin1String( "/" ),
      QDBusConnection::sessionBus(),
      this
    );

  if( !mInterface || !mInterface->isValid() )
  {
    Tracer::self()->warning(
        QLatin1String( "PreprocessorInstance" ),
        QString::fromLatin1( "Could not connect to pre-processor instance '%1': %2" )
          .arg( mId )
          .arg( mInterface ? mInterface->lastError().message() : QString() )
      );
    delete mInterface;
    mInterface = 0;
    return false;
  }

  QObject::connect(
      mInterface,
      SIGNAL(itemProcessed(qlonglong)),
      this,
      SLOT(itemProcessed(qlonglong))
    );

  return true;
}

void PreprocessorInstance::enqueueItem( qint64 itemId )
{
  qDebug() << "PreprocessorInstance::enqueueItem(" << itemId << ")";

  mItemQueue.push_back( itemId );

  // If the preprocessor is already busy processing another item then do nothing.
  if ( mBusy )
  {
    // The "head" item is the one being processed and we have just added another one.
    Q_ASSERT( mItemQueue.size() > 1 );
    return;
  }

  // Not busy: handle the item.
  processHeadItem();
}

void PreprocessorInstance::processHeadItem()
{
  // We shouldn't be called if there are no items in the queue
  Q_ASSERT( mItemQueue.size() > 0 );
  // We shouldn't be here with no interface
  Q_ASSERT( mInterface );

  qint64 itemId = mItemQueue.front();

  // Fetch the actual item data (as it may have changed since it was enqueued)
  // The fetch will hit the cache if the item wasn't changed.

  PimItem actualItem = PimItem::retrieveById( itemId );

  while ( !actualItem.isValid() )
  {
    // hum... item is gone ?
    // FIXME: Signal to the manager that the item is no longer valid!
    PreprocessorManager::instance()->preProcessorFinishedHandlingItem( this, itemId );

    mItemQueue.pop_front();
    if( mItemQueue.empty() )
    {
      // nothing more to process for this instance: jump out
      mBusy = false;
      return;
    }

    // try the next one in the queue
    itemId = mItemQueue.front();
    actualItem = PimItem::retrieveById( itemId );
  }

  // Ok.. got a valid item to process: collection and mimetype is known.

  qDebug() << "PreprocessorInstance::processHeadItem(): about to begin processing item " << itemId;

  mBusy = true;

  mItemProcessingStartDateTime = QDateTime::currentDateTime();

  // The beginProcessItem() D-Bus call is asynchronous (marked with NoReply attribute)
  mInterface->beginProcessItem( itemId, actualItem.collectionId(), actualItem.mimeType().name() );

  qDebug() << "PreprocessorInstance::processHeadItem(): processing started for item " << itemId;

}

int PreprocessorInstance::currentProcessingTime()
{
  if( !mBusy )
    return -1; // nothing being processed

  return mItemProcessingStartDateTime.secsTo( QDateTime::currentDateTime() );
}

bool PreprocessorInstance::abortProcessing()
{
  Q_ASSERT_X( mBusy, "PreprocessorInstance::abortProcessing()", "You shouldn't call this method when isBusy() returns false" );

  OrgFreedesktopAkonadiAgentControlInterface iface(
      QLatin1String( "org.freedesktop.Akonadi.Agent." ) + mId,
      QLatin1String( "/" ),
      QDBusConnection::sessionBus(),
      this
    );

  if( !iface.isValid() )
  {
    Tracer::self()->warning(
        QLatin1String( "PreprocessorInstance" ),
        QString::fromLatin1( "Could not connect to pre-processor instance '%1': %2" )
          .arg( mId )
          .arg( iface.lastError().message() )
      );
    return false;
  }

  // We don't check the return value.. as this is a "warning"
  // The preprocessor manager will check again in a while and eventually
  // terminate the agent at all...
  iface.abort();

  return true;
}

bool PreprocessorInstance::invokeRestart()
{
  Q_ASSERT_X( mBusy, "PreprocessorInstance::invokeRestart()", "You shouldn't call this method when isBusy() returns false" );

  OrgFreedesktopAkonadiAgentManagerInterface iface(
      QLatin1String( "org.freedesktop.Akonadi" ),
      QLatin1String( "/AgentManager" ),
      QDBusConnection::sessionBus(),
      this
    );

  if( !iface.isValid() )
  {
    Tracer::self()->warning(
        QLatin1String( "PreprocessorInstance" ),
        QString::fromLatin1( "Could not connect to the AgentManager in order to restart pre-processor instance '%1': %2" )
          .arg( mId )
          .arg( iface.lastError().message() )
      );
    return false;
  }

  iface.restartAgentInstance( mId );

  return true;
}

void PreprocessorInstance::itemProcessed( qlonglong id )
{
  qDebug() << "PreprocessorInstance::itemProcessed(" << id << ")";

  // We shouldn't be called if there are no items in the queue
  if( mItemQueue.empty() )
  {
    Tracer::self()->warning(
        QLatin1String( "PreprocessorInstance" ),
        QString::fromLatin1( "Pre-processor instance '%1' emitted itemProcessed(%2) but we actually have no item in the queue" )
          .arg( mId )
          .arg( id )
      );
    mBusy = false;
    return; // preprocessor is buggy (FIXME: What now ?)
  }

  // We should be busy now: this is more likely our fault, not the preprocessor's one.
  Q_ASSERT( mBusy );

  qlonglong itemId = mItemQueue.front();

  if( itemId != id )
  {
    Tracer::self()->warning(
        QLatin1String( "PreprocessorInstance" ),
        QString::fromLatin1( "Pre-processor instance '%1' emitted itemProcessed(%2) but the head item in the queue has id %3" )
          .arg( mId )
          .arg( id )
          .arg( itemId )
      );

    // FIXME: And what now ?
  }

  mItemQueue.pop_front();

  PreprocessorManager::instance()->preProcessorFinishedHandlingItem( this, itemId );

  if( mItemQueue.empty() )
  {
    // Nothing more to do
    mBusy = false;
    return;
  }

  // Stay busy and process next item in the queue
  processHeadItem();
}

} // namespace Akonadi

<commit_msg>Make preprocessor multi-instance aware as well.<commit_after>/******************************************************************************
 *
 *  File : preprocessorinstance.cpp
 *  Creation date : Sat 18 Jul 2009 02:50:39
 *
 *  Copyright (c) 2009 Szymon Stefanek <s.stefanek at gmail dot com>
 *
 *  This library is free software; you can redistribute it and/or modify it
 *  under the terms of the GNU Library General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or (at your
 *  option) any later version.
 *
 *  This library is distributed in the hope that it will be useful, but WITHOUT
 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
 *  License for more details.
 *
 *  You should have received a copy of the GNU Library General Public License
 *  along with this library; see the file COPYING.LIB.  If not, write to the
 *  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *  MA, 02110-1301, USA.
 *
 *****************************************************************************/

#include "preprocessorinstance.h"
#include "preprocessorinterface.h"
#include "preprocessormanager.h"

#include "entities.h"

#include "agentcontrolinterface.h"
#include "agentmanagerinterface.h"

#include "tracer.h"

#include <akdbus.h>

#include <QtCore/QTimer>

namespace Akonadi
{

PreprocessorInstance::PreprocessorInstance( const QString &id )
  : QObject(), mId( id ), mInterface( 0 )
{
  Q_ASSERT( !id.isEmpty() );

  mBusy = false;
}

PreprocessorInstance::~PreprocessorInstance()
{
}

bool PreprocessorInstance::init()
{
  Q_ASSERT( !mBusy ); // must be called very early
  Q_ASSERT( !mInterface );

  mInterface = new OrgFreedesktopAkonadiPreprocessorInterface(
      AkDBus::agentServiceName( mId, AkDBus::Preprocessor ),
      QLatin1String( "/" ),
      QDBusConnection::sessionBus(),
      this
    );

  if( !mInterface || !mInterface->isValid() )
  {
    Tracer::self()->warning(
        QLatin1String( "PreprocessorInstance" ),
        QString::fromLatin1( "Could not connect to pre-processor instance '%1': %2" )
          .arg( mId )
          .arg( mInterface ? mInterface->lastError().message() : QString() )
      );
    delete mInterface;
    mInterface = 0;
    return false;
  }

  QObject::connect(
      mInterface,
      SIGNAL(itemProcessed(qlonglong)),
      this,
      SLOT(itemProcessed(qlonglong))
    );

  return true;
}

void PreprocessorInstance::enqueueItem( qint64 itemId )
{
  qDebug() << "PreprocessorInstance::enqueueItem(" << itemId << ")";

  mItemQueue.push_back( itemId );

  // If the preprocessor is already busy processing another item then do nothing.
  if ( mBusy )
  {
    // The "head" item is the one being processed and we have just added another one.
    Q_ASSERT( mItemQueue.size() > 1 );
    return;
  }

  // Not busy: handle the item.
  processHeadItem();
}

void PreprocessorInstance::processHeadItem()
{
  // We shouldn't be called if there are no items in the queue
  Q_ASSERT( mItemQueue.size() > 0 );
  // We shouldn't be here with no interface
  Q_ASSERT( mInterface );

  qint64 itemId = mItemQueue.front();

  // Fetch the actual item data (as it may have changed since it was enqueued)
  // The fetch will hit the cache if the item wasn't changed.

  PimItem actualItem = PimItem::retrieveById( itemId );

  while ( !actualItem.isValid() )
  {
    // hum... item is gone ?
    // FIXME: Signal to the manager that the item is no longer valid!
    PreprocessorManager::instance()->preProcessorFinishedHandlingItem( this, itemId );

    mItemQueue.pop_front();
    if( mItemQueue.empty() )
    {
      // nothing more to process for this instance: jump out
      mBusy = false;
      return;
    }

    // try the next one in the queue
    itemId = mItemQueue.front();
    actualItem = PimItem::retrieveById( itemId );
  }

  // Ok.. got a valid item to process: collection and mimetype is known.

  qDebug() << "PreprocessorInstance::processHeadItem(): about to begin processing item " << itemId;

  mBusy = true;

  mItemProcessingStartDateTime = QDateTime::currentDateTime();

  // The beginProcessItem() D-Bus call is asynchronous (marked with NoReply attribute)
  mInterface->beginProcessItem( itemId, actualItem.collectionId(), actualItem.mimeType().name() );

  qDebug() << "PreprocessorInstance::processHeadItem(): processing started for item " << itemId;

}

int PreprocessorInstance::currentProcessingTime()
{
  if( !mBusy )
    return -1; // nothing being processed

  return mItemProcessingStartDateTime.secsTo( QDateTime::currentDateTime() );
}

bool PreprocessorInstance::abortProcessing()
{
  Q_ASSERT_X( mBusy, "PreprocessorInstance::abortProcessing()", "You shouldn't call this method when isBusy() returns false" );

  OrgFreedesktopAkonadiAgentControlInterface iface(
      AkDBus::agentServiceName( mId, AkDBus::Agent ),
      QLatin1String( "/" ),
      QDBusConnection::sessionBus(),
      this
    );

  if( !iface.isValid() )
  {
    Tracer::self()->warning(
        QLatin1String( "PreprocessorInstance" ),
        QString::fromLatin1( "Could not connect to pre-processor instance '%1': %2" )
          .arg( mId )
          .arg( iface.lastError().message() )
      );
    return false;
  }

  // We don't check the return value.. as this is a "warning"
  // The preprocessor manager will check again in a while and eventually
  // terminate the agent at all...
  iface.abort();

  return true;
}

bool PreprocessorInstance::invokeRestart()
{
  Q_ASSERT_X( mBusy, "PreprocessorInstance::invokeRestart()", "You shouldn't call this method when isBusy() returns false" );

  OrgFreedesktopAkonadiAgentManagerInterface iface(
      AkDBus::serviceName(AkDBus::Control),
      QLatin1String( "/AgentManager" ),
      QDBusConnection::sessionBus(),
      this
    );

  if( !iface.isValid() )
  {
    Tracer::self()->warning(
        QLatin1String( "PreprocessorInstance" ),
        QString::fromLatin1( "Could not connect to the AgentManager in order to restart pre-processor instance '%1': %2" )
          .arg( mId )
          .arg( iface.lastError().message() )
      );
    return false;
  }

  iface.restartAgentInstance( mId );

  return true;
}

void PreprocessorInstance::itemProcessed( qlonglong id )
{
  qDebug() << "PreprocessorInstance::itemProcessed(" << id << ")";

  // We shouldn't be called if there are no items in the queue
  if( mItemQueue.empty() )
  {
    Tracer::self()->warning(
        QLatin1String( "PreprocessorInstance" ),
        QString::fromLatin1( "Pre-processor instance '%1' emitted itemProcessed(%2) but we actually have no item in the queue" )
          .arg( mId )
          .arg( id )
      );
    mBusy = false;
    return; // preprocessor is buggy (FIXME: What now ?)
  }

  // We should be busy now: this is more likely our fault, not the preprocessor's one.
  Q_ASSERT( mBusy );

  qlonglong itemId = mItemQueue.front();

  if( itemId != id )
  {
    Tracer::self()->warning(
        QLatin1String( "PreprocessorInstance" ),
        QString::fromLatin1( "Pre-processor instance '%1' emitted itemProcessed(%2) but the head item in the queue has id %3" )
          .arg( mId )
          .arg( id )
          .arg( itemId )
      );

    // FIXME: And what now ?
  }

  mItemQueue.pop_front();

  PreprocessorManager::instance()->preProcessorFinishedHandlingItem( this, itemId );

  if( mItemQueue.empty() )
  {
    // Nothing more to do
    mBusy = false;
    return;
  }

  // Stay busy and process next item in the queue
  processHeadItem();
}

} // namespace Akonadi

<|endoftext|>


<commit_before>#include <ctype.h>
#include <stdio.h>
#include <string.h>

#include "refalrts-diagnostic-config.h"

//FROM refalrts-debugger
#include "refalrts-debugger.h"
//FROM refalrts-platform-specific
#include "refalrts-platform-specific.h"

#define AZ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
#define az "abcdefghijklmnopqrstuvwxyz"
#define AZaz AZ az

namespace {

void normalize_name(char *dest, const char *src) {
  while (*src) {
    if (*src == '-') {
      *dest = '_';
    } else {
      *dest = static_cast<char>(tolower(*src));
    }
    ++dest;
    ++src;
  }
  *dest = '\0';
}

void bad_type(
  const char *filename, int line_no, const char *param, const char *type
) {
  fprintf(
    stderr, "%s:%d:parameter '%s' expects %s value\n",
    filename, line_no, param, type
  );
}

enum { cMaxLineLen = 2000 };

void parse_config_line(
  refalrts::DiagnosticConfig *config,
  const char *filename, int line_no, const char *line
) {
  enum Type { cString, cNumber, cBoolean } type;
  char param_name[cMaxLineLen + 1] = { '\0' };
  char string_value[cMaxLineLen + 1] = { '\0' };
  long int number_value;
  bool boolean_value;

  if (
    sscanf(line, "%[-_" AZaz "] = \"%[^\"]\"", param_name, string_value) == 2
  ) {
    type = cString;
  } else if (
    sscanf(line, "%[-_" AZaz "] = \"%[^\"]\"", param_name, string_value) == 2
  ) {
    type = cString;
  } else if (
    sscanf(line, "%[-_" AZaz "] = %li", param_name, &number_value) == 2
  ) {
    type = cNumber;
  } else {
    if (sscanf(line, "%[-_" AZaz "] = %s", param_name, string_value) == 2) {
      char boolean_value_str[cMaxLineLen + 1];
      normalize_name(boolean_value_str, string_value);
      if (strcmp(boolean_value_str, "true") == 0) {
        type = cBoolean;
        boolean_value = true;
      } else if (strcmp(boolean_value_str, "false") == 0) {
        type = cBoolean;
        boolean_value = false;
      } else {
        type = cString;
      }
    } else {
      fprintf(stderr, "%s:%d:bad config line:\n", filename, line_no);
      fprintf(stderr, "%s:%d:    %s\n", filename, line_no, line);
      return;
    }
  }

  normalize_name(param_name, param_name);

#define set_number_param(field) \
  if (strcmp(param_name, #field) == 0) { \
    if (type == cNumber) { \
      config->field = static_cast<unsigned long>(number_value); \
    } else { \
      bad_type(filename, line_no, #field, "number"); \
    } \
  }

#define set_boolean_param(field) \
  if (strcmp(param_name, #field) == 0) { \
    if (type == cNumber) { \
      config->field = !!number_value; \
    } else if (type == cBoolean) { \
      config->field = boolean_value; \
    } else { \
      bad_type(filename, line_no, #field, "boolean"); \
    } \
  }

#define set_string_param(field) \
  if (strcmp(param_name, #field) == 0) { \
    if (type == cString) { \
      if (sizeof(config->field) > strlen(string_value)) { \
        strcpy(config->field, string_value); \
      } else { \
        fprintf( \
          stderr, "%s:%d:very long string parameter '%s': \"%s\"\n", \
          filename, line_no, #field, string_value \
        ); \
      } \
    } else { \
      bad_type(filename, line_no, #field, "string"); \
    } \
  }

  set_number_param(idents_limit);
  set_number_param(memory_limit);
  set_number_param(step_limit);
  set_number_param(start_step_trace);
  set_boolean_param(print_statistics);
  set_boolean_param(dump_free_list);

  if (strcmp(param_name, "enable_debugger") == 0) {
    if (type == cNumber) {
      if (!! number_value) {
        config->debugger_factory = refalrts::debugger::RefalDebugger::create;
      }
    } else if (type == cBoolean) {
      if (boolean_value) {
        config->debugger_factory = refalrts::debugger::RefalDebugger::create;
      }
    } else {
      bad_type(filename, line_no, "enable_debugger", "boolean");
    }
  }

  set_string_param(dump_file);
#undef set_string_param
#undef set_boolean_param
#undef set_number_param
}

void read_config(refalrts::DiagnosticConfig *config, const char *filename) {
  FILE *fin = fopen(filename, "rt");
  if (! fin) {
    return;
  }

  char line[cMaxLineLen + 1] = { '\0' };
  for (int line_no = 1; fgets(line, cMaxLineLen, fin); ++line_no) {
    if (! strchr(line, '\n') && ! feof(fin)) {
      fprintf(stderr, "%s:%d:very long line\n", filename, line_no);
      int c;
      do {
        c = fgetc(fin);
      } while (c != EOF && c != '\n');
    }

    const char *pline = line;
    while (*pline && isspace(*pline)) {
      ++pline;
    }

    // Пустая строка или комментарий
    if (*pline == '\n' || *pline == '#') {
      continue;
    }

    parse_config_line(config, filename, line_no, pline);
  }

  fclose(fin);
}

const char diagnostic_suffix[] = "@refal-5-lambda-diagnostics.txt";

void load_local_diagnostic_config(
  refalrts::DiagnosticConfig *config, char *argv0
);

void init_diagnostic_config(
  refalrts::DiagnosticConfig *config, int *argc, char *argv[]
) {
#ifdef IDENTS_LIMIT
  config->idents_limit = IDENTS_LIMIT;
#endif

#ifdef MEMORY_LIMIT
  config->memory_limit = MEMORY_LIMIT;
#endif // ifdef MEMORY_LIMIT

#ifdef STEP_LIMIT
  config->step_limit = STEP_LIMIT;
#endif // ifdef STEP_LIMIT

#if SHOW_DEBUG
  config->start_step_trace = SHOW_DEBUG;
#endif // if SHOW_DEBUG

#ifndef DONT_PRINT_STATISTICS
  config->print_statistics = true;
#endif // ifndef DONT_PRINT_STATISTICS

#ifdef DUMP_FREE_LIST
  config->dump_free_list = true;
#endif // ifdef DUMP_FREE_LIST

#ifdef ENABLE_DEBUGGER
  int debug_arg = refalrts::debugger::find_debugger_flag(*argc, argv);
  if (debug_arg != -1) {
    for (int i = debug_arg; i < *argc; ++i) {
      argv[i] = argv[i + 1];
    }
    --*argc;
    config->debugger_factory = refalrts::debugger::RefalDebugger::create;
  }
#else
  (void) argc;
  (void) argv;
#endif // ifdef ENABLE_DEBUGGER

#ifdef DUMP_FILE
  if (strlen(DUMP_FILE) < sizeof(config->dump_file) - 1) {
    strcpy(config->dump_file, DUMP_FILE);
  }
#endif // ifdef DUMP_FILE

  // Чтение глобальных настроек диагностики
  read_config(config, diagnostic_suffix);

  // Чтение локальных настроек диагностики
  load_local_diagnostic_config(config, argv[0]);
}

void load_local_diagnostic_config(
  refalrts::DiagnosticConfig *config, char *argv0
) {
  const char *slash_pos = 0;
  for (const char *p = argv0; *p != '\0'; ++p) {
    if (strchr(refalrts::api::directory_separators, *p)) {
      slash_pos = p;
    }
  }

  if (slash_pos != 0 && *(slash_pos + 1) == '\0') {
    slash_pos = 0;
  }

  const char *exe_file_name = slash_pos != '\0' ? slash_pos + 1 : argv0;
  char local_diagnostic_file[FILENAME_MAX + 1] = { '\0' };
  if (strlen(exe_file_name) + strlen(diagnostic_suffix) < FILENAME_MAX) {
    strcpy(local_diagnostic_file, exe_file_name);
    strcat(local_diagnostic_file, diagnostic_suffix);
    read_config(config, local_diagnostic_file);
  }
}

int initializer =
  ((refalrts::g_init_diagnostic_config = init_diagnostic_config), 0);

}  // unnamed namespace
<commit_msg>Параметр командной строки файла конфигурации диагностики (#171)<commit_after>#include <ctype.h>
#include <stdio.h>
#include <string.h>

#include "refalrts-diagnostic-config.h"

//FROM refalrts-debugger
#include "refalrts-debugger.h"
//FROM refalrts-platform-specific
#include "refalrts-platform-specific.h"

#define AZ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
#define az "abcdefghijklmnopqrstuvwxyz"
#define AZaz AZ az

namespace {

void normalize_name(char *dest, const char *src) {
  while (*src) {
    if (*src == '-') {
      *dest = '_';
    } else {
      *dest = static_cast<char>(tolower(*src));
    }
    ++dest;
    ++src;
  }
  *dest = '\0';
}

void bad_type(
  const char *filename, int line_no, const char *param, const char *type
) {
  fprintf(
    stderr, "%s:%d:parameter '%s' expects %s value\n",
    filename, line_no, param, type
  );
}

enum { cMaxLineLen = 2000 };

void parse_config_line(
  refalrts::DiagnosticConfig *config,
  const char *filename, int line_no, const char *line
) {
  enum Type { cString, cNumber, cBoolean } type;
  char param_name[cMaxLineLen + 1] = { '\0' };
  char string_value[cMaxLineLen + 1] = { '\0' };
  long int number_value;
  bool boolean_value;

  if (
    sscanf(line, "%[-_" AZaz "] = \"%[^\"]\"", param_name, string_value) == 2
  ) {
    type = cString;
  } else if (
    sscanf(line, "%[-_" AZaz "] = \"%[^\"]\"", param_name, string_value) == 2
  ) {
    type = cString;
  } else if (
    sscanf(line, "%[-_" AZaz "] = %li", param_name, &number_value) == 2
  ) {
    type = cNumber;
  } else {
    if (sscanf(line, "%[-_" AZaz "] = %s", param_name, string_value) == 2) {
      char boolean_value_str[cMaxLineLen + 1];
      normalize_name(boolean_value_str, string_value);
      if (strcmp(boolean_value_str, "true") == 0) {
        type = cBoolean;
        boolean_value = true;
      } else if (strcmp(boolean_value_str, "false") == 0) {
        type = cBoolean;
        boolean_value = false;
      } else {
        type = cString;
      }
    } else {
      fprintf(stderr, "%s:%d:bad config line:\n", filename, line_no);
      fprintf(stderr, "%s:%d:    %s\n", filename, line_no, line);
      return;
    }
  }

  normalize_name(param_name, param_name);

#define set_number_param(field) \
  if (strcmp(param_name, #field) == 0) { \
    if (type == cNumber) { \
      config->field = static_cast<unsigned long>(number_value); \
    } else { \
      bad_type(filename, line_no, #field, "number"); \
    } \
  }

#define set_boolean_param(field) \
  if (strcmp(param_name, #field) == 0) { \
    if (type == cNumber) { \
      config->field = !!number_value; \
    } else if (type == cBoolean) { \
      config->field = boolean_value; \
    } else { \
      bad_type(filename, line_no, #field, "boolean"); \
    } \
  }

#define set_string_param(field) \
  if (strcmp(param_name, #field) == 0) { \
    if (type == cString) { \
      if (sizeof(config->field) > strlen(string_value)) { \
        strcpy(config->field, string_value); \
      } else { \
        fprintf( \
          stderr, "%s:%d:very long string parameter '%s': \"%s\"\n", \
          filename, line_no, #field, string_value \
        ); \
      } \
    } else { \
      bad_type(filename, line_no, #field, "string"); \
    } \
  }

  set_number_param(idents_limit);
  set_number_param(memory_limit);
  set_number_param(step_limit);
  set_number_param(start_step_trace);
  set_boolean_param(print_statistics);
  set_boolean_param(dump_free_list);

  if (strcmp(param_name, "enable_debugger") == 0) {
    if (type == cNumber) {
      if (!! number_value) {
        config->debugger_factory = refalrts::debugger::RefalDebugger::create;
      }
    } else if (type == cBoolean) {
      if (boolean_value) {
        config->debugger_factory = refalrts::debugger::RefalDebugger::create;
      }
    } else {
      bad_type(filename, line_no, "enable_debugger", "boolean");
    }
  }

  set_string_param(dump_file);
#undef set_string_param
#undef set_boolean_param
#undef set_number_param
}

void read_config(refalrts::DiagnosticConfig *config, const char *filename) {
  FILE *fin = fopen(filename, "rt");
  if (! fin) {
    return;
  }

  char line[cMaxLineLen + 1] = { '\0' };
  for (int line_no = 1; fgets(line, cMaxLineLen, fin); ++line_no) {
    if (! strchr(line, '\n') && ! feof(fin)) {
      fprintf(stderr, "%s:%d:very long line\n", filename, line_no);
      int c;
      do {
        c = fgetc(fin);
      } while (c != EOF && c != '\n');
    }

    const char *pline = line;
    while (*pline && isspace(*pline)) {
      ++pline;
    }

    // Пустая строка или комментарий
    if (*pline == '\n' || *pline == '#') {
      continue;
    }

    parse_config_line(config, filename, line_no, pline);
  }

  fclose(fin);
}

const char diagnostic_suffix[] = "@refal-5-lambda-diagnostics.txt";

void load_local_diagnostic_config(
  refalrts::DiagnosticConfig *config, char *argv0
);

void init_diagnostic_config(
  refalrts::DiagnosticConfig *config, int *argc, char *argv[]
) {
#ifdef IDENTS_LIMIT
  config->idents_limit = IDENTS_LIMIT;
#endif

#ifdef MEMORY_LIMIT
  config->memory_limit = MEMORY_LIMIT;
#endif // ifdef MEMORY_LIMIT

#ifdef STEP_LIMIT
  config->step_limit = STEP_LIMIT;
#endif // ifdef STEP_LIMIT

#if SHOW_DEBUG
  config->start_step_trace = SHOW_DEBUG;
#endif // if SHOW_DEBUG

#ifndef DONT_PRINT_STATISTICS
  config->print_statistics = true;
#endif // ifndef DONT_PRINT_STATISTICS

#ifdef DUMP_FREE_LIST
  config->dump_free_list = true;
#endif // ifdef DUMP_FREE_LIST

#ifdef ENABLE_DEBUGGER
  int debug_arg = refalrts::debugger::find_debugger_flag(*argc, argv);
  if (debug_arg != -1) {
    for (int i = debug_arg; i < *argc; ++i) {
      argv[i] = argv[i + 1];
    }
    --*argc;
    config->debugger_factory = refalrts::debugger::RefalDebugger::create;
  }
#else
  (void) argc;
  (void) argv;
#endif // ifdef ENABLE_DEBUGGER

#ifdef DUMP_FILE
  if (strlen(DUMP_FILE) < sizeof(config->dump_file) - 1) {
    strcpy(config->dump_file, DUMP_FILE);
  }
#endif // ifdef DUMP_FILE

  int delta = 0;
  for (int i = 1; i < *argc; ++i) {
    const char config_prefix[] = "++diagnostic+config=";
    size_t config_prefix_len = strlen(config_prefix);
    if (strncmp(argv[i], config_prefix, config_prefix_len) == 0) {
      read_config(config, argv[i] + config_prefix_len);
      delta += 1;
    } else {
      argv[i - delta] = argv[i];
    }
  }
  *argc -= delta;
  argv[*argc] = 0;

  if (delta == 0) {
    // Чтение глобальных настроек диагностики
    read_config(config, diagnostic_suffix);

    // Чтение локальных настроек диагностики
    load_local_diagnostic_config(config, argv[0]);
  }
}

void load_local_diagnostic_config(
  refalrts::DiagnosticConfig *config, char *argv0
) {
  const char *slash_pos = 0;
  for (const char *p = argv0; *p != '\0'; ++p) {
    if (strchr(refalrts::api::directory_separators, *p)) {
      slash_pos = p;
    }
  }

  if (slash_pos != 0 && *(slash_pos + 1) == '\0') {
    slash_pos = 0;
  }

  const char *exe_file_name = slash_pos != '\0' ? slash_pos + 1 : argv0;
  char local_diagnostic_file[FILENAME_MAX + 1] = { '\0' };
  if (strlen(exe_file_name) + strlen(diagnostic_suffix) < FILENAME_MAX) {
    strcpy(local_diagnostic_file, exe_file_name);
    strcat(local_diagnostic_file, diagnostic_suffix);
    read_config(config, local_diagnostic_file);
  }
}

int initializer =
  ((refalrts::g_init_diagnostic_config = init_diagnostic_config), 0);

}  // unnamed namespace
<|endoftext|>