<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit (ITK)
  Module:    itkImageToImageAffineMutualInformationGradientDescentRegistrationTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 2001 Insight Consortium
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

 * The name of the Insight Consortium, nor the names of any consortium members,
   nor of any contributors, may be used to endorse or promote products derived
   from this software without specific prior written permission.

  * Modified source versions must be plainly marked as such, and must not be
    misrepresented as being the original software.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================*/
#include "itkPhysicalImage.h"
#include "itkImageRegionIterator.h"

#include "itkImageToImageAffineMutualInformationGradientDescentRegistration.h"
#include "vnl/vnl_math.h"

#include <iostream>

int main()
{

//------------------------------------------------------------
// Create two simple images
// Two Gaussians with one translated (7,3) pixels from another
//------------------------------------------------------------

  //Allocate Images
  typedef itk::PhysicalImage<unsigned char,2>           ReferenceType;
  typedef itk::PhysicalImage<unsigned char,2>           TargetType;
  enum { ImageDimension = ReferenceType::ImageDimension };

  ReferenceType::SizeType size = {{100,100}};
  ReferenceType::IndexType index = {{0,0}};
  ReferenceType::RegionType region;
  region.SetSize( size );
  region.SetIndex( index );

  ReferenceType::Pointer imgReference = ReferenceType::New();
  imgReference->SetLargestPossibleRegion( region );
  imgReference->SetBufferedRegion( region );
  imgReference->SetRequestedRegion( region );
  imgReference->Allocate();

  TargetType::Pointer imgTarget = TargetType::New();
  imgTarget->SetLargestPossibleRegion( region );
  imgTarget->SetBufferedRegion( region );
  imgTarget->SetRequestedRegion( region );
  imgTarget->Allocate();

  // Fill images with a 2D gaussian
  typedef  itk::ImageRegionIterator<ReferenceType>
    ReferenceIteratorType;
  typedef  itk::ImageRegionIterator<TargetType>
    TargetIteratorType;

  itk::Point<double,2> center;
  center[0] = (double)region.GetSize()[0]/2.0;
  center[1] = (double)region.GetSize()[1]/2.0;

  const double s = (double)region.GetSize()[0]/2.0;

  itk::Point<double,2>  p;
  itk::Vector<double,2> d;

  // Set the displacement
  itk::Vector<double,2> displacement;
  displacement[0] = 7;
  displacement[1] =	3;

  ReferenceIteratorType ri(imgReference,region);
  TargetIteratorType ti(imgTarget,region);
  ri.Begin();
  while(!ri.IsAtEnd())
  {
    p[0] = ri.GetIndex()[0];
    p[1] = ri.GetIndex()[1];
	  d = p-center;
	  d += displacement;
	  const double x = d[0];
	  const double y = d[1];
    ri.Set( (unsigned char)( 200.0 * exp( - ( x*x + y*y )/(s*s) ) ) );
    ++ri;
  }

  ti.Begin();
  while(!ti.IsAtEnd())
  {
    p[0] = ti.GetIndex()[0];
    p[1] = ti.GetIndex()[1];
	d = p-center;
	const double x = d[0];
	const double y = d[1];
    ti.Set( (unsigned char)( 200.0 * exp( - ( x*x + y*y )/(s*s) ) ) );
    ++ti;
  }

//-----------------------------------------------------------
// Set up a the registrator
//-----------------------------------------------------------
  typedef itk::ImageToImageAffineMutualInformationGradientDescentRegistration<
    ReferenceType,TargetType> RegistrationType;

  RegistrationType::Pointer registrationMethod = RegistrationType::New();

  // connect the images
  registrationMethod->SetReference(imgReference);
  registrationMethod->SetTarget(imgTarget);

  // set the transformation centers
  RegistrationType::PointType transCenter;
  for( unsigned int j = 0; j < 2; j++ )
    {
    transCenter[j] = double(size[j]) / 2;
    }

  registrationMethod->SetTargetTransformationCenter( transCenter );
  registrationMethod->SetReferenceTransformationCenter( transCenter );

  // set translation scale
  const double transScale = 100;
  registrationMethod->SetTranslationScale( transScale );

  // set metric related parameters
  registrationMethod->GetMetric()->SetTargetStandardDeviation( 5.0 );
  registrationMethod->GetMetric()->SetReferenceStandardDeviation( 5.0 );
  registrationMethod->GetMetric()->SetNumberOfSpatialSamples( 50 );

  // do the registration
  // reduce learning rate as we go
  registrationMethod->SetNumberOfIterations( 500 );
  registrationMethod->SetLearningRate( 1e-5 );
  registrationMethod->StartRegistration();

  registrationMethod->SetNumberOfIterations( 250 );
  registrationMethod->SetLearningRate( 1e-7 );
  registrationMethod->StartRegistration();

  registrationMethod->SetNumberOfIterations( 125 );
  registrationMethod->SetLearningRate( 1e-8 );
  registrationMethod->StartRegistration();

  // get the results
  RegistrationType::ParametersType solution =
    registrationMethod->GetParameters();

  std::cout << "Solution is: " << solution << std::endl;

  //
  // check results to see if it is within range
  //
  bool pass = true;
  double trueParameters[6] = { 1, 0, 0, 1, 0, 0 };
  trueParameters[4] = - displacement[0];
  trueParameters[5] = - displacement[1];
  for( unsigned int j = 0; j < 4; j++ )
    {
    if( vnl_math_abs( solution[j] - trueParameters[j] ) > 0.02 )
      {
      std::cout << j << " ";
      std::cout << solution[j] << " ";
      std::cout << trueParameters[j] << " ";
      std::cout << vnl_math_abs( solution[j] - trueParameters[j] ) << " ";
      std::cout << std::endl;
      pass = false;
      }
    }
  for( unsigned int j = 4; j < 6; j++ )
    {
    if( vnl_math_abs( solution[j] * transScale - trueParameters[j] ) > 1.0 )
      {
      std::cout << j << " ";
      std::cout << solution[j] << " ";
      std::cout << trueParameters[j] << " ";
      std::cout << vnl_math_abs( solution[j] - trueParameters[j] ) << " ";
      std::cout << std::endl;
      pass = false;
      }
    }

  if( !pass )
    {
    std::cout << "Test failed." << std::endl;
    return EXIT_FAILURE;
    }

  std::cout << "Test passed." << std::endl;
  return EXIT_SUCCESS;

}
<commit_msg><commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit (ITK)
  Module:    itkImageToImageAffineMutualInformationGradientDescentRegistrationTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 2001 Insight Consortium
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

 * The name of the Insight Consortium, nor the names of any consortium members,
   nor of any contributors, may be used to endorse or promote products derived
   from this software without specific prior written permission.

  * Modified source versions must be plainly marked as such, and must not be
    misrepresented as being the original software.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================*/
#include "itkPhysicalImage.h"
#include "itkImageRegionIterator.h"

#include "itkImageToImageAffineMutualInformationGradientDescentRegistration.h"
#include "vnl/vnl_math.h"

#include <iostream>

int main()
{

//------------------------------------------------------------
// Create two simple images
// Two Gaussians with one translated (7,3) pixels from another
//------------------------------------------------------------

  //Allocate Images
  typedef itk::PhysicalImage<unsigned char,2>           ReferenceType;
  typedef itk::PhysicalImage<unsigned char,2>           TargetType;
  enum { ImageDimension = ReferenceType::ImageDimension };

  ReferenceType::SizeType size = {{100,100}};
  ReferenceType::IndexType index = {{0,0}};
  ReferenceType::RegionType region;
  region.SetSize( size );
  region.SetIndex( index );

  ReferenceType::Pointer imgReference = ReferenceType::New();
  imgReference->SetLargestPossibleRegion( region );
  imgReference->SetBufferedRegion( region );
  imgReference->SetRequestedRegion( region );
  imgReference->Allocate();

  TargetType::Pointer imgTarget = TargetType::New();
  imgTarget->SetLargestPossibleRegion( region );
  imgTarget->SetBufferedRegion( region );
  imgTarget->SetRequestedRegion( region );
  imgTarget->Allocate();

  // Fill images with a 2D gaussian
  typedef  itk::ImageRegionIterator<ReferenceType>
    ReferenceIteratorType;
  typedef  itk::ImageRegionIterator<TargetType>
    TargetIteratorType;

  itk::Point<double,2> center;
  center[0] = (double)region.GetSize()[0]/2.0;
  center[1] = (double)region.GetSize()[1]/2.0;

  const double s = (double)region.GetSize()[0]/2.0;

  itk::Point<double,2>  p;
  itk::Vector<double,2> d;

  // Set the displacement
  itk::Vector<double,2> displacement;
  displacement[0] = 7;
  displacement[1] =	3;

  ReferenceIteratorType ri(imgReference,region);
  TargetIteratorType ti(imgTarget,region);
  ri.Begin();
  while(!ri.IsAtEnd())
  {
    p[0] = ri.GetIndex()[0];
    p[1] = ri.GetIndex()[1];
	  d = p-center;
	  d += displacement;
	  const double x = d[0];
	  const double y = d[1];
    ri.Set( (unsigned char)( 200.0 * exp( - ( x*x + y*y )/(s*s) ) ) );
    ++ri;
  }

  ti.Begin();
  while(!ti.IsAtEnd())
  {
    p[0] = ti.GetIndex()[0];
    p[1] = ti.GetIndex()[1];
	d = p-center;
	const double x = d[0];
	const double y = d[1];
    ti.Set( (unsigned char)( 200.0 * exp( - ( x*x + y*y )/(s*s) ) ) );
    ++ti;
  }

//-----------------------------------------------------------
// Set up a the registrator
//-----------------------------------------------------------
  typedef itk::ImageToImageAffineMutualInformationGradientDescentRegistration<
    ReferenceType,TargetType> RegistrationType;

  RegistrationType::Pointer registrationMethod = RegistrationType::New();

  // connect the images
  registrationMethod->SetReference(imgReference);
  registrationMethod->SetTarget(imgTarget);

  // set the transformation centers
  RegistrationType::PointType transCenter;
  for( unsigned int j = 0; j < 2; j++ )
    {
    transCenter[j] = double(size[j]) / 2;
    }

  registrationMethod->SetTargetTransformationCenter( transCenter );
  registrationMethod->SetReferenceTransformationCenter( transCenter );

  // set translation scale
  const double transScale = 100;
  registrationMethod->SetTranslationScale( transScale );

  // set metric related parameters
  registrationMethod->GetMetric()->SetTargetStandardDeviation( 5.0 );
  registrationMethod->GetMetric()->SetReferenceStandardDeviation( 5.0 );
  registrationMethod->GetMetric()->SetNumberOfSpatialSamples( 50 );

  // do the registration
  // reduce learning rate as we go
  registrationMethod->SetNumberOfIterations( 300 );
  registrationMethod->SetLearningRate( 5e-5 );
  registrationMethod->StartRegistration();

  registrationMethod->SetNumberOfIterations( 300 );
  registrationMethod->SetLearningRate( 1e-5 );
  registrationMethod->StartRegistration();

  registrationMethod->SetNumberOfIterations( 300 );
  registrationMethod->SetLearningRate( 1e-6 );
  registrationMethod->StartRegistration();

  // get the results
  RegistrationType::ParametersType solution =
    registrationMethod->GetParameters();

  std::cout << "Solution is: " << solution << std::endl;

  //
  // check results to see if it is within range
  //
  bool pass = true;
  double trueParameters[6] = { 1, 0, 0, 1, 0, 0 };
  trueParameters[4] = - displacement[0];
  trueParameters[5] = - displacement[1];
  for( unsigned int j = 0; j < 4; j++ )
    {
    if( vnl_math_abs( solution[j] - trueParameters[j] ) > 0.02 )
      {
      std::cout << j << " ";
      std::cout << solution[j] << " ";
      std::cout << trueParameters[j] << " ";
      std::cout << vnl_math_abs( solution[j] - trueParameters[j] ) << " ";
      std::cout << std::endl;
      pass = false;
      }
    }
  for( unsigned int j = 4; j < 6; j++ )
    {
    if( vnl_math_abs( solution[j] * transScale - trueParameters[j] ) > 1.0 )
      {
      std::cout << j << " ";
      std::cout << solution[j] << " ";
      std::cout << trueParameters[j] << " ";
      std::cout << vnl_math_abs( solution[j] - trueParameters[j] ) << " ";
      std::cout << std::endl;
      pass = false;
      }
    }

  if( !pass )
    {
    std::cout << "Test failed." << std::endl;
    return EXIT_FAILURE;
    }

  std::cout << "Test passed." << std::endl;
  return EXIT_SUCCESS;

}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: sdfilter.cxx,v $
 *
 *  $Revision: 1.13 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-16 18:19:23 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

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

#ifndef _COM_SUN_STAR_TASK_XSTATUSINDICATORFACTORY_HPP_
#include <com/sun/star/task/XStatusIndicatorFactory.hpp>
#endif

#include <tools/debug.hxx>
#include <osl/file.hxx>
#include <vos/module.hxx>
#include <svtools/pathoptions.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/progress.hxx>

#ifndef _SFXITEMSET_HXX
#include <svtools/itemset.hxx>
#endif

#ifndef MAC
#ifndef SVX_LIGHT
#ifndef SD_DRAW_DOC_SHELL_HXX
#include "../ui/inc/DrawDocShell.hxx"
#endif
#include "../ui/inc/strings.hrc"
#endif //!SVX_LIGHT
#else  //MAC
#ifndef SVX_LIGHT
#ifndef SD_DRAW_DOC_SHELL_HXX
#include "DrawDocShell.hxx"
#endif
#include "strings.hrc"
#endif //!SVX_LIGHT
#endif //!MAC

#include "sdresid.hxx"
#include "pres.hxx"
#include "drawdoc.hxx"
#include "sdfilter.hxx"

// --------------
// - Namespaces -
// --------------

using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::task;
using namespace ::com::sun::star::frame;

// ------------
// - SdFilter -
// ------------

SdFilter::SdFilter( SfxMedium& rMedium, ::sd::DrawDocShell& rDocShell, sal_Bool bShowProgress ) :
    mrMedium( rMedium ),
    mrDocShell( rDocShell ),
    mrDocument( *rDocShell.GetDoc() ),
    mxModel( rDocShell.GetModel() ),
    mpProgress( NULL ),
    mbIsDraw( rDocShell.GetDocumentType() == DOCUMENT_TYPE_DRAW ),
    mbShowProgress( bShowProgress )
{
}

// -----------------------------------------------------------------------------

SdFilter::~SdFilter()
{
    if( !mrDocShell.HasSpecialProgress() )
        delete mpProgress;
}

// -----------------------------------------------------------------------------

::rtl::OUString SdFilter::ImplGetFullLibraryName( const ::rtl::OUString& rLibraryName ) const
{
    String aTemp( ::rtl::OUString::createFromAscii( SVLIBRARY( "?" ) ) );
    xub_StrLen nIndex = aTemp.Search( (sal_Unicode)'?' );
    aTemp.Replace( nIndex, 1, rLibraryName );
    ::rtl::OUString aLibraryName( aTemp );
    return aLibraryName;
}

// -----------------------------------------------------------------------------

::vos::OModule* SdFilter::OpenLibrary( const ::rtl::OUString& rLibraryName ) const
{
    ::rtl::OUString aDest;
    ::rtl::OUString aNormalizedPath;
    ::vos::OModule* pRet;

    if ( ::osl::FileBase::getFileURLFromSystemPath( SvtPathOptions().GetModulePath(), aDest ) != ::osl::FileBase::E_None )
        aDest = SvtPathOptions().GetModulePath();
    aDest += ::rtl::OUString( sal_Unicode( '/' ) );
    aDest += ::rtl::OUString( ImplGetFullLibraryName( rLibraryName ) );
    ::osl::FileBase::getSystemPathFromFileURL( aDest, aNormalizedPath );

    if( !( pRet = new ::vos::OModule( aNormalizedPath ) )->isLoaded() )
        delete pRet, pRet = NULL;

    return pRet;
}

// -----------------------------------------------------------------------------

void SdFilter::CreateStatusIndicator()
{
    // The status indicator must be retrieved from the provided medium arguments
    const SfxUnoAnyItem* pStatusBarItem = static_cast<const SfxUnoAnyItem*>(
            mrMedium.GetItemSet()->GetItem(SID_PROGRESS_STATUSBAR_CONTROL) );

    if ( pStatusBarItem )
        pStatusBarItem->GetValue() >>= mxStatusIndicator;

//  try
//  {
//      if (mxModel.is())
//      {
//          Reference< XController > xController( mxModel->getCurrentController());
//          if( xController.is())
//          {
//              Reference< XFrame > xFrame( xController->getFrame());
//              if( xFrame.is())
//              {
//                  Reference< XStatusIndicatorFactory > xFactory( xFrame, UNO_QUERY );
//                  if( xFactory.is())
//                  {
//                      mxStatusIndicator = xFactory->createStatusIndicator();
//                  }
//              }
//          }
//      }
//  }
//  catch( Exception& )
//  {
//  }
}

// -----------------------------------------------------------------------------

void SdFilter::CreateProgress()
{
    if( mrDocShell.HasSpecialProgress() )
        mpProgress = mrDocShell.GetSpecialProgress();
    else
    {
        mpProgress = new SfxProgress( &mrDocShell, String( SdResId( STR_OPEN_DOCUMENT ) ), 100 );
        mpProgress->SetState( 0, 100 );
    }
}

<commit_msg>INTEGRATION: CWS aw024 (1.10.12); FILE MERGED 2006/09/21 22:47:47 aw 1.10.12.4: RESYNC: (1.12-1.13); FILE MERGED 2005/11/18 14:18:07 aw 1.10.12.3: RESYNC: (1.11-1.12); FILE MERGED 2005/09/17 10:26:06 aw 1.10.12.2: RESYNC: (1.10-1.11); FILE MERGED 2005/08/04 14:49:36 sj 1.10.12.1: #48467# using GraphicExporter component for exports, graphic filter progress now works now via xStatusIndicater instead of callback mechanism<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: sdfilter.cxx,v $
 *
 *  $Revision: 1.14 $
 *
 *  last change: $Author: ihi $ $Date: 2006-11-14 14:22:10 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

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

#ifndef _COM_SUN_STAR_TASK_XSTATUSINDICATORFACTORY_HPP_
#include <com/sun/star/task/XStatusIndicatorFactory.hpp>
#endif

#include <tools/debug.hxx>
#include <osl/file.hxx>
#include <vos/module.hxx>
#include <svtools/pathoptions.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/progress.hxx>

#ifndef _SFXITEMSET_HXX
#include <svtools/itemset.hxx>
#endif

#ifndef MAC
#ifndef SVX_LIGHT
#ifndef SD_DRAW_DOC_SHELL_HXX
#include "../ui/inc/DrawDocShell.hxx"
#endif
#include "../ui/inc/strings.hrc"
#endif //!SVX_LIGHT
#else  //MAC
#ifndef SVX_LIGHT
#ifndef SD_DRAW_DOC_SHELL_HXX
#include "DrawDocShell.hxx"
#endif
#include "strings.hrc"
#endif //!SVX_LIGHT
#endif //!MAC

#include "sdresid.hxx"
#include "pres.hxx"
#include "drawdoc.hxx"
#include "sdfilter.hxx"

// --------------
// - Namespaces -
// --------------

using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::task;
using namespace ::com::sun::star::frame;

// ------------
// - SdFilter -
// ------------

SdFilter::SdFilter( SfxMedium& rMedium, ::sd::DrawDocShell& rDocShell, sal_Bool bShowProgress ) :
    mrMedium( rMedium ),
    mrDocShell( rDocShell ),
    mrDocument( *rDocShell.GetDoc() ),
    mxModel( rDocShell.GetModel() ),
    mbIsDraw( rDocShell.GetDocumentType() == DOCUMENT_TYPE_DRAW ),
    mbShowProgress( bShowProgress )
{
}

// -----------------------------------------------------------------------------

SdFilter::~SdFilter()
{
}

// -----------------------------------------------------------------------------

::rtl::OUString SdFilter::ImplGetFullLibraryName( const ::rtl::OUString& rLibraryName ) const
{
    String aTemp( ::rtl::OUString::createFromAscii( SVLIBRARY( "?" ) ) );
    xub_StrLen nIndex = aTemp.Search( (sal_Unicode)'?' );
    aTemp.Replace( nIndex, 1, rLibraryName );
    ::rtl::OUString aLibraryName( aTemp );
    return aLibraryName;
}

// -----------------------------------------------------------------------------

::vos::OModule* SdFilter::OpenLibrary( const ::rtl::OUString& rLibraryName ) const
{
    ::rtl::OUString aDest;
    ::rtl::OUString aNormalizedPath;
    ::vos::OModule* pRet;

    if ( ::osl::FileBase::getFileURLFromSystemPath( SvtPathOptions().GetModulePath(), aDest ) != ::osl::FileBase::E_None )
        aDest = SvtPathOptions().GetModulePath();
    aDest += ::rtl::OUString( sal_Unicode( '/' ) );
    aDest += ::rtl::OUString( ImplGetFullLibraryName( rLibraryName ) );
    ::osl::FileBase::getSystemPathFromFileURL( aDest, aNormalizedPath );

    if( !( pRet = new ::vos::OModule( aNormalizedPath ) )->isLoaded() )
        delete pRet, pRet = NULL;

    return pRet;
}

// -----------------------------------------------------------------------------

void SdFilter::CreateStatusIndicator()
{
    // The status indicator must be retrieved from the provided medium arguments
    const SfxUnoAnyItem* pStatusBarItem = static_cast<const SfxUnoAnyItem*>(
            mrMedium.GetItemSet()->GetItem(SID_PROGRESS_STATUSBAR_CONTROL) );

    if ( pStatusBarItem )
        pStatusBarItem->GetValue() >>= mxStatusIndicator;

//  try
//  {
//      if (mxModel.is())
//      {
//          Reference< XController > xController( mxModel->getCurrentController());
//          if( xController.is())
//          {
//              Reference< XFrame > xFrame( xController->getFrame());
//              if( xFrame.is())
//              {
//                  Reference< XStatusIndicatorFactory > xFactory( xFrame, UNO_QUERY );
//                  if( xFactory.is())
//                  {
//                      mxStatusIndicator = xFactory->createStatusIndicator();
//                  }
//              }
//          }
//      }
//  }
//  catch( Exception& )
//  {
//  }
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: BreakDlg.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: obo $ $Date: 2004-01-20 11:29:55 $
 *
 *  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 SD_BREAK_DLG_HXX
#define SD_BREAK_DLG_HXX

#ifndef _SV_GROUP_HXX //autogen
#include <vcl/group.hxx>
#endif
#ifndef _SV_BUTTON_HXX //autogen
#include <vcl/button.hxx>
#endif
#ifndef _SVX_DLG_CTRL_HXX //autogen
#include <svx/dlgctrl.hxx>
#endif
#ifndef _SV_FIELD_HXX //autogen
#include <vcl/field.hxx>
#endif
#ifndef _SV_FIXED_HXX //autogen
#include <vcl/fixed.hxx>
#endif
#ifndef _PRGSBAR_HXX
#include <svtools/prgsbar.hxx>
#endif
#ifndef _SV_EDIT_HXX
#include <vcl/edit.hxx>
#endif
#ifndef _STDCTRL_HXX
#include <svtools/stdctrl.hxx>
#endif

#ifndef _BASEDLGS_HXX //autogen
#include <sfx2/basedlgs.hxx>
#endif

class SvdProgressInfo;
class SfxProgress;

namespace sd {

class DrawDocShell;
class DrawView;

/*************************************************************************
|*
|* Dialog zum aufbrechen von Metafiles
|*
\************************************************************************/
class BreakDlg
    : public SfxModalDialog
{
public:
    BreakDlg (
        ::Window* pWindow,
        DrawView* pDrView,
        DrawDocShell* pShell,
        ULONG nSumActionCount,
        ULONG nObjCount);
    virtual ~BreakDlg();

    short Execute();

private:
    FixedText       aFtObjInfo;
    FixedText       aFtActInfo;
    FixedText       aFtInsInfo;

    FixedInfo       aFiObjInfo;
    FixedInfo       aFiActInfo;
    FixedInfo       aFiInsInfo;

    CancelButton    aBtnCancel;
    DrawView*   pDrView;

    BOOL            bCancel;

    Timer           aTimer;
    SvdProgressInfo *pProgrInfo;
    Link            aLink;
    SfxProgress     *mpProgress;

    DECL_LINK( CancelButtonHdl, void* );
    DECL_LINK( UpDate, void* );
    DECL_LINK( InitialUpdate, Timer* );
};

} // end of namespace sd

#endif
<commit_msg>INTEGRATION: CWS ooo19126 (1.2.562); FILE MERGED 2005/09/05 13:22:37 rt 1.2.562.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: BreakDlg.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 05:02:12 $
 *
 *  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 SD_BREAK_DLG_HXX
#define SD_BREAK_DLG_HXX

#ifndef _SV_GROUP_HXX //autogen
#include <vcl/group.hxx>
#endif
#ifndef _SV_BUTTON_HXX //autogen
#include <vcl/button.hxx>
#endif
#ifndef _SVX_DLG_CTRL_HXX //autogen
#include <svx/dlgctrl.hxx>
#endif
#ifndef _SV_FIELD_HXX //autogen
#include <vcl/field.hxx>
#endif
#ifndef _SV_FIXED_HXX //autogen
#include <vcl/fixed.hxx>
#endif
#ifndef _PRGSBAR_HXX
#include <svtools/prgsbar.hxx>
#endif
#ifndef _SV_EDIT_HXX
#include <vcl/edit.hxx>
#endif
#ifndef _STDCTRL_HXX
#include <svtools/stdctrl.hxx>
#endif

#ifndef _BASEDLGS_HXX //autogen
#include <sfx2/basedlgs.hxx>
#endif

class SvdProgressInfo;
class SfxProgress;

namespace sd {

class DrawDocShell;
class DrawView;

/*************************************************************************
|*
|* Dialog zum aufbrechen von Metafiles
|*
\************************************************************************/
class BreakDlg
    : public SfxModalDialog
{
public:
    BreakDlg (
        ::Window* pWindow,
        DrawView* pDrView,
        DrawDocShell* pShell,
        ULONG nSumActionCount,
        ULONG nObjCount);
    virtual ~BreakDlg();

    short Execute();

private:
    FixedText       aFtObjInfo;
    FixedText       aFtActInfo;
    FixedText       aFtInsInfo;

    FixedInfo       aFiObjInfo;
    FixedInfo       aFiActInfo;
    FixedInfo       aFiInsInfo;

    CancelButton    aBtnCancel;
    DrawView*   pDrView;

    BOOL            bCancel;

    Timer           aTimer;
    SvdProgressInfo *pProgrInfo;
    Link            aLink;
    SfxProgress     *mpProgress;

    DECL_LINK( CancelButtonHdl, void* );
    DECL_LINK( UpDate, void* );
    DECL_LINK( InitialUpdate, Timer* );
};

} // end of namespace sd

#endif
<|endoftext|>


<commit_before>#include <string>
#include <cassert>
#include <cstdarg>
#include <libport/cstdlib>
#include <iostream>
#include <stdexcept>

#include <sdk/config.h>

#include <libport/cli.hh>
#include <libport/containers.hh>
#include <libport/file-system.hh>
#include <libport/foreach.hh>
#include <libport/path.hh>
#include <libport/package-info.hh>
#include <libport/program-name.hh>
#include <libport/sysexits.hh>
#include <libport/unistd.h>
#include <libport/windows.hh>
#include <libport/option-parser.hh>
#include <libport/xltdl.hh>

#include <urbi/exit.hh>
#include <urbi/package-info.hh>
#include <urbi/uclient.hh>

using namespace urbi;
using libport::program_name;

// List of module names.
typedef std::list<std::string> modules_type;

static UCallbackAction
onError(const UMessage& msg)
{
  std::cerr << program_name()
            << ": load module error: " << msg.message << std::endl;
  return URBI_CONTINUE;
}

static UCallbackAction
onDone(const UMessage&)
{
  ::exit(0);
}

static int
connect_plugin(const std::string& host, int port, const modules_type& modules)
{
  UClient cl(host, port);
  if (cl.error())
    // UClient already displayed an error message.
    ::exit(1);
  cl.setErrorCallback(callback(&onError));
  cl.setCallback(callback(&onDone), "output");
  foreach (const std::string& m, modules)
    cl << "loadModule(\"" << m << "\");";
  cl << "output << 1;";
  while (true)
    sleep(1);
  return 0;
}

static void
usage(libport::OptionParser& parser)
{
  std::cout <<
    "usage: " << program_name() <<
    " [OPTIONS] MODULE_NAMES ... [-- UOPTIONS...]\n"
    "Start an UObject in either remote or plugin mode.\n"
              << parser <<
    "\n"
    "MODULE_NAMES is a list of modules.\n"
    "UOPTIONS are passed to urbi::main in remote and start modes.\n"
    "\n"
    "Exit values:\n"
    "  0  success\n"
    " " << EX_NOINPUT << "  some of the MODULES are missing\n"
    " " << EX_OSFILE << "  libuobject is missing\n"
    "  *  other kinds of errors\n"
    ;
  ::exit(EX_OK);
}

static
void
version()
{
  std::cout << urbi::package_info() << std::endl
            << libport::exit(EX_OK);
}

static
std::string
absolute(const std::string& s)
{
  libport::path p = s;
  if (!p.absolute_get())
    p = libport::get_current_directory() / p;
  return p.to_string();
}

static
int
ltdebug(unsigned verbosity, unsigned level, const char* format, va_list args)
{
  int errors = 0;
  if (level <= verbosity)
  {
    errors += fprintf(stderr, "%s: ", program_name().c_str()) < 0;
    errors += vfprintf(stderr, format, args) < 0;
  }
  return errors;
}

typedef int (*umain_type)(const libport::cli_args_type& args,
                          bool block, bool errors);
int
main(int argc, char* argv[])
{
  libport::program_initialize(argc, argv);
  unsigned verbosity = 0;
  libport::path urbi_root = libport::xgetenv("URBI_ROOT", URBI_ROOT);

  enum ConnectMode
  {
    /// Start a new engine and plug the module
    MODE_PLUGIN_START,
    /// Load the module in a running engine as a plugin
    MODE_PLUGIN_LOAD,
    /// Connect the module to a running engine (remote uobject)
    MODE_REMOTE
  };
  ConnectMode connect_mode = MODE_REMOTE;
  /// Core dll to use.
  std::string dll;
  /// Server host name.
  std::string host = "localhost";
  /// Server port.
  int port = urbi::UClient::URBI_PORT;
  // The list of modules.
  modules_type modules;

  // The options passed to urbi::main.
  libport::cli_args_type args;
  libport::cli_args_type args4modules;
  args << argv[0];

  libport::OptionValue
    arg_custom("start using the shared library FILE", "custom", 'c', "FILE"),
    arg_debug("increase verbosity for debug", "debug", 0, "N"),
    arg_pfile("file containing the port to listen to", "port-file", 0, "FILE");
  libport::OptionFlag
    arg_plugin("start as a plugin uobject on a running server", "plugin", 'p'),
    arg_remote("start as a remote uobject", "remote", 'r'),
    arg_start("start an urbi server and connect as plugin", "start", 's');
  libport::OptionsEnd arg_end;

  libport::OptionParser opt_parser;
  opt_parser << "Urbi-Launch options:"
	     << libport::opts::help
	     << libport::opts::version
	     << arg_custom
	     << arg_debug
	     << "Mode selection:"
	     << arg_plugin
	     << arg_remote
	     << arg_start
	     << "Urbi-Launch options for plugin mode:"
	     << libport::opts::host
	     << libport::opts::port
	     << arg_pfile
	     << arg_end;

  try
  {
    args4modules = opt_parser(libport::program_arguments());
  }
  catch (libport::Error& e)
  {
    const libport::Error::errors_type& err = e.errors();
    foreach (std::string wrong_arg, err)
      libport::invalid_option(wrong_arg);
  }
  foreach (std::string& mod_arg, args4modules)
    modules << absolute(mod_arg);

  if (libport::opts::version.get())
    version();
  if (libport::opts::help.get())
    usage(opt_parser);
  if (arg_custom.filled())
    dll = arg_custom.value();
  if (arg_debug.filled())
    verbosity = arg_debug.get<unsigned>(1);
  if (libport::opts::host.filled())
  {
    host = libport::opts::host.value();
    args << "--host" << host;
  }
  if (arg_plugin.get())
    connect_mode = MODE_PLUGIN_LOAD;
  if (libport::opts::port.filled())
  {
    port = libport::opts::port.get<int>();
    args << "--port" << libport::opts::port.value();
  }
  if (arg_pfile.filled())
  {
    std::string my_arg = arg_pfile.value();
    port = libport::file_contents_get<int>(my_arg);
    args << "--port-file" << my_arg;
  }
  if (arg_remote.get())
    connect_mode = MODE_REMOTE;
  if (arg_start.get())
    connect_mode = MODE_PLUGIN_START;
  args.insert(args.end(), arg_end.get().begin(), arg_end.get().end());

  if (connect_mode == MODE_PLUGIN_LOAD)
    return connect_plugin(host, port, modules);

  if (dll.empty())
    dll = urbi_root / "gostai" / "core" / URBI_HOST /
      (connect_mode == MODE_REMOTE ? "remote" : "engine") / "libuobject";

  /* The two other modes are handled the same way:
   * -Dlopen the correct libuobject.
   * -Dlopen the uobjects to load.
   * -Call urbi::main found by dlsym() in libuobject.
   */
  lt_dladd_log_function((lt_dllog_function*) &ltdebug, (void*) verbosity);
  lt_dlinit();
  lt_dlhandle core = libport::xlt_dlopenext(dll, true, EX_OSFILE, verbosity);
  foreach (const std::string& s, modules)
    libport::xlt_dlopenext(s, false, EX_NOINPUT);

  umain_type umain = libport::xlt_dlsym<umain_type>(core, "urbi_main_args");
  umain(args, true, true);
}
<commit_msg>urbi-launch: refactoring.<commit_after>#include <string>
#include <cassert>
#include <cstdarg>
#include <libport/cstdlib>
#include <iostream>
#include <stdexcept>

#include <sdk/config.h>

#include <libport/cli.hh>
#include <libport/containers.hh>
#include <libport/file-system.hh>
#include <libport/foreach.hh>
#include <libport/path.hh>
#include <libport/package-info.hh>
#include <libport/program-name.hh>
#include <libport/sysexits.hh>
#include <libport/unistd.h>
#include <libport/windows.hh>
#include <libport/option-parser.hh>
#include <libport/xltdl.hh>

#include <urbi/exit.hh>
#include <urbi/package-info.hh>
#include <urbi/uclient.hh>

using namespace urbi;
using libport::program_name;

// List of module names.
typedef std::list<std::string> modules_type;

static UCallbackAction
onError(const UMessage& msg)
{
  std::cerr << program_name()
            << ": load module error: " << msg.message << std::endl;
  return URBI_CONTINUE;
}

static UCallbackAction
onDone(const UMessage&)
{
  ::exit(0);
}

static int
connect_plugin(const std::string& host, int port, const modules_type& modules)
{
  UClient cl(host, port);
  if (cl.error())
    // UClient already displayed an error message.
    ::exit(1);
  cl.setErrorCallback(callback(&onError));
  cl.setCallback(callback(&onDone), "output");
  foreach (const std::string& m, modules)
    cl << "loadModule(\"" << m << "\");";
  cl << "output << 1;";
  while (true)
    sleep(1);
  return 0;
}

static void
usage(libport::OptionParser& parser)
{
  std::cout <<
    "usage: " << program_name() <<
    " [OPTIONS] MODULE_NAMES ... [-- UOPTIONS...]\n"
    "Start an UObject in either remote or plugin mode.\n"
              << parser <<
    "\n"
    "MODULE_NAMES is a list of modules.\n"
    "UOPTIONS are passed to urbi::main in remote and start modes.\n"
    "\n"
    "Exit values:\n"
    "  0  success\n"
    " " << EX_NOINPUT << "  some of the MODULES are missing\n"
    " " << EX_OSFILE << "  libuobject is missing\n"
    "  *  other kinds of errors\n"
    ;
  ::exit(EX_OK);
}

static
void
version()
{
  std::cout << urbi::package_info() << std::endl
            << libport::exit(EX_OK);
}

static
std::string
absolute(const std::string& s)
{
  libport::path p = s;
  if (!p.absolute_get())
    p = libport::get_current_directory() / p;
  return p.to_string();
}

static
int
ltdebug(unsigned verbosity, unsigned level, const char* format, va_list args)
{
  int errors = 0;
  if (level <= verbosity)
  {
    errors += fprintf(stderr, "%s: ", program_name().c_str()) < 0;
    errors += vfprintf(stderr, format, args) < 0;
  }
  return errors;
}

typedef int (*umain_type)(const libport::cli_args_type& args,
                          bool block, bool errors);
int
main(int argc, char* argv[])
{
  libport::program_initialize(argc, argv);
  unsigned verbosity = 0;

  enum ConnectMode
  {
    /// Start a new engine and plug the module
    MODE_PLUGIN_START,
    /// Load the module in a running engine as a plugin
    MODE_PLUGIN_LOAD,
    /// Connect the module to a running engine (remote uobject)
    MODE_REMOTE
  };
  ConnectMode connect_mode = MODE_REMOTE;
  /// Core dll to use.
  std::string dll;
  /// Server host name.
  std::string host = "localhost";
  /// Server port.
  int port = urbi::UClient::URBI_PORT;
  // The list of modules.
  modules_type modules;

  // The options passed to urbi::main.
  libport::cli_args_type args;
  libport::cli_args_type args4modules;
  args << argv[0];

  libport::OptionValue
    arg_custom("start using the shared library FILE", "custom", 'c', "FILE"),
    arg_debug("increase verbosity for debug", "debug", 0, "N"),
    arg_pfile("file containing the port to listen to", "port-file", 0, "FILE");
  libport::OptionFlag
    arg_plugin("start as a plugin uobject on a running server", "plugin", 'p'),
    arg_remote("start as a remote uobject", "remote", 'r'),
    arg_start("start an urbi server and connect as plugin", "start", 's');
  libport::OptionsEnd arg_end;

  libport::OptionParser opt_parser;
  opt_parser << "Urbi-Launch options:"
	     << libport::opts::help
	     << libport::opts::version
	     << arg_custom
	     << arg_debug
	     << "Mode selection:"
	     << arg_plugin
	     << arg_remote
	     << arg_start
	     << "Urbi-Launch options for plugin mode:"
	     << libport::opts::host
	     << libport::opts::port
	     << arg_pfile
	     << arg_end;

  try
  {
    args4modules = opt_parser(libport::program_arguments());
  }
  catch (libport::Error& e)
  {
    const libport::Error::errors_type& err = e.errors();
    foreach (std::string wrong_arg, err)
      libport::invalid_option(wrong_arg);
  }
  foreach (std::string& mod_arg, args4modules)
    modules << absolute(mod_arg);

  if (libport::opts::version.get())
    version();
  if (libport::opts::help.get())
    usage(opt_parser);
  if (arg_custom.filled())
    dll = arg_custom.value();
  if (arg_debug.filled())
    verbosity = arg_debug.get<unsigned>(1);
  if (libport::opts::host.filled())
  {
    host = libport::opts::host.value();
    args << "--host" << host;
  }
  if (arg_plugin.get())
    connect_mode = MODE_PLUGIN_LOAD;
  if (libport::opts::port.filled())
  {
    port = libport::opts::port.get<int>();
    args << "--port" << libport::opts::port.value();
  }
  if (arg_pfile.filled())
  {
    std::string my_arg = arg_pfile.value();
    port = libport::file_contents_get<int>(my_arg);
    args << "--port-file" << my_arg;
  }
  if (arg_remote.get())
    connect_mode = MODE_REMOTE;
  if (arg_start.get())
    connect_mode = MODE_PLUGIN_START;
  args.insert(args.end(), arg_end.get().begin(), arg_end.get().end());

  if (connect_mode == MODE_PLUGIN_LOAD)
    return connect_plugin(host, port, modules);

  libport::path urbi_root = libport::xgetenv("URBI_ROOT", URBI_ROOT);
  libport::path coredir = urbi_root / "gostai" / "core" / URBI_HOST;
  if (dll.empty())
    dll = (coredir
           / (connect_mode == MODE_REMOTE ? "remote" : "engine")
           / "libuobject");

  /* The two other modes are handled the same way:
   * -Dlopen the correct libuobject.
   * -Dlopen the uobjects to load.
   * -Call urbi::main found by dlsym() in libuobject.
   */
  lt_dladd_log_function((lt_dllog_function*) &ltdebug, (void*) verbosity);
  lt_dlinit();
  lt_dlhandle core = libport::xlt_dlopenext(dll, true, EX_OSFILE, verbosity);
  foreach (const std::string& s, modules)
    libport::xlt_dlopenext(s, false, EX_NOINPUT);

  umain_type umain = libport::xlt_dlsym<umain_type>(core, "urbi_main_args");
  umain(args, true, true);
}
<|endoftext|>


<commit_before>#include "messages.h"

qint64  Messages::FileSendingContext::transferID;
QMap<qint64, std::shared_ptr<Messages::FileSendingContext>> Messages::FileSendingContext::transfers;

qint64  Messages::FileReceivingContext::transferID;
QMap<qint64, std::shared_ptr<Messages::FileReceivingContext>> Messages::FileReceivingContext::transfers;

Messages::Messages(peer *peerToConnect = nullptr, QObject *parent) : QObject(parent), mPeer(peerToConnect)
{
    //here we create peerconnection session
}

Messages::~Messages()
{

}

Messages::ArmaMessage Messages::createRegularMessage(Session & session, const QString & message) {
	return addMessageHeader(session, message.toUtf8(), Messages::MsgType::RegularMessage, Messages::MsgType::RegularMessageDH);
}

Messages::ArmaMessage Messages::createLoginMessage(QString & name, const QString & password, int port, bool reg) {
    //TODO: certificate and port
	ArmaMessage ret;
    ret.append(reg ? "r" : "l");
    ret.append(Messages::armaSeparator);
	ret.append(name.toUtf8().toBase64());
	ret.append(Messages::armaSeparator);
	ret.append(password.toUtf8().toBase64());
    ret.append(Messages::armaSeparator);
    ret.append(QString::number(port).toUtf8().toBase64());
	return ret;
}

bool Messages::isJsonMessage(const ArmaMessage& message) {
	return !QJsonDocument::fromJson(message).isNull();
}

bool Messages::parseJsonUsers(ArmaMessage &message, QList<peer>& usersList) {
	usersList.clear();
	QJsonDocument jsonDoc = QJsonDocument::fromJson(message);
	if (jsonDoc.isNull()) {
		return false;
	}
	QJsonObject jsonObject = jsonDoc.object();
	if (jsonObject["users"].isArray()) {
		QJsonArray users = jsonObject["users"].toArray();
		foreach (QJsonValue user, users)
		{
			QJsonObject userObject = user.toObject();
			peer p;
			p.address = userObject["address"].toString();
			p.name = userObject["nick"].toString();
			p.listeningPort = userObject["port"].toInt();
			usersList.append(p);
		}
	}
	else {
		return false;
	}
	return true;
}

bool Messages::parseMessage(std::function<Session &(QString & name)> sessions, const ArmaMessage & message, std::function<void(Session &, MsgType, const ReceivedMessage &)> callback) {
	QString senderNick, receiverNick;
	QByteArray dh;
    QDateTime timestamp;
    MsgType type;

    QList<QByteArray> list = message.split(armaSeparator);

    if (list.size() < 5) throw MessageException("incomplete message");

    senderNick = QString::fromUtf8(QByteArray::fromBase64(list[0]));
    receiverNick = QString::fromUtf8(QByteArray::fromBase64(list[1]));

	Session & session = sessions(senderNick);
	if (session.getMyName() != receiverNick) throw MessageException("Message not for this client.");

	ReceivedMessage parsedMessage;
    timestamp.setMSecsSinceEpoch(list[2].toLongLong());
    parsedMessage.timestamp = timestamp;

    type = static_cast<MsgType>(list[3][0] - 'A');

    QByteArray messageText;

    if(type == Messages::MsgType::PureDH)
    {
        dh = QByteArray::fromBase64(list[4]);

        SessionKey& sk = session.getKey();

        int contextDataLength = list[0].size() + list[1].size() + list[2].size() + list[3].size() + list[4].size() + 5;
        QByteArray messageText;
        try {
            QByteArray a1 = message.left(contextDataLength);
            QByteArray a2 = message.right(message.length() - contextDataLength);
            messageText = sk.unprotect(a2, a1);
        }
        catch (KryptoException e) {
            return false;
        }
        sk.setDH(dh);
        sk.generateKey();

        parsedMessage.messageText = messageText;
		return true;
    }
    else if (type % 2) {
		if (list.size() < 6) throw MessageException("incomplete message");
		dh = QByteArray::fromBase64(list[4]);

		SessionKey& sk = session.getKey();

		int contextDataLength = list[0].size() + list[1].size() + list[2].size() + list[3].size() + list[4].size() + 5;
		QByteArray messageText;
		try {
			QByteArray a1 = message.left(contextDataLength);
			QByteArray a2 = message.right(message.length() - contextDataLength);
			messageText = sk.unprotect(a2, a1);
		}
		catch (KryptoException e) {
			return false;
		}
		sk.setDH(dh);
		sk.generateKey();

		parsedMessage.messageText = messageText;
	}
    //regularMessage
	else {

        SessionKey& sk = session.getKey();
        int contextDataLength = list[0].size() + list[1].size() + list[2].size() + list[3].size() + 4; //number of separators
        try{
            QByteArray a1 = message.left(contextDataLength);
            QByteArray a2 = message.right(message.length() - contextDataLength);
            messageText = sk.unprotect(a2, a1);
        }
        catch (KryptoException e) {
            return false;
        }
        parsedMessage.messageText = messageText;
    }

	callback(session, type, parsedMessage);
    return true;
}

QByteArray Messages::addMessageHeader(Session & session, const QByteArray & payload, Messages::MsgType type, Messages::MsgType typeDH) {
	QByteArray ret;
	SessionKey & key = session.getKey();

	ret.append(session.getMyName().toUtf8().toBase64());
	ret.append(Messages::armaSeparator);
	ret.append(session.getPartnerName().toUtf8().toBase64());
	ret.append(Messages::armaSeparator);
	ret.append(QString::number(QDateTime::currentMSecsSinceEpoch()));
	ret.append(Messages::armaSeparator);

	QByteArray dh = key.conditionalGetDH();
	if (dh.length() > 0) {
		ret.append('A' + typeDH);
		ret.append(Messages::armaSeparator);
		ret.append(dh.toBase64());
	}
	else {
		ret.append('A' + type);
	}
	ret.append(Messages::armaSeparator);

	ret.append(key.protect(payload, ret));

	if (dh.length() > 0) key.generateKey();
	return ret;
}

void Messages::FileSendingContext::sendFile(Session & s, const QString & path, std::function<void(const QByteArray &)> sender) {
	QByteArray payload;
	auto it = transfers.insert(++transferID, std::shared_ptr<FileSendingContext>(new FileSendingContext(s, path, sender)));

	payload.append(QByteArray::number(transferID));
	payload.append(Messages::armaSeparator);
	payload.append(QByteArray::number((*it)->fileSize));

	sender(Messages::addMessageHeader(s, payload, MsgType::FileContext, MsgType::FileContextDH));
}

void Messages::FileSendingContext::confirmFile(Session & s, const QByteArray & response) {
	QList<QByteArray> list = response.split(Messages::armaSeparator);

	qint64 id = list[0].toLongLong();
	auto it = transfers.find(id);
	(*it)->destID = list[1].toLongLong();
	(*it)->startSending();
}

void Messages::FileReceivingContext::receiveFile(Session & s, const QByteArray & payload, std::function<void(const QByteArray &)> sender) {
	QList<QByteArray> list = payload.split(Messages::armaSeparator);
	qint64 id = list[0].toLongLong();
	qint64 size = list[1].toLongLong();

	QString path = "downloads/";
	path.append(QString::number(++transferID));
	path.append(".rec");

	auto it = transfers.insert(transferID, std::shared_ptr<FileReceivingContext>(new FileReceivingContext(s, path)));

	QByteArray response;
	response.append(QByteArray::number(id));
	response.append(Messages::armaSeparator);
	response.append(QByteArray::number(transferID));

	if(sender) sender(Messages::addMessageHeader(s, response, MsgType::FileResponse, MsgType::FileResponseDH));
	else s.send(Messages::addMessageHeader(s, response, MsgType::FileResponse, MsgType::FileResponseDH));
}

void Messages::FileReceivingContext::receiveChunk(Session & s, const QByteArray & payload) {
	QList<QByteArray> list = payload.split(Messages::armaSeparator);

	qint64 id = list[0].toLongLong();
	qint64 start = list[1].toLongLong();
	qint64 len = list[2].toLongLong();

	auto it = transfers.find(id);
	(*it)->parseChunk(start, len, payload.right(payload.length() - (list[0].length() + list[1].length() + list[2].length() + 3)));
}

Messages::FileSendingContext::FileSendingContext(Session & session, QString path, std::function<void(const QByteArray &)> dataSender) : session(session), path(path), dataSender(dataSender) {
	QFile file(path);
	if(!file.open(QIODevice::ReadWrite)) throw MessageException("Unable to open file!");
	fileSize = file.size();
	file.close();
}

bool Messages::FileSendingContext::startSending() {
	qint64 chunks = (fileSize - 1) / Messages::maxChunkSize + 1;
	qint64 threads = std::min(chunks, maxThreads);
	qint64 done = 0;

	for (qint64 i = 0; i < threads; ++i) {
		workers.push_back(Worker(session, destID, path, dataSender));

		// Load balancer
		qint64 cChunks = ((chunks - 1) / threads + (((chunks - 1) % threads < i) ? 0 : 1));
		qint64 start = done * Messages::maxChunkSize;
		done += cChunks;
		qint64 len = (i == threads - 1) ? (fileSize - start) : (cChunks * Messages::maxChunkSize);

		futures.push_back(QtConcurrent::run(workers.back(), start, len));
	}
	return true;
}

void Messages::FileSendingContext::Worker::operator()(qint64 gstart, qint64 glen) {
	QFile file(path);
	file.open(QIODevice::ReadOnly);
	file.seek(gstart);

	do {
		qint64 len = std::min(glen, maxChunkSize);
		qint64 start = file.pos();
		glen -= len;

		QByteArray payload;
		payload.append(QString::number(destID));
		payload.append(Messages::armaSeparator);
		payload.append(QString::number(start));
		payload.append(Messages::armaSeparator);
		payload.append(QString::number(len));
		payload.append(Messages::armaSeparator);
		payload.append(file.read(len));

		QByteArray ret = addMessageHeader(session, payload, Messages::MsgType::FileMessage, Messages::MsgType::FileMessageDH);

		dataSender(ret);
	} while (glen > 0);
	file.close();
}

Messages::FileReceivingContext::FileReceivingContext(Session & session, QString path) : session(session), path(path) {
	QFile file(path);
	if (!file.open(QIODevice::ReadWrite)) throw MessageException("Unable to open file!");
	fileSize = file.size();
	file.close();
}

void Messages::FileReceivingContext::parseChunk(qint64 start, qint64 len, const QByteArray & data) {
	workers.push_back(Worker(session, path, fileSize));
	futures.push_back(QtConcurrent::run(workers.back(), start, len, data));
}

void Messages::FileReceivingContext::parseChunk(const QByteArray & data) {
	QList<QByteArray> list = data.split(Messages::armaSeparator);

	qint64 start = list[0].toLongLong();
	qint64 len = list[1].toLongLong();

	parseChunk(start, len, data.right(data.length() - (list[0].length() + list[1].length() + 2)));
}

void Messages::FileReceivingContext::Worker::operator()(qint64 start, qint64 len, QByteArray data) {

	//if (start + len > fileSize) throw MessageException("File chunk out of range.");

	QFile file(path);
	file.open(QIODevice::ReadWrite);
	file.seek(start);
	file.write(data);
	file.close();
}
<commit_msg>gcc compatibility<commit_after>#include "messages.h"

const char Messages::armaSeparator;
const qint64 Messages::maxThreads;
const qint64 Messages::maxChunkSize;

qint64  Messages::FileSendingContext::transferID;
QMap<qint64, std::shared_ptr<Messages::FileSendingContext>> Messages::FileSendingContext::transfers;

qint64  Messages::FileReceivingContext::transferID;
QMap<qint64, std::shared_ptr<Messages::FileReceivingContext>> Messages::FileReceivingContext::transfers;

Messages::Messages(peer *peerToConnect = nullptr, QObject *parent) : QObject(parent), mPeer(peerToConnect)
{
    //here we create peerconnection session
}

Messages::~Messages()
{

}

Messages::ArmaMessage Messages::createRegularMessage(Session & session, const QString & message) {
	return addMessageHeader(session, message.toUtf8(), Messages::MsgType::RegularMessage, Messages::MsgType::RegularMessageDH);
}

Messages::ArmaMessage Messages::createLoginMessage(QString & name, const QString & password, int port, bool reg) {
    //TODO: certificate and port
	ArmaMessage ret;
    ret.append(reg ? "r" : "l");
    ret.append(Messages::armaSeparator);
	ret.append(name.toUtf8().toBase64());
	ret.append(Messages::armaSeparator);
	ret.append(password.toUtf8().toBase64());
    ret.append(Messages::armaSeparator);
    ret.append(QString::number(port).toUtf8().toBase64());
	return ret;
}

bool Messages::isJsonMessage(const ArmaMessage& message) {
	return !QJsonDocument::fromJson(message).isNull();
}

bool Messages::parseJsonUsers(ArmaMessage &message, QList<peer>& usersList) {
	usersList.clear();
	QJsonDocument jsonDoc = QJsonDocument::fromJson(message);
	if (jsonDoc.isNull()) {
		return false;
	}
	QJsonObject jsonObject = jsonDoc.object();
	if (jsonObject["users"].isArray()) {
		QJsonArray users = jsonObject["users"].toArray();
		foreach (QJsonValue user, users)
		{
			QJsonObject userObject = user.toObject();
			peer p;
			p.address = userObject["address"].toString();
			p.name = userObject["nick"].toString();
			p.listeningPort = userObject["port"].toInt();
			usersList.append(p);
		}
	}
	else {
		return false;
	}
	return true;
}

bool Messages::parseMessage(std::function<Session &(QString & name)> sessions, const ArmaMessage & message, std::function<void(Session &, MsgType, const ReceivedMessage &)> callback) {
	QString senderNick, receiverNick;
	QByteArray dh;
    QDateTime timestamp;
    MsgType type;

    QList<QByteArray> list = message.split(armaSeparator);

    if (list.size() < 5) throw MessageException("incomplete message");

    senderNick = QString::fromUtf8(QByteArray::fromBase64(list[0]));
    receiverNick = QString::fromUtf8(QByteArray::fromBase64(list[1]));

	Session & session = sessions(senderNick);
	if (session.getMyName() != receiverNick) throw MessageException("Message not for this client.");

	ReceivedMessage parsedMessage;
    timestamp.setMSecsSinceEpoch(list[2].toLongLong());
    parsedMessage.timestamp = timestamp;

    type = static_cast<MsgType>(list[3][0] - 'A');

    QByteArray messageText;

    if(type == Messages::MsgType::PureDH)
    {
        dh = QByteArray::fromBase64(list[4]);

        SessionKey& sk = session.getKey();

        int contextDataLength = list[0].size() + list[1].size() + list[2].size() + list[3].size() + list[4].size() + 5;
        QByteArray messageText;
        try {
            QByteArray a1 = message.left(contextDataLength);
            QByteArray a2 = message.right(message.length() - contextDataLength);
            messageText = sk.unprotect(a2, a1);
        }
        catch (KryptoException e) {
            return false;
        }
        sk.setDH(dh);
        sk.generateKey();

        parsedMessage.messageText = messageText;
		return true;
    }
    else if (type % 2) {
		if (list.size() < 6) throw MessageException("incomplete message");
		dh = QByteArray::fromBase64(list[4]);

		SessionKey& sk = session.getKey();

		int contextDataLength = list[0].size() + list[1].size() + list[2].size() + list[3].size() + list[4].size() + 5;
		QByteArray messageText;
		try {
			QByteArray a1 = message.left(contextDataLength);
			QByteArray a2 = message.right(message.length() - contextDataLength);
			messageText = sk.unprotect(a2, a1);
		}
		catch (KryptoException e) {
			return false;
		}
		sk.setDH(dh);
		sk.generateKey();

		parsedMessage.messageText = messageText;
	}
    //regularMessage
	else {

        SessionKey& sk = session.getKey();
        int contextDataLength = list[0].size() + list[1].size() + list[2].size() + list[3].size() + 4; //number of separators
        try{
            QByteArray a1 = message.left(contextDataLength);
            QByteArray a2 = message.right(message.length() - contextDataLength);
            messageText = sk.unprotect(a2, a1);
        }
        catch (KryptoException e) {
            return false;
        }
        parsedMessage.messageText = messageText;
    }

	callback(session, type, parsedMessage);
    return true;
}

QByteArray Messages::addMessageHeader(Session & session, const QByteArray & payload, Messages::MsgType type, Messages::MsgType typeDH) {
	QByteArray ret;
	SessionKey & key = session.getKey();

	ret.append(session.getMyName().toUtf8().toBase64());
	ret.append(Messages::armaSeparator);
	ret.append(session.getPartnerName().toUtf8().toBase64());
	ret.append(Messages::armaSeparator);
	ret.append(QString::number(QDateTime::currentMSecsSinceEpoch()));
	ret.append(Messages::armaSeparator);

	QByteArray dh = key.conditionalGetDH();
	if (dh.length() > 0) {
		ret.append('A' + typeDH);
		ret.append(Messages::armaSeparator);
		ret.append(dh.toBase64());
	}
	else {
		ret.append('A' + type);
	}
	ret.append(Messages::armaSeparator);

	ret.append(key.protect(payload, ret));

	if (dh.length() > 0) key.generateKey();
	return ret;
}

void Messages::FileSendingContext::sendFile(Session & s, const QString & path, std::function<void(const QByteArray &)> sender) {
	QByteArray payload;
	auto it = transfers.insert(++transferID, std::shared_ptr<FileSendingContext>(new FileSendingContext(s, path, sender)));

	payload.append(QByteArray::number(transferID));
	payload.append(Messages::armaSeparator);
	payload.append(QByteArray::number((*it)->fileSize));

	sender(Messages::addMessageHeader(s, payload, MsgType::FileContext, MsgType::FileContextDH));
}

void Messages::FileSendingContext::confirmFile(Session & s, const QByteArray & response) {
	QList<QByteArray> list = response.split(Messages::armaSeparator);

	qint64 id = list[0].toLongLong();
	auto it = transfers.find(id);
	(*it)->destID = list[1].toLongLong();
	(*it)->startSending();
}

void Messages::FileReceivingContext::receiveFile(Session & s, const QByteArray & payload, std::function<void(const QByteArray &)> sender) {
	QList<QByteArray> list = payload.split(Messages::armaSeparator);
	qint64 id = list[0].toLongLong();
	qint64 size = list[1].toLongLong();

	QString path = "downloads/";
	path.append(QString::number(++transferID));
	path.append(".rec");

	auto it = transfers.insert(transferID, std::shared_ptr<FileReceivingContext>(new FileReceivingContext(s, path)));

	QByteArray response;
	response.append(QByteArray::number(id));
	response.append(Messages::armaSeparator);
	response.append(QByteArray::number(transferID));

	if(sender) sender(Messages::addMessageHeader(s, response, MsgType::FileResponse, MsgType::FileResponseDH));
	else s.send(Messages::addMessageHeader(s, response, MsgType::FileResponse, MsgType::FileResponseDH));
}

void Messages::FileReceivingContext::receiveChunk(Session & s, const QByteArray & payload) {
	QList<QByteArray> list = payload.split(Messages::armaSeparator);

	qint64 id = list[0].toLongLong();
	qint64 start = list[1].toLongLong();
	qint64 len = list[2].toLongLong();

	auto it = transfers.find(id);
	(*it)->parseChunk(start, len, payload.right(payload.length() - (list[0].length() + list[1].length() + list[2].length() + 3)));
}

Messages::FileSendingContext::FileSendingContext(Session & session, QString path, std::function<void(const QByteArray &)> dataSender) : session(session), path(path), dataSender(dataSender) {
	QFile file(path);
	if(!file.open(QIODevice::ReadWrite)) throw MessageException("Unable to open file!");
	fileSize = file.size();
	file.close();
}

bool Messages::FileSendingContext::startSending() {
	qint64 chunks = (fileSize - 1) / Messages::maxChunkSize + 1;
	qint64 threads = std::min(chunks, maxThreads);
	qint64 done = 0;

	for (qint64 i = 0; i < threads; ++i) {
		workers.push_back(Worker(session, destID, path, dataSender));

		// Load balancer
		qint64 cChunks = ((chunks - 1) / threads + (((chunks - 1) % threads < i) ? 0 : 1));
		qint64 start = done * Messages::maxChunkSize;
		done += cChunks;
		qint64 len = (i == threads - 1) ? (fileSize - start) : (cChunks * Messages::maxChunkSize);

		futures.push_back(QtConcurrent::run(workers.back(), start, len));
	}
	return true;
}

void Messages::FileSendingContext::Worker::operator()(qint64 gstart, qint64 glen) {
	QFile file(path);
	file.open(QIODevice::ReadOnly);
	file.seek(gstart);

	do {
		qint64 len = std::min(glen, maxChunkSize);
		qint64 start = file.pos();
		glen -= len;

		QByteArray payload;
		payload.append(QString::number(destID));
		payload.append(Messages::armaSeparator);
		payload.append(QString::number(start));
		payload.append(Messages::armaSeparator);
		payload.append(QString::number(len));
		payload.append(Messages::armaSeparator);
		payload.append(file.read(len));

		QByteArray ret = addMessageHeader(session, payload, Messages::MsgType::FileMessage, Messages::MsgType::FileMessageDH);

		dataSender(ret);
	} while (glen > 0);
	file.close();
}

Messages::FileReceivingContext::FileReceivingContext(Session & session, QString path) : session(session), path(path) {
	QFile file(path);
	if (!file.open(QIODevice::ReadWrite)) throw MessageException("Unable to open file!");
	fileSize = file.size();
	file.close();
}

void Messages::FileReceivingContext::parseChunk(qint64 start, qint64 len, const QByteArray & data) {
	workers.push_back(Worker(session, path, fileSize));
	futures.push_back(QtConcurrent::run(workers.back(), start, len, data));
}

void Messages::FileReceivingContext::parseChunk(const QByteArray & data) {
	QList<QByteArray> list = data.split(Messages::armaSeparator);

	qint64 start = list[0].toLongLong();
	qint64 len = list[1].toLongLong();

	parseChunk(start, len, data.right(data.length() - (list[0].length() + list[1].length() + 2)));
}

void Messages::FileReceivingContext::Worker::operator()(qint64 start, qint64 len, QByteArray data) {

	//if (start + len > fileSize) throw MessageException("File chunk out of range.");

	QFile file(path);
	file.open(QIODevice::ReadWrite);
	file.seek(start);
	file.write(data);
	file.close();
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2004-present, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 *
 */
#include "BcmEgress.h"

#include "fboss/agent/Constants.h"
#include "fboss/agent/hw/bcm/BcmError.h"
#include "fboss/agent/hw/bcm/BcmHost.h"
#include "fboss/agent/hw/bcm/BcmSwitch.h"
#include "fboss/agent/hw/bcm/BcmWarmBootCache.h"

namespace facebook { namespace fboss {

using folly::IPAddress;
using folly::MacAddress;

bool BcmEgress::alreadyExists(const opennsl_l3_egress_t& newEgress) const {
  if (id_ == INVALID) {
    return false;
  }
  opennsl_l3_egress_t existingEgress;
  auto rv = opennsl_l3_egress_get(hw_->getUnit(), id_, &existingEgress);
  bcmCheckError(rv, "Egress object ", id_, " does not exist");
  bool sameMacs = !memcmp(newEgress.mac_addr, existingEgress.mac_addr,
        sizeof(newEgress.mac_addr));
   return sameMacs && existingEgress.intf == newEgress.intf &&
   existingEgress.port == newEgress.port &&
   existingEgress.flags == newEgress.flags;
}

void BcmEgress::verifyDropEgress(int unit) {
  const auto id = getDropEgressId();
  opennsl_l3_egress_t egress;
  opennsl_l3_egress_t_init(&egress);
  auto ret = opennsl_l3_egress_get(unit, id, &egress);
  bcmCheckError(ret, "failed to verify drop egress ", id);
  if (!(egress.flags & OPENNSL_L3_DST_DISCARD)) {
    throw FbossError("Egress ID ", id, " is not programmed as drop");
  }
}

void BcmEgress::program(opennsl_if_t intfId, opennsl_vrf_t vrf,
    const IPAddress& ip, const MacAddress* mac, opennsl_port_t port,
    RouteForwardAction action) {
  opennsl_l3_egress_t eObj;
  opennsl_l3_egress_t_init(&eObj);
  if (mac == nullptr) {
    if (action == TO_CPU) {
      eObj.flags |= (OPENNSL_L3_L2TOCPU | OPENNSL_L3_COPY_TO_CPU);
    } else {
      eObj.flags |= OPENNSL_L3_DST_DISCARD;
    }
  } else {
    memcpy(&eObj.mac_addr, mac->bytes(), sizeof(eObj.mac_addr));
    eObj.port = port;
  }
  eObj.intf = intfId;
  bool addOrUpdateEgress = false;
  const auto warmBootCache = hw_->getWarmBootCache();
  CHECK(warmBootCache);
  auto egressId2EgressAndBoolCitr = warmBootCache->findEgress(vrf, ip);
  if (egressId2EgressAndBoolCitr !=
      warmBootCache->egressId2EgressAndBool_end()) {
    // Lambda to compare with existing egress to know if should reprogram
    auto equivalent = [] (const opennsl_l3_egress_t& newEgress,
        const opennsl_l3_egress_t& existingEgress) {
      auto puntToCPU = [=] (const opennsl_l3_egress_t& egress) {
        // Check if both OPENNSL_L3_L2TOCPU and OPENNSL_L3_COPY_TO_CPU are set
        static const auto kCPUFlags =
          OPENNSL_L3_L2TOCPU | OPENNSL_L3_COPY_TO_CPU;
        return (egress.flags & kCPUFlags) == kCPUFlags;
      };
      if (!puntToCPU(newEgress) && !puntToCPU(existingEgress)) {
        // Both new and existing egress point to a valid nexthop
        // Compare mac, port and interface of egress objects
        return !memcmp(newEgress.mac_addr, existingEgress.mac_addr,
          sizeof(newEgress.mac_addr)) &&
          existingEgress.intf == newEgress.intf &&
          existingEgress.port == newEgress.port;
      }
      if (puntToCPU(existingEgress)) {
        // If existing entry and new entry both point to CPU we
        // consider them equal (i.e. no need to update h/w)
        return puntToCPU(newEgress);
      } else {
        // Existing entry does not point to CPU while the new
        // one does. This is because the new entry does not know
        // the result of ARP/NDP resolution yet. Leave the entry
        // in h/w intact
        return true;
      }
      return false;
    };
    const auto& existingEgressId = egressId2EgressAndBoolCitr->first;
    // Cache existing egress id
    id_ = existingEgressId;
    auto existingEgressObject = egressId2EgressAndBoolCitr->second.first;
    if (!equivalent(eObj, existingEgressObject)) {
      VLOG(1) << "Updating egress object for next hop : " << ip;
      addOrUpdateEgress = true;
    } else {
      VLOG(1) << "Egress object for : " << ip << " already exists";
    }
  } else {
    addOrUpdateEgress = true;
  }
  if (addOrUpdateEgress) {
    if (egressId2EgressAndBoolCitr ==
        warmBootCache->egressId2EgressAndBool_end()) {
      VLOG(1) << "Adding egress object for next hop : " << ip;
    }
    uint32_t flags = 0;
    if (id_ != INVALID) {
      flags |= OPENNSL_L3_REPLACE|OPENNSL_L3_WITH_ID;
    }
    if (!alreadyExists(eObj)) {
      /*
       *  Only program the HW if a identical egress object does not
       *  exist. Per BCM documentation updating entries like so should not
       *  be a problem. However we found that if we reprogrammed a already
       *  existing egress object with the same parameters forwarding to
       *  the corresponding IP address sometimes broke. BCM issue is being
       *  tracked in t4324084
       */
      auto rc = opennsl_l3_egress_create(hw_->getUnit(), flags, &eObj, &id_);
      bcmCheckError(rc, "failed to program L3 egress object ", id_,
          " ", (mac) ? mac->toString() : "ToCPU",
          " on port ", port,
          " on unit ", hw_->getUnit());
      VLOG(3) << "programmed L3 egress object " << id_ << " for "
              << ((mac) ? mac->toString() : "to CPU") << " on unit "
              << hw_->getUnit() << " for ip: " << ip << " flags " << eObj.flags;
      if (mac != nullptr) {
        mac_ = *mac;
      }
      intfId_ = intfId;
    } else {
      // TODO(t10268453): How can we get here? The entries were not equivalent
      // when we entered this ' if (addOrUpdateEgress) ' condition. Is the
      // difference between what is in BcmWarmBootCache and what is in the
      // hardware?
      VLOG(1) << "Identical egress object for : " << ip << " pointing to "
        << (mac ? mac->toString() : "CPU ") << " already exists "
        << "skipping egress programming ";
    }
  }
  if (egressId2EgressAndBoolCitr !=
      warmBootCache->egressId2EgressAndBool_end()) {
    warmBootCache->programmed(egressId2EgressAndBoolCitr);
  }
  CHECK_NE(id_, INVALID);
}

void BcmEgress::programToCPU() {
  auto egressFromCache = hw_->getWarmBootCache()->getToCPUEgressId();
  if (id_ == INVALID && egressFromCache != INVALID) {
    id_ = egressFromCache;
    return;
  }
  opennsl_l3_egress_t eObj;
  opennsl_l3_egress_t_init(&eObj);
  eObj.flags |= (OPENNSL_L3_L2TOCPU | OPENNSL_L3_COPY_TO_CPU);
  // BCM does not care about interface ID for punt to CPU egress object
  uint32_t flags = 0;
  if (id_ != INVALID) {
    flags |= OPENNSL_L3_REPLACE|OPENNSL_L3_WITH_ID;
  }
  auto rc = opennsl_l3_egress_create(hw_->getUnit(), flags, &eObj, &id_);
  bcmCheckError(rc, "failed to program L3 egress object ", id_,
                " to CPU on unit ", hw_->getUnit());
  VLOG(3) << "programmed L3 egress object " << id_
          << " to CPU on unit " << hw_->getUnit();
}

BcmEgress::~BcmEgress() {
  if (id_ == INVALID) {
    return;
  }
  auto rc = opennsl_l3_egress_destroy(hw_->getUnit(), id_);
  bcmLogFatal(rc, hw_, "failed to destroy L3 egress object ",
      id_, " on unit ", hw_->getUnit());
  VLOG(3) << "destroyed L3 egress object " << id_
          << " on unit " << hw_->getUnit();
}

void BcmEcmpEgress::program() {
  opennsl_l3_egress_ecmp_t obj;
  opennsl_l3_egress_ecmp_t_init(&obj);
  auto n_path = paths_.size();
  obj.max_paths = ((n_path + 3) >> 2) << 2; // multiple of 4

  const auto warmBootCache = hw_->getWarmBootCache();
  auto egressIds2EcmpCItr = warmBootCache->findEcmp(paths_);
  if (egressIds2EcmpCItr != warmBootCache->egressIds2Ecmp_end()) {
    const auto& existing = egressIds2EcmpCItr->second;
    // TODO figure out why the following check fails
    // i.e. the suggested max_paths is not the same
    // as programmed max_paths. Note that this does not
    // imply that less number of next hops got programmed
    // but just that the max_paths did not get rounded to
    // the next multiple of 4 as we desired.
    // CHECK(obj.max_paths == existing.max_paths);
    id_ = existing.ecmp_intf;
    VLOG(1) << "Ecmp egress object for egress : " <<
      BcmWarmBootCache::toEgressIdsStr(paths_)
      << " already exists ";
    warmBootCache->programmed(egressIds2EcmpCItr);
  } else {
    VLOG(1) << "Adding ecmp egress with egress : " <<
      BcmWarmBootCache::toEgressIdsStr(paths_);
    if (id_ != INVALID) {
      obj.flags |= OPENNSL_L3_REPLACE|OPENNSL_L3_WITH_ID;
      obj.ecmp_intf = id_;
    }
    opennsl_if_t pathsArray[paths_.size()];
    auto index = 0;
    for (auto path: paths_) {
      if (hw_->getHostTable()->egressIdPort(path)) {
        pathsArray[index++] = path;
      } else {
        VLOG(1) << "Skipping unresolved egress : " << path << " while "
          << "programming ECMP group ";
      }
    }
    auto ret = opennsl_l3_egress_ecmp_create(hw_->getUnit(), &obj, index,
                                             pathsArray);
    bcmCheckError(ret, "failed to program L3 ECMP egress object ", id_,
                " with ", n_path, " paths");
    id_ = obj.ecmp_intf;
    VLOG(2) << "Programmed L3 ECMP egress object " << id_ << " for "
          << n_path << " paths";
  }
  CHECK_NE(id_, INVALID);
}

BcmEcmpEgress::~BcmEcmpEgress() {
  if (id_ == INVALID) {
    return;
  }
  opennsl_l3_egress_ecmp_t obj;
  opennsl_l3_egress_ecmp_t_init(&obj);
  obj.ecmp_intf = id_;
  auto ret = opennsl_l3_egress_ecmp_destroy(hw_->getUnit(), &obj);
  bcmLogFatal(ret, hw_, "failed to destroy L3 ECMP egress object ",
      id_, " on unit ", hw_->getUnit());
  VLOG(3) << "Destroyed L3 ECMP egress object " << id_
          << " on unit " << hw_->getUnit();
}

folly::dynamic BcmEgress::toFollyDynamic() const {
  folly::dynamic egress = folly::dynamic::object;
  egress[kEgressId] = getID();
  egress[kMac] = mac_.toString();
  egress[kIntfId] = intfId_;
  return egress;
}

folly::dynamic BcmEcmpEgress::toFollyDynamic() const {
  folly::dynamic ecmpEgress = folly::dynamic::object;
  ecmpEgress[kEgressId] = getID();
  folly::dynamic paths = folly::dynamic::array;
  for (auto path: paths_) {
    paths.push_back(path);
  }
  ecmpEgress[kPaths] = std::move(paths);
  return ecmpEgress;
}

bool BcmEcmpEgress::pathUnreachableHwLocked(EgressId path) {
  return removeEgressIdHwLocked(hw_->getUnit(), getID(), path);
}

bool BcmEcmpEgress::pathReachableHwLocked(EgressId path) {
  return addEgressIdHwLocked(hw_->getUnit(), getID(), paths_, path);
}

bool BcmEcmpEgress::removeEgressIdHwLocked(
    int unit,
    EgressId ecmpId,
    EgressId toRemove) {
  // We don't really need the lock here so safe to call the
  // stricter non locked version.
  return removeEgressIdHwNotLocked(unit, ecmpId, toRemove);
}

}}
<commit_msg>Make message hub work with new TCP connections<commit_after>/*
 *  Copyright (c) 2004-present, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 *
 */
#include "BcmEgress.h"

#include "fboss/agent/Constants.h"
#include "fboss/agent/hw/bcm/BcmError.h"
#include "fboss/agent/hw/bcm/BcmHost.h"
#include "fboss/agent/hw/bcm/BcmSwitch.h"
#include "fboss/agent/hw/bcm/BcmWarmBootCache.h"

namespace facebook { namespace fboss {

using folly::IPAddress;
using folly::MacAddress;

bool BcmEgress::alreadyExists(const opennsl_l3_egress_t& newEgress) const {
  if (id_ == INVALID) {
    return false;
  }
  opennsl_l3_egress_t existingEgress;
  auto rv = opennsl_l3_egress_get(hw_->getUnit(), id_, &existingEgress);
  bcmCheckError(rv, "Egress object ", id_, " does not exist");
  bool sameMacs = !memcmp(newEgress.mac_addr, existingEgress.mac_addr,
        sizeof(newEgress.mac_addr));
   return sameMacs && existingEgress.intf == newEgress.intf &&
   existingEgress.port == newEgress.port &&
   existingEgress.flags == newEgress.flags;
}

void BcmEgress::verifyDropEgress(int unit) {
  const auto id = getDropEgressId();
  opennsl_l3_egress_t egress;
  opennsl_l3_egress_t_init(&egress);
  auto ret = opennsl_l3_egress_get(unit, id, &egress);
  bcmCheckError(ret, "failed to verify drop egress ", id);
  if (!(egress.flags & OPENNSL_L3_DST_DISCARD)) {
    throw FbossError("Egress ID ", id, " is not programmed as drop");
  }
}

void BcmEgress::program(opennsl_if_t intfId, opennsl_vrf_t vrf,
    const IPAddress& ip, const MacAddress* mac, opennsl_port_t port,
    RouteForwardAction action) {
  opennsl_l3_egress_t eObj;
  opennsl_l3_egress_t_init(&eObj);
  if (mac == nullptr) {
    if (action == TO_CPU) {
      eObj.flags |= (OPENNSL_L3_L2TOCPU | OPENNSL_L3_COPY_TO_CPU);
    } else {
      eObj.flags |= OPENNSL_L3_DST_DISCARD;
    }
  } else {
    memcpy(&eObj.mac_addr, mac->bytes(), sizeof(eObj.mac_addr));
    eObj.port = port;
  }
  eObj.intf = intfId;
  bool addOrUpdateEgress = false;
  const auto warmBootCache = hw_->getWarmBootCache();
  CHECK(warmBootCache);
  auto egressId2EgressAndBoolCitr = warmBootCache->findEgress(vrf, ip);
  if (egressId2EgressAndBoolCitr !=
      warmBootCache->egressId2EgressAndBool_end()) {
    // Lambda to compare with existing egress to know if should reprogram
    auto equivalent = [] (const opennsl_l3_egress_t& newEgress,
        const opennsl_l3_egress_t& existingEgress) {
      auto puntToCPU = [=] (const opennsl_l3_egress_t& egress) {
        // Check if both OPENNSL_L3_L2TOCPU and OPENNSL_L3_COPY_TO_CPU are set
        static const auto kCPUFlags =
          OPENNSL_L3_L2TOCPU | OPENNSL_L3_COPY_TO_CPU;
        return (egress.flags & kCPUFlags) == kCPUFlags;
      };
      if (!puntToCPU(newEgress) && !puntToCPU(existingEgress)) {
        // Both new and existing egress point to a valid nexthop
        // Compare mac, port and interface of egress objects
        return !memcmp(newEgress.mac_addr, existingEgress.mac_addr,
          sizeof(newEgress.mac_addr)) &&
          existingEgress.intf == newEgress.intf &&
          existingEgress.port == newEgress.port;
      }
      if (puntToCPU(existingEgress)) {
        // If existing entry and new entry both point to CPU we
        // consider them equal (i.e. no need to update h/w)
        return puntToCPU(newEgress);
      } else {
        // Existing entry does not point to CPU while the new
        // one does. This is because the new entry does not know
        // the result of ARP/NDP resolution yet. Leave the entry
        // in h/w intact
        return true;
      }
      return false;
    };
    const auto& existingEgressId = egressId2EgressAndBoolCitr->first;
    // Cache existing egress id
    id_ = existingEgressId;
    auto existingEgressObject = egressId2EgressAndBoolCitr->second.first;
    if (!equivalent(eObj, existingEgressObject)) {
      VLOG(1) << "Updating egress object for next hop : " << ip;
      addOrUpdateEgress = true;
    } else {
      VLOG(1) << "Egress object for : " << ip << " already exists";
    }
  } else {
    addOrUpdateEgress = true;
  }
  if (addOrUpdateEgress) {
    if (egressId2EgressAndBoolCitr ==
        warmBootCache->egressId2EgressAndBool_end()) {
      VLOG(1) << "Adding egress object for next hop : " << ip;
    }
    uint32_t flags = 0;
    if (id_ != INVALID) {
      flags |= OPENNSL_L3_REPLACE|OPENNSL_L3_WITH_ID;
    }
    if (!alreadyExists(eObj)) {
      /*
       *  Only program the HW if a identical egress object does not
       *  exist. Per BCM documentation updating entries like so should not
       *  be a problem. However we found that if we reprogrammed a already
       *  existing egress object with the same parameters forwarding to
       *  the corresponding IP address sometimes broke. BCM issue is being
       *  tracked in t4324084
       */
      auto rc = opennsl_l3_egress_create(hw_->getUnit(), flags, &eObj, &id_);
      bcmCheckError(rc, "failed to program L3 egress object ", id_,
          " ", (mac) ? mac->toString() : "ToCPU",
          " on port ", port,
          " on unit ", hw_->getUnit());
      VLOG(3) << "programmed L3 egress object " << id_ << " for "
              << ((mac) ? mac->toString() : "to CPU") << " on unit "
              << hw_->getUnit() << " for ip: " << ip << " flags " << eObj.flags
              << " towards port " << eObj.port;
      if (mac != nullptr) {
        mac_ = *mac;
      }
      intfId_ = intfId;
    } else {
      // TODO(t10268453): How can we get here? The entries were not equivalent
      // when we entered this ' if (addOrUpdateEgress) ' condition. Is the
      // difference between what is in BcmWarmBootCache and what is in the
      // hardware?
      VLOG(1) << "Identical egress object for : " << ip << " pointing to "
        << (mac ? mac->toString() : "CPU ") << " already exists "
        << "skipping egress programming ";
    }
  }
  if (egressId2EgressAndBoolCitr !=
      warmBootCache->egressId2EgressAndBool_end()) {
    warmBootCache->programmed(egressId2EgressAndBoolCitr);
  }
  CHECK_NE(id_, INVALID);
}

void BcmEgress::programToCPU() {
  auto egressFromCache = hw_->getWarmBootCache()->getToCPUEgressId();
  if (id_ == INVALID && egressFromCache != INVALID) {
    id_ = egressFromCache;
    return;
  }
  opennsl_l3_egress_t eObj;
  opennsl_l3_egress_t_init(&eObj);
  eObj.flags |= (OPENNSL_L3_L2TOCPU | OPENNSL_L3_COPY_TO_CPU);
  // BCM does not care about interface ID for punt to CPU egress object
  uint32_t flags = 0;
  if (id_ != INVALID) {
    flags |= OPENNSL_L3_REPLACE|OPENNSL_L3_WITH_ID;
  }
  auto rc = opennsl_l3_egress_create(hw_->getUnit(), flags, &eObj, &id_);
  bcmCheckError(rc, "failed to program L3 egress object ", id_,
                " to CPU on unit ", hw_->getUnit());
  VLOG(3) << "programmed L3 egress object " << id_
          << " to CPU on unit " << hw_->getUnit();
}

BcmEgress::~BcmEgress() {
  if (id_ == INVALID) {
    return;
  }
  auto rc = opennsl_l3_egress_destroy(hw_->getUnit(), id_);
  bcmLogFatal(rc, hw_, "failed to destroy L3 egress object ",
      id_, " on unit ", hw_->getUnit());
  VLOG(3) << "destroyed L3 egress object " << id_
          << " on unit " << hw_->getUnit();
}

void BcmEcmpEgress::program() {
  opennsl_l3_egress_ecmp_t obj;
  opennsl_l3_egress_ecmp_t_init(&obj);
  auto n_path = paths_.size();
  obj.max_paths = ((n_path + 3) >> 2) << 2; // multiple of 4

  const auto warmBootCache = hw_->getWarmBootCache();
  auto egressIds2EcmpCItr = warmBootCache->findEcmp(paths_);
  if (egressIds2EcmpCItr != warmBootCache->egressIds2Ecmp_end()) {
    const auto& existing = egressIds2EcmpCItr->second;
    // TODO figure out why the following check fails
    // i.e. the suggested max_paths is not the same
    // as programmed max_paths. Note that this does not
    // imply that less number of next hops got programmed
    // but just that the max_paths did not get rounded to
    // the next multiple of 4 as we desired.
    // CHECK(obj.max_paths == existing.max_paths);
    id_ = existing.ecmp_intf;
    VLOG(1) << "Ecmp egress object for egress : " <<
      BcmWarmBootCache::toEgressIdsStr(paths_)
      << " already exists ";
    warmBootCache->programmed(egressIds2EcmpCItr);
  } else {
    VLOG(1) << "Adding ecmp egress with egress : " <<
      BcmWarmBootCache::toEgressIdsStr(paths_);
    if (id_ != INVALID) {
      obj.flags |= OPENNSL_L3_REPLACE|OPENNSL_L3_WITH_ID;
      obj.ecmp_intf = id_;
    }
    opennsl_if_t pathsArray[paths_.size()];
    auto index = 0;
    for (auto path: paths_) {
      if (hw_->getHostTable()->egressIdPort(path)) {
        pathsArray[index++] = path;
      } else {
        VLOG(1) << "Skipping unresolved egress : " << path << " while "
          << "programming ECMP group ";
      }
    }
    auto ret = opennsl_l3_egress_ecmp_create(hw_->getUnit(), &obj, index,
                                             pathsArray);
    bcmCheckError(ret, "failed to program L3 ECMP egress object ", id_,
                " with ", n_path, " paths");
    id_ = obj.ecmp_intf;
    VLOG(2) << "Programmed L3 ECMP egress object " << id_ << " for "
          << n_path << " paths";
  }
  CHECK_NE(id_, INVALID);
}

BcmEcmpEgress::~BcmEcmpEgress() {
  if (id_ == INVALID) {
    return;
  }
  opennsl_l3_egress_ecmp_t obj;
  opennsl_l3_egress_ecmp_t_init(&obj);
  obj.ecmp_intf = id_;
  auto ret = opennsl_l3_egress_ecmp_destroy(hw_->getUnit(), &obj);
  bcmLogFatal(ret, hw_, "failed to destroy L3 ECMP egress object ",
      id_, " on unit ", hw_->getUnit());
  VLOG(3) << "Destroyed L3 ECMP egress object " << id_
          << " on unit " << hw_->getUnit();
}

folly::dynamic BcmEgress::toFollyDynamic() const {
  folly::dynamic egress = folly::dynamic::object;
  egress[kEgressId] = getID();
  egress[kMac] = mac_.toString();
  egress[kIntfId] = intfId_;
  return egress;
}

folly::dynamic BcmEcmpEgress::toFollyDynamic() const {
  folly::dynamic ecmpEgress = folly::dynamic::object;
  ecmpEgress[kEgressId] = getID();
  folly::dynamic paths = folly::dynamic::array;
  for (auto path: paths_) {
    paths.push_back(path);
  }
  ecmpEgress[kPaths] = std::move(paths);
  return ecmpEgress;
}

bool BcmEcmpEgress::pathUnreachableHwLocked(EgressId path) {
  return removeEgressIdHwLocked(hw_->getUnit(), getID(), path);
}

bool BcmEcmpEgress::pathReachableHwLocked(EgressId path) {
  return addEgressIdHwLocked(hw_->getUnit(), getID(), paths_, path);
}

bool BcmEcmpEgress::removeEgressIdHwLocked(
    int unit,
    EgressId ecmpId,
    EgressId toRemove) {
  // We don't really need the lock here so safe to call the
  // stricter non locked version.
  return removeEgressIdHwNotLocked(unit, ecmpId, toRemove);
}

}}
<|endoftext|>