<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: AView.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 06:55:04 $
 *
 *  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 _CONNECTIVITY_ADO_VIEW_HXX_
#define _CONNECTIVITY_ADO_VIEW_HXX_

#ifndef _CONNECTIVITY_SDBCX_VIEW_HXX_
#include "connectivity/sdbcx/VView.hxx"
#endif
#ifndef _CONNECTIVITY_ADO_AWRAPADOX_HXX_
#include "ado/Awrapadox.hxx"
#endif

namespace connectivity
{
    namespace ado
    {

        typedef sdbcx::OView OView_ADO;

        class OAdoView :     public OView_ADO
        {
            WpADOView       m_aView;

        protected:
            // OPropertySetHelper
            virtual void SAL_CALL getFastPropertyValue(
                                ::com::sun::star::uno::Any& rValue,
                                    sal_Int32 nHandle
                                         ) const;
        public:
            OAdoView(sal_Bool _bCase, ADOView* _pView=NULL);

            // com::sun::star::lang::XUnoTunnel
            virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException);
            static ::com::sun::star::uno::Sequence< sal_Int8 > getUnoTunnelImplementationId();
            virtual void SAL_CALL acquire() throw();
            virtual void SAL_CALL release() throw();

            WpADOView getImpl() const { return m_aView;}
        };
    }
}

#endif // _CONNECTIVITY_ADO_VIEW_HXX_

<commit_msg>INTEGRATION: CWS changefileheader (1.6.372); FILE MERGED 2008/04/01 10:53:21 thb 1.6.372.2: #i85898# Stripping all external header guards 2008/03/28 15:24:12 rt 1.6.372.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: AView.hxx,v $
 * $Revision: 1.7 $
 *
 * 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.
 *
 ************************************************************************/

#ifndef _CONNECTIVITY_ADO_VIEW_HXX_
#define _CONNECTIVITY_ADO_VIEW_HXX_

#include "connectivity/sdbcx/VView.hxx"
#include "ado/Awrapadox.hxx"

namespace connectivity
{
    namespace ado
    {

        typedef sdbcx::OView OView_ADO;

        class OAdoView :     public OView_ADO
        {
            WpADOView       m_aView;

        protected:
            // OPropertySetHelper
            virtual void SAL_CALL getFastPropertyValue(
                                ::com::sun::star::uno::Any& rValue,
                                    sal_Int32 nHandle
                                         ) const;
        public:
            OAdoView(sal_Bool _bCase, ADOView* _pView=NULL);

            // com::sun::star::lang::XUnoTunnel
            virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException);
            static ::com::sun::star::uno::Sequence< sal_Int8 > getUnoTunnelImplementationId();
            virtual void SAL_CALL acquire() throw();
            virtual void SAL_CALL release() throw();

            WpADOView getImpl() const { return m_aView;}
        };
    }
}

#endif // _CONNECTIVITY_ADO_VIEW_HXX_

<|endoftext|>


<commit_before>/*************************************************************************\
**
**  tOutput.cpp: Functions for output classes tOutput and tLOutput
**
**  (see tOutput.h for a description of these classes)
**
**  $Id: tOutput.cpp,v 1.43 2000-07-04 04:44:54 daniel Exp $
\*************************************************************************/

#include <math.h>    // For fmod function
#include "tOutput.h"

/*************************************************************************\
**
**  Constructor
**
**  The constructor takes two arguments, a pointer to the mesh and
**  a reference to an open input file. It reads the base name for the
**  output files from the input file, and opens and initializes these.
**
**  Input: meshPtr -- pointer to a tMesh object (or descendant), assumed
**                    valid
**         infile -- reference to an open input file, assumed valid
**
\*************************************************************************/
template< class tSubNode >
tOutput<tSubNode>::tOutput( tMesh<tSubNode> * meshPtr, tInputFile &infile )
{
   assert( meshPtr > 0 );
   m = meshPtr;

   infile.ReadItem( baseName, "OUTFILENAME" );

   CreateAndOpenFile( &nodeofs, ".nodes" );
   CreateAndOpenFile( &edgofs, ".edges" );
   CreateAndOpenFile( &triofs, ".tri" );
   CreateAndOpenFile( &zofs, ".z" );
   CreateAndOpenFile( &vaofs, ".varea" );

}

/*************************************************************************\
**
**  tOutput::CreateAndOpenFile
**
**  Opens the output file stream pointed to by theOFStream, giving it the
**  name <baseName><extension>, and checks to make sure that the ofstream
**  is valid.
**
**  Input:  theOFStream -- ptr to an ofstream object
**          extension -- file name extension (e.g., ".nodes")
**  Output: theOFStream is initialized to create an open output file
**  Assumes: extension is a null-terminated string, and the length of
**           baseName plus extension doesn't exceed kMaxNameSize+6
**           (ie, the extension is expected to be <= 6 characters)
**
\*************************************************************************/
template< class tSubNode >
void tOutput<tSubNode>::CreateAndOpenFile( ofstream *theOFStream,
                                           char *extension )
{
   char fullName[kMaxNameSize+6];  // name of file to be created

   strcpy( fullName, baseName );
   strcat( fullName, extension );
   theOFStream->open( fullName );

   if( !theOFStream->good() )
       ReportFatalError(
           "I can't create files for output. Storage space may be exhausted.");

}

/*************************************************************************\
**
**  tOutput::WriteOutput
**
**  This function writes information about the mesh to four files called
**  name.nodes, name.edges, name.tri, and name.z, where "name" is a
**  name that the user has specified in the input file and which is
**  stored in the data member baseName.
**
**  Input: time -- time of the current output time-slice
**  Output: the node, edge, and triangle ID numbers are modified so that
**          they are numbered according to their position on the list
**  Assumes: the four file ofstreams have been opened by the constructor
**           and are valid
**
**  TODO: deal with option for once-only printing of mesh when mesh not
**        deforming
\*************************************************************************/
template< class tSubNode >
void tOutput<tSubNode>::WriteOutput( double time )
{
   tMeshListIter<tSubNode> niter( m->getNodeList() ); // node list iterator
   tMeshListIter<tEdge> eiter( m->getEdgeList() );    // edge list iterator
   tPtrListIter<tTriangle> titer( m->getTriList() );     // tri list iterator
   tNode * cn;       // current node
   tEdge * ce;       // current edge
   tTriangle * ct;   // current triangle
   int id;           // id of element (node, edge, or triangle)
   int nnodes = m->getNodeList()->getSize();  // # of nodes on list
   int nedges = m->getEdgeList()->getSize();  // "    edges "
   int ntri = m->getTriList()->getSize();     // "    triangles "

   cout << "tOutput::WriteOutput()\n" << flush;

   // Renumber IDs in order by position on list
   for( cn=niter.FirstP(), id=0; id<nnodes; cn=niter.NextP(), id++ )
       cn->setID( id );
   for( ce=eiter.FirstP(), id=0; id<nedges; ce=eiter.NextP(), id++ )
       ce->setID( id );
   for( ct=titer.FirstP(), id=0; id<ntri; ct=titer.NextP(), id++ )
       ct->setID( id );

   // Write node file, z file, and varea file
   nodeofs << " " << time << endl << nnodes << endl;
   zofs << " " << time << endl << nnodes << endl;
   vaofs << " " << time << endl << nnodes << endl;
   for( cn=niter.FirstP(); !(niter.AtEnd()); cn=niter.NextP() )
   {
      nodeofs << cn->getX() << " " << cn->getY() << " "
              << cn->getEdg()->getID() << " " << cn->getBoundaryFlag() << endl;
      zofs << cn->getZ() << endl;
      vaofs << cn->getVArea() << endl;
   }

   // Write edge file
   edgofs << " " << time << endl << nedges << endl;
   for( ce=eiter.FirstP(); !(eiter.AtEnd()); ce=eiter.NextP() )
      edgofs << ce->getOriginPtrNC()->getID() << " "
             << ce->getDestinationPtrNC()->getID() << " "
             << ce->getCCWEdg()->getID() << endl;

   // Write triangle file
   int i;
   triofs << " " << time << endl << ntri << endl;
   for( ct=titer.FirstP(); !(titer.AtEnd()); ct=titer.NextP() )
   {
      for( i=0; i<=2; i++ )
          triofs << ct->pPtr(i)->getID() << " ";
      for( i=0; i<=2; i++ )
      {
          if( ct->tPtr(i) ) triofs << ct->tPtr(i)->getID() << " ";
          else triofs << "-1 ";
      }
      triofs << ct->ePtr(0)->getID() << " "
             << ct->ePtr(1)->getID() << " "
             << ct->ePtr(2)->getID() << endl;
   }

   // Call virtual function to write any additional data
   WriteNodeData( time );

}

/*************************************************************************\
**
**  tOutput::WriteNodeData
**
**  This is a virtual function which can be overridden to write any
**  additional node data. The base class version does nothing.
**
\*************************************************************************/
template< class tSubNode >
void tOutput<tSubNode>::WriteNodeData( double time )
{}

/*************************************************************************\
**
**  tLOutput constructor
**
**  Creates and opens a series of files for drainage areas, slopes, etc.
**
**  Modifications:
**    - 1/00 added "opOpt" and creation of veg output file (GT)
**    - added flow depth output file (GT 1/00)
\*************************************************************************/
template< class tSubNode >
tLOutput<tSubNode>::tLOutput( tMesh<tSubNode> *meshPtr, tInputFile &infile )
        : tOutput<tSubNode>( meshPtr, infile )  // call base-class constructor
{
   int opOpt;  // Optional modules: only output stuff when needed
   int optTSOutput;

   counter=0;
   strcpy(nums, "0123456789");

   CreateAndOpenFile( &drareaofs, ".area" );
   CreateAndOpenFile( &netofs, ".net" );
   CreateAndOpenFile( &slpofs, ".slp" );
   CreateAndOpenFile( &qofs, ".q" );
   CreateAndOpenFile( &texofs, ".tx" );
   if( (opOpt = infile.ReadItem( opOpt, "OPTVEG" ) ) )
       CreateAndOpenFile( &vegofs, ".veg" );
   if( (opOpt = infile.ReadItem( opOpt, "OPTKINWAVE" ) ) )
       CreateAndOpenFile( &flowdepofs, ".dep" );
   if( (optTSOutput = infile.ReadItem( optTSOutput, "OPTTSOUTPUT" ) ) ) {
       CreateAndOpenFile( &volsofs, ".vols" );
       if( (opOpt = infile.ReadItem( opOpt, "OPTVEG" ) ) )
	 CreateAndOpenFile( &vegcovofs, ".vcov" );
       CreateAndOpenFile( &tareaofs, ".tarea" );
   }

}

/*************************************************************************\
**
**  tLOutput::WriteNodeData
**
**  This overridden virtual function writes output for tLNodes, including
**  drainage areas, flow pathways, slopes, discharges, layer info, etc.
**
**  Modifications:
**    - 1/00 added output to veg output file (GT)
**    - added output of flow depth; made slope output for all nodes (GT 1/00)
**    - 6/00 layer info for each time step written to a different file (NG)
\*************************************************************************/
//TODO: should output boundary points as well so they'll map up with nodes
// for plotting. Means changing getSlope so it returns zero if flowedg
// undefined
template< class tSubNode >
void tLOutput<tSubNode>::WriteNodeData( double time )
{
   tMeshListIter<tSubNode> ni( m->getNodeList() ); // node list iterator
   tSubNode *cn;   // current node
   int nActiveNodes = m->getNodeList()->getActiveSize(); // # active nodes
   int nnodes = m->getNodeList()->getSize();             // total # nodes
   int i, j;      // counters

   //taking care of layer file, since new one each time step
   char ext[7];
   strcpy( ext, ".lay");
   if(counter<10)
       strncat( ext, &nums[counter], 1);
   else if(counter>=10){
      strncat(ext, &nums[counter/10], 1);
      strncat(ext, &nums[(int) fmod((double)counter,10.0)], 1);
   }
   CreateAndOpenFile( &layofs, ext );
   counter++;

   // Write current time in each file
   drareaofs << " " << time << "\n " << nActiveNodes << endl;
   netofs << " " << time << "\n " << nActiveNodes << endl;
   slpofs << " " << time << "\n " << nnodes << endl;
   qofs << " " << time << "\n " << nnodes << endl;
   layofs << " " << time << "\n" << nActiveNodes << endl;
   texofs << " " << time << "\n" << nnodes << endl;
   if( vegofs.good() ) vegofs << " " << time << "\n" << nnodes << endl;
   if( flowdepofs.good() ) flowdepofs << " " << time << "\n" << nnodes << endl;

   // Write data, including layer info
   for( cn = ni.FirstP(); ni.IsActive(); cn = ni.NextP() )
   {
      assert( cn>0 );
      drareaofs << cn->getDrArea() << endl;
      if( cn->getDownstrmNbr() )
          netofs << cn->getDownstrmNbr()->getID() << endl;
      layofs << " " << cn->getNumLayer() << endl;
      i=0;
      while(i<cn->getNumLayer()){
         layofs << cn->getLayerCtime(i) << " " << cn->getLayerRtime(i) << " " << cn->getLayerEtime(i) << endl;
         layofs << cn->getLayerDepth(i) << " " << cn->getLayerErody(i) << " " << cn->getLayerSed(i) << endl;
         j=0;
         while(j<cn->getNumg()){
            layofs << cn->getLayerDgrade(i,j) << " ";
            j++;
         }
         layofs << endl;
         i++;
      }
   }

   // Write discharge, vegetation, & texture data
   for( cn = ni.FirstP(); !(ni.AtEnd()); cn = ni.NextP() )
   {
      if( !cn->getBoundaryFlag() ) slpofs << cn->getSlope() << endl;
      else slpofs << 0 << endl;
      qofs << cn->getQ() << endl;
      if( vegofs.good() ) vegofs << cn->getVegCover().getVeg() << endl;
      if( flowdepofs.good() )
          flowdepofs << cn->getHydrDepth() << endl;
      if( cn->getNumg()>1 ) // temporary hack TODO
      {
            texofs << cn->getLayerDgrade(0,0)/cn->getLayerDepth(0) << endl;
      }

   }

   layofs.close();
}

/*************************************************************************\
**
**  tOutput::WriteTSOutput
**  This function writes the total volume of the DEM above the datum to
**  a file called name.vols, where "name" is a name that the user has
**  specified in the input file and which is stored in the data member
**  baseName.
**
\*************************************************************************/
template< class tSubNode >
void tLOutput<tSubNode>::WriteTSOutput()
{
   tMeshListIter<tSubNode> niter( m->getNodeList() ); // node list iterator

   tSubNode * cn;       // current node

   double volume = 0,
          area = 0,
          cover = 0;

   cout << "tLOutput::WriteTSOutput()\n" << flush;

   for( cn=niter.FirstP(); !(niter.AtEnd()); cn=niter.NextP() ) {
       volume += cn->getZ()*cn->getVArea();
       area += cn->getVArea();
   }

   volsofs << volume << endl;
   tareaofs << area << endl;

   if( vegofs.good() ) {
     for( cn = niter.FirstP(); !(niter.AtEnd()); cn=niter.NextP() )
       cover += cn->getVegCover().getVeg()*cn->getVArea();
     vegcovofs << cover/area << endl;
   }

}

template< class tSubNode >
int tLOutput<tSubNode>::NodeCount()
{
  tMeshListIter<tSubNode> niter( m->getNodeList() ); // node list iterator

  tSubNode * cn;       // current node

  int count = 0;

  for( cn=niter.FirstP(); !(niter.AtEnd()); cn=niter.NextP() ) {
    count++;
  }

  return count;
}
<commit_msg>*** empty log message ***<commit_after>/*************************************************************************\
**
**  tOutput.cpp: Functions for output classes tOutput and tLOutput
**
**  (see tOutput.h for a description of these classes)
**
**  $Id: tOutput.cpp,v 1.44 2000-07-04 05:19:33 daniel Exp $
\*************************************************************************/

#include <math.h>    // For fmod function
#include "tOutput.h"

/*************************************************************************\
**
**  Constructor
**
**  The constructor takes two arguments, a pointer to the mesh and
**  a reference to an open input file. It reads the base name for the
**  output files from the input file, and opens and initializes these.
**
**  Input: meshPtr -- pointer to a tMesh object (or descendant), assumed
**                    valid
**         infile -- reference to an open input file, assumed valid
**
\*************************************************************************/
template< class tSubNode >
tOutput<tSubNode>::tOutput( tMesh<tSubNode> * meshPtr, tInputFile &infile )
{
   assert( meshPtr > 0 );
   m = meshPtr;

   infile.ReadItem( baseName, "OUTFILENAME" );

   CreateAndOpenFile( &nodeofs, ".nodes" );
   CreateAndOpenFile( &edgofs, ".edges" );
   CreateAndOpenFile( &triofs, ".tri" );
   CreateAndOpenFile( &zofs, ".z" );
   CreateAndOpenFile( &vaofs, ".varea" );

}

/*************************************************************************\
**
**  tOutput::CreateAndOpenFile
**
**  Opens the output file stream pointed to by theOFStream, giving it the
**  name <baseName><extension>, and checks to make sure that the ofstream
**  is valid.
**
**  Input:  theOFStream -- ptr to an ofstream object
**          extension -- file name extension (e.g., ".nodes")
**  Output: theOFStream is initialized to create an open output file
**  Assumes: extension is a null-terminated string, and the length of
**           baseName plus extension doesn't exceed kMaxNameSize+6
**           (ie, the extension is expected to be <= 6 characters)
**
\*************************************************************************/
template< class tSubNode >
void tOutput<tSubNode>::CreateAndOpenFile( ofstream *theOFStream,
                                           char *extension )
{
   char fullName[kMaxNameSize+6];  // name of file to be created

   strcpy( fullName, baseName );
   strcat( fullName, extension );
   theOFStream->open( fullName );

   if( !theOFStream->good() )
       ReportFatalError(
           "I can't create files for output. Storage space may be exhausted.");

}

/*************************************************************************\
**
**  tOutput::WriteOutput
**
**  This function writes information about the mesh to four files called
**  name.nodes, name.edges, name.tri, and name.z, where "name" is a
**  name that the user has specified in the input file and which is
**  stored in the data member baseName.
**
**  Input: time -- time of the current output time-slice
**  Output: the node, edge, and triangle ID numbers are modified so that
**          they are numbered according to their position on the list
**  Assumes: the four file ofstreams have been opened by the constructor
**           and are valid
**
**  TODO: deal with option for once-only printing of mesh when mesh not
**        deforming
\*************************************************************************/
template< class tSubNode >
void tOutput<tSubNode>::WriteOutput( double time )
{
   tMeshListIter<tSubNode> niter( m->getNodeList() ); // node list iterator
   tMeshListIter<tEdge> eiter( m->getEdgeList() );    // edge list iterator
   tPtrListIter<tTriangle> titer( m->getTriList() );     // tri list iterator
   tNode * cn;       // current node
   tEdge * ce;       // current edge
   tTriangle * ct;   // current triangle
   int id;           // id of element (node, edge, or triangle)
   int nnodes = m->getNodeList()->getSize();  // # of nodes on list
   int nedges = m->getEdgeList()->getSize();  // "    edges "
   int ntri = m->getTriList()->getSize();     // "    triangles "

   cout << "tOutput::WriteOutput()\n" << flush;

   // Renumber IDs in order by position on list
   for( cn=niter.FirstP(), id=0; id<nnodes; cn=niter.NextP(), id++ )
       cn->setID( id );
   for( ce=eiter.FirstP(), id=0; id<nedges; ce=eiter.NextP(), id++ )
       ce->setID( id );
   for( ct=titer.FirstP(), id=0; id<ntri; ct=titer.NextP(), id++ )
       ct->setID( id );

   // Write node file, z file, and varea file
   nodeofs << " " << time << endl << nnodes << endl;
   zofs << " " << time << endl << nnodes << endl;
   vaofs << " " << time << endl << nnodes << endl;
   for( cn=niter.FirstP(); !(niter.AtEnd()); cn=niter.NextP() )
   {
      nodeofs << cn->getX() << " " << cn->getY() << " "
              << cn->getEdg()->getID() << " " << cn->getBoundaryFlag() << endl;
      zofs << cn->getZ() << endl;
      vaofs << cn->getVArea() << endl;
   }

   // Write edge file
   edgofs << " " << time << endl << nedges << endl;
   for( ce=eiter.FirstP(); !(eiter.AtEnd()); ce=eiter.NextP() )
      edgofs << ce->getOriginPtrNC()->getID() << " "
             << ce->getDestinationPtrNC()->getID() << " "
             << ce->getCCWEdg()->getID() << endl;

   // Write triangle file
   int i;
   triofs << " " << time << endl << ntri << endl;
   for( ct=titer.FirstP(); !(titer.AtEnd()); ct=titer.NextP() )
   {
      for( i=0; i<=2; i++ )
          triofs << ct->pPtr(i)->getID() << " ";
      for( i=0; i<=2; i++ )
      {
          if( ct->tPtr(i) ) triofs << ct->tPtr(i)->getID() << " ";
          else triofs << "-1 ";
      }
      triofs << ct->ePtr(0)->getID() << " "
             << ct->ePtr(1)->getID() << " "
             << ct->ePtr(2)->getID() << endl;
   }

   // Call virtual function to write any additional data
   WriteNodeData( time );

}

/*************************************************************************\
**
**  tOutput::WriteNodeData
**
**  This is a virtual function which can be overridden to write any
**  additional node data. The base class version does nothing.
**
\*************************************************************************/
template< class tSubNode >
void tOutput<tSubNode>::WriteNodeData( double time )
{}

/*************************************************************************\
**
**  tLOutput constructor
**
**  Creates and opens a series of files for drainage areas, slopes, etc.
**
**  Modifications:
**    - 1/00 added "opOpt" and creation of veg output file (GT)
**    - added flow depth output file (GT 1/00)
\*************************************************************************/
template< class tSubNode >
tLOutput<tSubNode>::tLOutput( tMesh<tSubNode> *meshPtr, tInputFile &infile )
        : tOutput<tSubNode>( meshPtr, infile )  // call base-class constructor
{
   int opOpt;  // Optional modules: only output stuff when needed
   int optTSOutput;

   counter=0;
   strcpy(nums, "0123456789");

   CreateAndOpenFile( &drareaofs, ".area" );
   CreateAndOpenFile( &netofs, ".net" );
   CreateAndOpenFile( &slpofs, ".slp" );
   CreateAndOpenFile( &qofs, ".q" );
   CreateAndOpenFile( &texofs, ".tx" );
   if( (opOpt = infile.ReadItem( opOpt, "OPTVEG" ) ) )
       CreateAndOpenFile( &vegofs, ".veg" );
   if( (opOpt = infile.ReadItem( opOpt, "OPTKINWAVE" ) ) )
       CreateAndOpenFile( &flowdepofs, ".dep" );
   if( (optTSOutput = infile.ReadItem( optTSOutput, "OPTTSOUTPUT" ) ) ) {
       CreateAndOpenFile( &volsofs, ".vols" );
       if( (opOpt = infile.ReadItem( opOpt, "OPTVEG" ) ) )
	 CreateAndOpenFile( &vegcovofs, ".vcov" );
       CreateAndOpenFile( &tareaofs, ".tarea" );
   }

}

/*************************************************************************\
**
**  tLOutput::WriteNodeData
**
**  This overridden virtual function writes output for tLNodes, including
**  drainage areas, flow pathways, slopes, discharges, layer info, etc.
**
**  Modifications:
**    - 1/00 added output to veg output file (GT)
**    - added output of flow depth; made slope output for all nodes (GT 1/00)
**    - 6/00 layer info for each time step written to a different file (NG)
\*************************************************************************/
//TODO: should output boundary points as well so they'll map up with nodes
// for plotting. Means changing getSlope so it returns zero if flowedg
// undefined
template< class tSubNode >
void tLOutput<tSubNode>::WriteNodeData( double time )
{
   tMeshListIter<tSubNode> ni( m->getNodeList() ); // node list iterator
   tSubNode *cn;   // current node
   int nActiveNodes = m->getNodeList()->getActiveSize(); // # active nodes
   int nnodes = m->getNodeList()->getSize();             // total # nodes
   int i, j;      // counters

   //taking care of layer file, since new one each time step
   char ext[7];
   strcpy( ext, ".lay");
   if(counter<10)
       strncat( ext, &nums[counter], 1);
   else if(counter>=10){
      strncat(ext, &nums[counter/10], 1);
      strncat(ext, &nums[(int) fmod((double)counter,10.0)], 1);
   }
   CreateAndOpenFile( &layofs, ext );
   counter++;

   // Write current time in each file
   drareaofs << " " << time << "\n " << nActiveNodes << endl;
   netofs << " " << time << "\n " << nActiveNodes << endl;
   slpofs << " " << time << "\n " << nnodes << endl;
   qofs << " " << time << "\n " << nnodes << endl;
   layofs << " " << time << "\n" << nActiveNodes << endl;
   texofs << " " << time << "\n" << nnodes << endl;
   if( vegofs.good() ) vegofs << " " << time << "\n" << nnodes << endl;
   if( flowdepofs.good() ) flowdepofs << " " << time << "\n" << nnodes << endl;

   // Write data, including layer info
   for( cn = ni.FirstP(); ni.IsActive(); cn = ni.NextP() )
   {
      assert( cn>0 );
      drareaofs << cn->getDrArea() << endl;
      if( cn->getDownstrmNbr() )
          netofs << cn->getDownstrmNbr()->getID() << endl;
      layofs << " " << cn->getNumLayer() << endl;
      i=0;
      while(i<cn->getNumLayer()){
         layofs << cn->getLayerCtime(i) << " " << cn->getLayerRtime(i) << " " << cn->getLayerEtime(i) << endl;
         layofs << cn->getLayerDepth(i) << " " << cn->getLayerErody(i) << " " << cn->getLayerSed(i) << endl;
         j=0;
         while(j<cn->getNumg()){
            layofs << cn->getLayerDgrade(i,j) << " ";
            j++;
         }
         layofs << endl;
         i++;
      }
   }

   // Write discharge, vegetation, & texture data
   for( cn = ni.FirstP(); !(ni.AtEnd()); cn = ni.NextP() )
   {
      if( !cn->getBoundaryFlag() ) slpofs << cn->getSlope() << endl;
      else slpofs << 0 << endl;
      qofs << cn->getQ() << endl;
      if( vegofs.good() ) vegofs << cn->getVegCover().getVeg() << endl;
      if( flowdepofs.good() )
          flowdepofs << cn->getHydrDepth() << endl;
      if( cn->getNumg()>1 ) // temporary hack TODO
      {
            texofs << cn->getLayerDgrade(0,0)/cn->getLayerDepth(0) << endl;
      }

   }

   layofs.close();
}

/*************************************************************************\
**
**  tOutput::WriteTSOutput
**  This function writes the total volume of the DEM above the datum to
**  a file called name.vols, where "name" is a name that the user has
**  specified in the input file and which is stored in the data member
**  baseName.
**
\*************************************************************************/
template< class tSubNode >
void tLOutput<tSubNode>::WriteTSOutput()
{
   tMeshListIter<tSubNode> niter( m->getNodeList() ); // node list iterator

   tSubNode * cn;       // current node

   double volume = 0,
          area = 0,
          cover = 0;

   cout << "tLOutput::WriteTSOutput()\n" << flush;

   int i = 0;
   for( cn=niter.FirstP(); !(niter.AtEnd()); cn=niter.NextP() ) {
       volume += cn->getZ()*cn->getVArea();
       area += cn->getVArea();
   }

   volsofs << volume << endl;
   tareaofs << area << endl;

   if( vegofs.good() ) {
     for( cn = niter.FirstP(); !(niter.AtEnd()); cn=niter.NextP() )
       cover += cn->getVegCover().getVeg()*cn->getVArea();
     vegcovofs << cover/area << endl;
   }

}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2005, Peter Sommerlad and IFS Institute for Software at HSR Rapperswil, Switzerland
 * All rights reserved.
 *
 * This library/application is free software; you can redistribute and/or modify it under the terms of
 * the license that is included with this library/application in the file license.txt.
 */

//--- c-library modules used ---------------------------------------------------
#include <stdlib.h>

//#define TRACE_LOCKS

//--- standard modules used ----------------------------------------------------
#include "Anything.h"
#include "TraceLocks.h"
#include "Threads.h"
#include "SysLog.h"
#include "Dbg.h"
#include "Registry.h"
#include "SSLModule.h"
#include "SSLAPI.h"

//--- interface include --------------------------------------------------------
#include "SSLObjectManager.h"

SSLObjectManager *SSLObjectManager::fgSSLObjectManager = 0;

SSLObjectManager *SSLObjectManager::SSLOBJMGR()
{
	fgSSLObjectManager = SafeCast(WDModule::FindWDModule("SSLObjectManager"), SSLObjectManager);
	return fgSSLObjectManager;
}

RegisterModule(SSLObjectManager);
//---- SSLObjectManager ----------------------------------------------------------------
SSLObjectManager::SSLObjectManager(const char *name)
	: WDModule(name)
	, fSSLCtxStoreRWLock("SSLCtxStoreRWLock")
	, fSSLSessionIdStoreRWLock("SSLSessionIdStoreRWLock")
	, fSSLCtxStore(Storage::Global())
	, fSSLSessionIdStore(Storage::Global())
{
	StartTrace1(SSLObjectManager.SSLObjectManager, "Name:<" << NotNull(name) << ">");
	SysLog::Info("SSLObjectManager: <unblocked>");
}

SSLObjectManager::~SSLObjectManager()
{
	StartTrace(SSLObjectManager.~SSLObjectManager);
	Finis();
}

SSL_CTX *SSLObjectManager::GetCtx(const String &ip, const String &port, ROAnything sslModuleCfg)
{
	StartTrace(SSLObjectManager.GetCtx);
	SSL_CTX *sslctx;
	TraceAny(sslModuleCfg, "sslModuleCfg");
	TRACE_LOCK_START("GetCtx");
	{
		RWLockEntry me(fSSLCtxStoreRWLock, true);
		me.Use();
		if ( ( sslctx = (SSL_CTX *) fSSLCtxStore[ip][port].AsIFAObject(0)) != (SSL_CTX *) NULL ) {
			Trace("Found ssl context for ip: " << ip << " port:  " << port);
			return sslctx;
		}
	}
	if (!(sslModuleCfg.IsNull())) {
		Trace("Creating ssl context [SSLModule with config] for ip: " << ip << " port:  " << port);
		{
			RWLockEntry me(fSSLCtxStoreRWLock, false);
			me.Use();
			sslctx = SSLModule::GetSSLClientCtx(sslModuleCfg);
		}
	} else {
		Trace("Creating ssl context [default SSLV23_client_method] for ip: " << ip << " port:  " << port);
		{
			RWLockEntry me(fSSLCtxStoreRWLock, false);
			me.Use();
			sslctx = SSL_CTX_new(SSLv23_client_method());
		}
	}
	fSSLCtxStore[ip][port] = (IFAObject *) sslctx;
	return sslctx;
}

bool SSLObjectManager::RemoveCtx(const String &ip, const String &port)
{
	StartTrace(SSLObjectManager.RemoveCtx);
	SSL_CTX *sslctx;
	TRACE_LOCK_START("GetCtx");
	{
		RWLockEntry me(fSSLCtxStoreRWLock, true);
		me.Use();
		if ( ( sslctx = (SSL_CTX *) fSSLCtxStore[ip][port].AsIFAObject(0)) != (SSL_CTX *) NULL ) {
			Trace("Found ssl context for ip: " << ip << " port:  " << port);
			SSL_CTX_free(sslctx);
			fSSLCtxStore[ip][port] = (IFAObject *) NULL;
			return true;
		}
	}
	return false;
}

SSL_SESSION *SSLObjectManager::GetSessionId(const String &ip, const String &port)
{
	StartTrace(SSLObjectManager.GetSessionId);
	String thrId;
	thrId.Append( Thread::MyId());
	TRACE_LOCK_START("GetSessionId");
	{
		RWLockEntry me(fSSLSessionIdStoreRWLock, true);
		me.Use();

		Trace("Got SessionId for: " << ip << " port:  " << port <<
			  " thread: " << thrId <<
			  " session: " << SessionIdAsHex((SSL_SESSION *) fSSLSessionIdStore[ip][port][thrId]["session"].AsIFAObject(0)));
		return (SSL_SESSION *) fSSLSessionIdStore[ip][port][thrId]["session"].AsIFAObject(0);
	}
}

void SSLObjectManager::SetSessionId(const String &ip, const String &port, SSL_SESSION *sslSession)
{
	StartTrace(SSLObjectManager.SetSessionId);
	String thrId;
	thrId.Append( Thread::MyId());
	SSL_SESSION *sslSessionStored = NULL;
	TRACE_LOCK_START("SetSessionId");
	{
		RWLockEntry me(fSSLSessionIdStoreRWLock, false);
		me.Use();
		// If there is already a session stored in this slot, free it
		sslSessionStored = (SSL_SESSION *) fSSLSessionIdStore[ip][port][thrId]["session"].AsIFAObject(0);
		if ( sslSessionStored != (SSL_SESSION *) NULL ) {
			Trace("Freeing old SessionId: "  << SessionIdAsHex(sslSessionStored) << " RefCount: " << sslSessionStored->references);
			if ( sslSessionStored->references != 1L) {
				String msg;
				msg << "SSLObjectManager::SetSessionId:  Session: " << SessionIdAsHex(sslSessionStored) <<
					" RefCount: " << sslSessionStored->references << " (should be 1)\n";
				SysLog::WriteToStderr(msg);
			}
			SSL_SESSION_free(sslSessionStored);
			fSSLSessionIdStore[ip][port][thrId].Remove("length");
		}
		fSSLSessionIdStore[ip][port][thrId]["session"] = (IFAObject *) sslSession;
		fSSLSessionIdStore[ip][port][thrId]["length"] =
			(long) ((sslSession != (SSL_SESSION *)  NULL) ? sslSession->session_id_length : 0L);
	}
	Trace("Set SessionId for: " << ip << " port:  " << port << " thread: " << thrId <<
		  " session: " << SessionIdAsHex(sslSession));
}

bool SSLObjectManager::Init(const Anything &config)
{
	StartTrace(SSLObjectManager.Init);
	SysLog::WriteToStderr(String("\t") << fName << ". done\n");
	return ResetInit(config);
}

bool SSLObjectManager::Finis()
{
	StartTrace(SSLObjectManager.Finis);
	{
		TraceAny(fSSLCtxStore, "fSSLCfSSLCtxStoretxStoreRWLock");
		RWLockEntry me(fSSLCtxStoreRWLock, false);
		me.Use();
		for ( long ip = 0; ip < fSSLCtxStore.GetSize(); ip++) {
			for ( long port = 0; port < fSSLCtxStore[ip].GetSize(); port++) {
				Trace("Freeing ssl context for address: " << fSSLCtxStore.SlotName(ip) << " port: " << fSSLCtxStore[ip].SlotName(port));
				SSL_CTX *sslctx = (SSL_CTX *) fSSLCtxStore[ip][port].AsIFAObject(0);
				if (sslctx) {
					SSL_CTX_free(sslctx);
				}
			}
		}
		fSSLCtxStore = Anything(Storage::Global());
	}
	{
		TraceAny(fSSLSessionIdStore, "fSSLSessionIdStore");
		RWLockEntry me(fSSLSessionIdStoreRWLock, false);
		me.Use();
		for (long ip = 0; ip < fSSLSessionIdStore.GetSize(); ip++) {
			for ( long port = 0; port < fSSLSessionIdStore[ip].GetSize(); port++) {
				for ( long thrId = 0; thrId < fSSLSessionIdStore[ip][port].GetSize(); thrId++) {
					if (fSSLSessionIdStore[ip][port][thrId]["session"].AsIFAObject(0) != (IFAObject *) NULL) {
						Trace("Freeing ssl session for address: " << fSSLSessionIdStore.SlotName(ip) <<
							  " port: " << fSSLSessionIdStore[ip].SlotName(port) <<
							  " thread: " << fSSLSessionIdStore[ip][port].SlotName(thrId) <<
							  " sessionId" <<  SessionIdAsHex((SSL_SESSION *) fSSLSessionIdStore[ip][port][thrId]["session"].AsIFAObject(0)));
						SSL_SESSION_free((SSL_SESSION *) fSSLSessionIdStore[ip][port][thrId]["session"].AsIFAObject(0));
					}
				}
			}
		}
		fSSLSessionIdStore = Anything(Storage::Global());
	}
	return true;
}

void SSLObjectManager::EmptySessionIdStore()
{
	StartTrace(SSLObjectManager.EmptySessionIdStore);
	fSSLSessionIdStore = Anything(Storage::Global());
}

bool SSLObjectManager::ResetFinis(const Anything &)
{
	StartTrace(SSLObjectManager.ResetFinis);
	return true;
}

bool SSLObjectManager::ResetInit(const Anything &config)
{
	StartTrace(SSLObjectManager.ResetInit);
	return true;
}

void SSLObjectManager::EnterReInit()
{
	StartTrace(SSLObjectManager.EnterReInit);
}

void SSLObjectManager::LeaveReInit()
{
	StartTrace(SSLObjectManager.LeaveReInit);
}

String SSLObjectManager::SessionIdAsHex(SSL_SESSION *sslSession)
{
	if ((sslSession != (SSL_SESSION *) NULL) && (sslSession->session_id != (unsigned char *) NULL)) {
		String out;
		out.AppendAsHex((const unsigned char *) (void *)sslSession->session_id, sslSession->session_id_length);
		return out;
	} else {
		return String("SESSION ID IS NULL POINTER!!!");
	}
}

Anything SSLObjectManager::TraceSSLSession(SSL_SESSION *sslSession)
{
	Anything result;
	if (sslSession == (SSL_SESSION *) NULL) {
		result["session_id"] = SSLObjectManager::SessionIdAsHex(sslSession);
		return result;
	}
	result["session_id"] = SSLObjectManager::SessionIdAsHex(sslSession);
	if (sslSession->key_arg != (unsigned char *) NULL) {
		result["session_size"] = i2d_SSL_SESSION(sslSession, (unsigned char **) NULL);
	} else {
		result["key_arg"] = "NULL POINTER SESSIONVALUE";
	}
	if (sslSession->master_key != (unsigned char *) NULL) {
		String out;
		out.AppendAsHex((const unsigned char *) (void *)sslSession->master_key, sslSession->master_key_length);
		result["master_key"] = out;
	} else {
		result["master_key"] = "NULL POINTER SESSIONVALUE";
	}
	if (sslSession != (SSL_SESSION *) NULL) {
		result["not_resumable"] = sslSession->not_resumable;
		result["references"] =   sslSession->references;
		result["timeout"] = sslSession->timeout;
		result["time"] = sslSession->time;
	} else {
		result["not_resumable"] = "NULL POINTER SESSIONVALUE";
		result["references"] =   "NULL POINTER SESSIONVALUE";
		result["timeout"] = "NULL POINTER SESSIONVALUE";
		result["time"] = "NULL POINTER SESSIONVALUE";
	}
	if ((sslSession->cipher != (SSL_CIPHER *) NULL) && (sslSession->cipher->name != (char *) NULL)) {
		result["cipher"] = sslSession->cipher->name;
	} else {
		result["cipher"] = "NULL POINTER SESSIONVALUE";
	}
	return result;
}
<commit_msg>removed not needed tracing<commit_after>/*
 * Copyright (c) 2005, Peter Sommerlad and IFS Institute for Software at HSR Rapperswil, Switzerland
 * All rights reserved.
 *
 * This library/application is free software; you can redistribute and/or modify it under the terms of
 * the license that is included with this library/application in the file license.txt.
 */

//--- c-library modules used ---------------------------------------------------
#include <stdlib.h>

//#define TRACE_LOCKS

//--- standard modules used ----------------------------------------------------
#include "Anything.h"
#include "TraceLocks.h"
#include "Threads.h"
#include "SysLog.h"
#include "Dbg.h"
#include "Registry.h"
#include "SSLModule.h"
#include "SSLAPI.h"

//--- interface include --------------------------------------------------------
#include "SSLObjectManager.h"

SSLObjectManager *SSLObjectManager::fgSSLObjectManager = 0;

SSLObjectManager *SSLObjectManager::SSLOBJMGR()
{
	fgSSLObjectManager = SafeCast(WDModule::FindWDModule("SSLObjectManager"), SSLObjectManager);
	return fgSSLObjectManager;
}

RegisterModule(SSLObjectManager);
//---- SSLObjectManager ----------------------------------------------------------------
SSLObjectManager::SSLObjectManager(const char *name)
	: WDModule(name)
	, fSSLCtxStoreRWLock("SSLCtxStoreRWLock")
	, fSSLSessionIdStoreRWLock("SSLSessionIdStoreRWLock")
	, fSSLCtxStore(Storage::Global())
	, fSSLSessionIdStore(Storage::Global())
{
	StartTrace1(SSLObjectManager.SSLObjectManager, "Name:<" << NotNull(name) << ">");
	SysLog::Info("SSLObjectManager: <unblocked>");
}

SSLObjectManager::~SSLObjectManager()
{
	StartTrace(SSLObjectManager.~SSLObjectManager);
	Finis();
}

SSL_CTX *SSLObjectManager::GetCtx(const String &ip, const String &port, ROAnything sslModuleCfg)
{
	StartTrace(SSLObjectManager.GetCtx);
	SSL_CTX *sslctx;
	TraceAny(sslModuleCfg, "sslModuleCfg");
	TRACE_LOCK_START("GetCtx");
	{
		RWLockEntry me(fSSLCtxStoreRWLock, true);
		me.Use();
		if ( ( sslctx = (SSL_CTX *) fSSLCtxStore[ip][port].AsIFAObject(0)) != (SSL_CTX *) NULL ) {
			Trace("Found ssl context for ip: " << ip << " port:  " << port);
			return sslctx;
		}
	}
	if (!(sslModuleCfg.IsNull())) {
		Trace("Creating ssl context [SSLModule with config] for ip: " << ip << " port:  " << port);
		{
			RWLockEntry me(fSSLCtxStoreRWLock, false);
			me.Use();
			sslctx = SSLModule::GetSSLClientCtx(sslModuleCfg);
		}
	} else {
		Trace("Creating ssl context [default SSLV23_client_method] for ip: " << ip << " port:  " << port);
		{
			RWLockEntry me(fSSLCtxStoreRWLock, false);
			me.Use();
			sslctx = SSL_CTX_new(SSLv23_client_method());
		}
	}
	fSSLCtxStore[ip][port] = (IFAObject *) sslctx;
	return sslctx;
}

bool SSLObjectManager::RemoveCtx(const String &ip, const String &port)
{
	StartTrace(SSLObjectManager.RemoveCtx);
	SSL_CTX *sslctx;
	TRACE_LOCK_START("GetCtx");
	{
		RWLockEntry me(fSSLCtxStoreRWLock, true);
		me.Use();
		if ( ( sslctx = (SSL_CTX *) fSSLCtxStore[ip][port].AsIFAObject(0)) != (SSL_CTX *) NULL ) {
			Trace("Found ssl context for ip: " << ip << " port:  " << port);
			SSL_CTX_free(sslctx);
			fSSLCtxStore[ip][port] = (IFAObject *) NULL;
			return true;
		}
	}
	return false;
}

SSL_SESSION *SSLObjectManager::GetSessionId(const String &ip, const String &port)
{
	StartTrace(SSLObjectManager.GetSessionId);
	String thrId;
	thrId.Append( Thread::MyId());
	TRACE_LOCK_START("GetSessionId");
	{
		RWLockEntry me(fSSLSessionIdStoreRWLock, true);
		me.Use();

		Trace("Got SessionId for: " << ip << " port:  " << port <<
			  " thread: " << thrId <<
			  " session: " << SessionIdAsHex((SSL_SESSION *) fSSLSessionIdStore[ip][port][thrId]["session"].AsIFAObject(0)));
		return (SSL_SESSION *) fSSLSessionIdStore[ip][port][thrId]["session"].AsIFAObject(0);
	}
}

void SSLObjectManager::SetSessionId(const String &ip, const String &port, SSL_SESSION *sslSession)
{
	StartTrace(SSLObjectManager.SetSessionId);
	String thrId;
	thrId.Append( Thread::MyId());
	SSL_SESSION *sslSessionStored = NULL;
	TRACE_LOCK_START("SetSessionId");
	{
		RWLockEntry me(fSSLSessionIdStoreRWLock, false);
		me.Use();
		// If there is already a session stored in this slot, free it
		sslSessionStored = (SSL_SESSION *) fSSLSessionIdStore[ip][port][thrId]["session"].AsIFAObject(0);
		if ( sslSessionStored != (SSL_SESSION *) NULL ) {
			Trace("Freeing old SessionId: "  << SessionIdAsHex(sslSessionStored) << " RefCount: " << sslSessionStored->references);
			SSL_SESSION_free(sslSessionStored);
			fSSLSessionIdStore[ip][port][thrId].Remove("length");
		}
		fSSLSessionIdStore[ip][port][thrId]["session"] = (IFAObject *) sslSession;
		fSSLSessionIdStore[ip][port][thrId]["length"] =
			(long) ((sslSession != (SSL_SESSION *)  NULL) ? sslSession->session_id_length : 0L);
	}
	Trace("Set SessionId for: " << ip << " port:  " << port << " thread: " << thrId <<
		  " session: " << SessionIdAsHex(sslSession));
}

bool SSLObjectManager::Init(const Anything &config)
{
	StartTrace(SSLObjectManager.Init);
	SysLog::WriteToStderr(String("\t") << fName << ". done\n");
	return ResetInit(config);
}

bool SSLObjectManager::Finis()
{
	StartTrace(SSLObjectManager.Finis);
	{
		TraceAny(fSSLCtxStore, "fSSLCfSSLCtxStoretxStoreRWLock");
		RWLockEntry me(fSSLCtxStoreRWLock, false);
		me.Use();
		for ( long ip = 0; ip < fSSLCtxStore.GetSize(); ip++) {
			for ( long port = 0; port < fSSLCtxStore[ip].GetSize(); port++) {
				Trace("Freeing ssl context for address: " << fSSLCtxStore.SlotName(ip) << " port: " << fSSLCtxStore[ip].SlotName(port));
				SSL_CTX *sslctx = (SSL_CTX *) fSSLCtxStore[ip][port].AsIFAObject(0);
				if (sslctx) {
					SSL_CTX_free(sslctx);
				}
			}
		}
		fSSLCtxStore = Anything(Storage::Global());
	}
	{
		TraceAny(fSSLSessionIdStore, "fSSLSessionIdStore");
		RWLockEntry me(fSSLSessionIdStoreRWLock, false);
		me.Use();
		for (long ip = 0; ip < fSSLSessionIdStore.GetSize(); ip++) {
			for ( long port = 0; port < fSSLSessionIdStore[ip].GetSize(); port++) {
				for ( long thrId = 0; thrId < fSSLSessionIdStore[ip][port].GetSize(); thrId++) {
					if (fSSLSessionIdStore[ip][port][thrId]["session"].AsIFAObject(0) != (IFAObject *) NULL) {
						Trace("Freeing ssl session for address: " << fSSLSessionIdStore.SlotName(ip) <<
							  " port: " << fSSLSessionIdStore[ip].SlotName(port) <<
							  " thread: " << fSSLSessionIdStore[ip][port].SlotName(thrId) <<
							  " sessionId" <<  SessionIdAsHex((SSL_SESSION *) fSSLSessionIdStore[ip][port][thrId]["session"].AsIFAObject(0)));
						SSL_SESSION_free((SSL_SESSION *) fSSLSessionIdStore[ip][port][thrId]["session"].AsIFAObject(0));
					}
				}
			}
		}
		fSSLSessionIdStore = Anything(Storage::Global());
	}
	return true;
}

void SSLObjectManager::EmptySessionIdStore()
{
	StartTrace(SSLObjectManager.EmptySessionIdStore);
	fSSLSessionIdStore = Anything(Storage::Global());
}

bool SSLObjectManager::ResetFinis(const Anything &)
{
	StartTrace(SSLObjectManager.ResetFinis);
	return true;
}

bool SSLObjectManager::ResetInit(const Anything &config)
{
	StartTrace(SSLObjectManager.ResetInit);
	return true;
}

void SSLObjectManager::EnterReInit()
{
	StartTrace(SSLObjectManager.EnterReInit);
}

void SSLObjectManager::LeaveReInit()
{
	StartTrace(SSLObjectManager.LeaveReInit);
}

String SSLObjectManager::SessionIdAsHex(SSL_SESSION *sslSession)
{
	if ((sslSession != (SSL_SESSION *) NULL) && (sslSession->session_id != (unsigned char *) NULL)) {
		String out;
		out.AppendAsHex((const unsigned char *) (void *)sslSession->session_id, sslSession->session_id_length);
		return out;
	} else {
		return String("SESSION ID IS NULL POINTER!!!");
	}
}

Anything SSLObjectManager::TraceSSLSession(SSL_SESSION *sslSession)
{
	Anything result;
	if (sslSession == (SSL_SESSION *) NULL) {
		result["session_id"] = SSLObjectManager::SessionIdAsHex(sslSession);
		return result;
	}
	result["session_id"] = SSLObjectManager::SessionIdAsHex(sslSession);
	if (sslSession->key_arg != (unsigned char *) NULL) {
		result["session_size"] = i2d_SSL_SESSION(sslSession, (unsigned char **) NULL);
	} else {
		result["key_arg"] = "NULL POINTER SESSIONVALUE";
	}
	if (sslSession->master_key != (unsigned char *) NULL) {
		String out;
		out.AppendAsHex((const unsigned char *) (void *)sslSession->master_key, sslSession->master_key_length);
		result["master_key"] = out;
	} else {
		result["master_key"] = "NULL POINTER SESSIONVALUE";
	}
	if (sslSession != (SSL_SESSION *) NULL) {
		result["not_resumable"] = sslSession->not_resumable;
		result["references"] =   sslSession->references;
		result["timeout"] = sslSession->timeout;
		result["time"] = sslSession->time;
	} else {
		result["not_resumable"] = "NULL POINTER SESSIONVALUE";
		result["references"] =   "NULL POINTER SESSIONVALUE";
		result["timeout"] = "NULL POINTER SESSIONVALUE";
		result["time"] = "NULL POINTER SESSIONVALUE";
	}
	if ((sslSession->cipher != (SSL_CIPHER *) NULL) && (sslSession->cipher->name != (char *) NULL)) {
		result["cipher"] = sslSession->cipher->name;
	} else {
		result["cipher"] = "NULL POINTER SESSIONVALUE";
	}
	return result;
}
<|endoftext|>


<commit_before>#ifndef ARGUMENT_TYPE_FILE_SYSTEM_HPP_
#define ARGUMENT_TYPE_FILE_SYSTEM_HPP_

#include <string>
#include <stdexcept>

#include "Tools/system_functions.h"
#include "Tools/version.h"

#include "Tools/Arguments/Types/Argument_type_limited.hpp"

namespace aff3ct
{
namespace tools
{

enum class openmode : uint8_t {read, write, read_write};

template <typename Read_F>
std::string modify_path(const std::string& val)
{
	std::string binary_path = get_binary_path();
	if (!binary_path.empty())
	{
		std::string basedir, filename;
		split_path(binary_path, basedir, filename);

		std::string aff3ct_version = aff3ct::version();
		if (!aff3ct_version.empty() && aff3ct_version[0] == 'v')
			aff3ct_version.erase(0, 1); // rm the 'v'

		std::vector<std::string> paths = {
			"../../",
			"../../../",
			"../share/aff3ct-" + aff3ct_version + "/",
			"../../share/aff3ct-" + aff3ct_version + "/",
			"/usr/share/aff3ct-" + aff3ct_version + "/",
			"/usr/share/aff3ct-" + aff3ct_version + "/",
			"/usr/local/share/aff3ct-" + aff3ct_version + "/",
			"../share/aff3ct/",
			"../../share/aff3ct/",
			"/usr/share/aff3ct/",
			"/usr/local/share/aff3ct/",
		};

		for (auto &path : paths)
		{
			std::string full_path = (path[0] != '/') ? basedir + "/" : "";
			full_path += path + val;
#if defined(_WIN32) || defined(_WIN64)
			if (path[0] == '/')
				continue;
			std::replace(full_path.begin(), full_path.end(), '/', '\\');
#endif
			if (Read_F::check(full_path))
				return full_path;
		}
	}

	return "";
}

std::string openmode_to_string(const openmode& mode);

struct Is_file
{
	static bool check(const std::string& filename);
};

struct Is_folder
{
	static bool check(const std::string& foldername);
};

struct Is_path
{
	static bool check(const std::string& path);
};

struct No_check
{
	static bool check(const std::string&);
};

template <typename T = std::string, typename Read_F = No_check, typename Write_F = No_check, typename RW_F = No_check, typename... Ranges>
class File_system_type : public Argument_type_limited<T,Ranges...>
{
protected:
	const std::string name;
	const openmode    mode;

public:
	template <typename r, typename... R>
	explicit File_system_type(const std::string& name, const openmode& mode, const r* range, const R*... ranges)
	: Argument_type_limited<T,Ranges...>(generate_title(name, mode), range, ranges...), name(name), mode(mode)
	{ }

	explicit File_system_type(const std::string& name, const openmode& mode)
	: Argument_type_limited<T,Ranges...>(generate_title(name, mode)), name(name), mode(mode)
	{ }

	virtual ~File_system_type() {};

	virtual File_system_type<T, Read_F, Write_F, RW_F, Ranges...>* clone() const
	{
		auto* clone = new File_system_type<T, Read_F, Write_F, RW_F, Ranges...>(name, mode);

		return dynamic_cast<File_system_type<T, Read_F, Write_F, RW_F, Ranges...>*>(this->clone_ranges(clone));
	}

	template <typename... NewRanges>
	File_system_type<T, Read_F, Write_F, RW_F, Ranges..., NewRanges...>* clone(NewRanges*... new_ranges)
	{
		auto* clone = new File_system_type<T, Read_F, Write_F, RW_F, Ranges..., NewRanges...>(name, mode);

		this->clone_ranges(clone);

		clone->add_ranges(new_ranges...);

		return clone;
	}

	static std::string generate_title(const std::string& name, const openmode& mode)
	{
		return name + " [" + openmode_to_string(mode) + "]";
	}

	virtual T convert(const std::string& val) const
	{
		return val;
	}

	virtual void check(const std::string& val) const
	{
		auto str_val = this->convert(val);

		if (str_val.empty())
			throw std::runtime_error("shall be a " + name + " name");

		switch(mode)
		{
			case openmode::read :
				if(!Read_F::check(str_val))
					if (modify_path<Read_F>(str_val).empty())
						throw std::runtime_error("does not name an existing " + name);
				break;

			case openmode::write :
				if(!Write_F::check(str_val))
					throw std::runtime_error("does not name a " + name);
				break;

			case openmode::read_write : // nothing to check
				if(!RW_F::check(str_val))
					throw std::runtime_error("does not name a " + name);
				break;
		}

		this->check_ranges(str_val);
	}
};

}
}

#include "File.hpp"
#include "Folder.hpp"
#include "Path.hpp"

#endif /* ARGUMENT_TYPE_FILE_SYSTEM_HPP_ */<commit_msg>Fix missing include.<commit_after>#ifndef ARGUMENT_TYPE_FILE_SYSTEM_HPP_
#define ARGUMENT_TYPE_FILE_SYSTEM_HPP_

#include <string>
#include <stdexcept>
#include <algorithm>

#include "Tools/system_functions.h"
#include "Tools/version.h"

#include "Tools/Arguments/Types/Argument_type_limited.hpp"

namespace aff3ct
{
namespace tools
{

enum class openmode : uint8_t {read, write, read_write};

template <typename Read_F>
std::string modify_path(const std::string& val)
{
	std::string binary_path = get_binary_path();
	if (!binary_path.empty())
	{
		std::string basedir, filename;
		split_path(binary_path, basedir, filename);

		std::string aff3ct_version = aff3ct::version();
		if (!aff3ct_version.empty() && aff3ct_version[0] == 'v')
			aff3ct_version.erase(0, 1); // rm the 'v'

		std::vector<std::string> paths = {
			"../../",
			"../../../",
			"../share/aff3ct-" + aff3ct_version + "/",
			"../../share/aff3ct-" + aff3ct_version + "/",
			"/usr/share/aff3ct-" + aff3ct_version + "/",
			"/usr/share/aff3ct-" + aff3ct_version + "/",
			"/usr/local/share/aff3ct-" + aff3ct_version + "/",
			"../share/aff3ct/",
			"../../share/aff3ct/",
			"/usr/share/aff3ct/",
			"/usr/local/share/aff3ct/",
		};

		for (auto &path : paths)
		{
			std::string full_path = (path[0] != '/') ? basedir + "/" : "";
			full_path += path + val;
#if defined(_WIN32) || defined(_WIN64)
			if (path[0] == '/')
				continue;
			std::replace(full_path.begin(), full_path.end(), '/', '\\');
#endif
			if (Read_F::check(full_path))
				return full_path;
		}
	}

	return "";
}

std::string openmode_to_string(const openmode& mode);

struct Is_file
{
	static bool check(const std::string& filename);
};

struct Is_folder
{
	static bool check(const std::string& foldername);
};

struct Is_path
{
	static bool check(const std::string& path);
};

struct No_check
{
	static bool check(const std::string&);
};

template <typename T = std::string, typename Read_F = No_check, typename Write_F = No_check, typename RW_F = No_check, typename... Ranges>
class File_system_type : public Argument_type_limited<T,Ranges...>
{
protected:
	const std::string name;
	const openmode    mode;

public:
	template <typename r, typename... R>
	explicit File_system_type(const std::string& name, const openmode& mode, const r* range, const R*... ranges)
	: Argument_type_limited<T,Ranges...>(generate_title(name, mode), range, ranges...), name(name), mode(mode)
	{ }

	explicit File_system_type(const std::string& name, const openmode& mode)
	: Argument_type_limited<T,Ranges...>(generate_title(name, mode)), name(name), mode(mode)
	{ }

	virtual ~File_system_type() {};

	virtual File_system_type<T, Read_F, Write_F, RW_F, Ranges...>* clone() const
	{
		auto* clone = new File_system_type<T, Read_F, Write_F, RW_F, Ranges...>(name, mode);

		return dynamic_cast<File_system_type<T, Read_F, Write_F, RW_F, Ranges...>*>(this->clone_ranges(clone));
	}

	template <typename... NewRanges>
	File_system_type<T, Read_F, Write_F, RW_F, Ranges..., NewRanges...>* clone(NewRanges*... new_ranges)
	{
		auto* clone = new File_system_type<T, Read_F, Write_F, RW_F, Ranges..., NewRanges...>(name, mode);

		this->clone_ranges(clone);

		clone->add_ranges(new_ranges...);

		return clone;
	}

	static std::string generate_title(const std::string& name, const openmode& mode)
	{
		return name + " [" + openmode_to_string(mode) + "]";
	}

	virtual T convert(const std::string& val) const
	{
		return val;
	}

	virtual void check(const std::string& val) const
	{
		auto str_val = this->convert(val);

		if (str_val.empty())
			throw std::runtime_error("shall be a " + name + " name");

		switch(mode)
		{
			case openmode::read :
				if(!Read_F::check(str_val))
					if (modify_path<Read_F>(str_val).empty())
						throw std::runtime_error("does not name an existing " + name);
				break;

			case openmode::write :
				if(!Write_F::check(str_val))
					throw std::runtime_error("does not name a " + name);
				break;

			case openmode::read_write : // nothing to check
				if(!RW_F::check(str_val))
					throw std::runtime_error("does not name a " + name);
				break;
		}

		this->check_ranges(str_val);
	}
};

}
}

#include "File.hpp"
#include "Folder.hpp"
#include "Path.hpp"

#endif /* ARGUMENT_TYPE_FILE_SYSTEM_HPP_ */<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016 Alvin Wong <alvinhochun@gmail.com>
 *
 * 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 "dllmain.h"
#include "KritaThumbnailProvider.h"
#include "zip_source_IStream.h"
#include "document.h"

#include <zip.h>

#include <memory>
#include <new>

#include <gdiplus.h>
#include <shlwapi.h>

#pragma comment(lib, "gdiplus.lib")
#pragma comment(lib, "shlwapi.lib")

using namespace kritashellex;

KritaThumbnailProvider::KritaThumbnailProvider() :
	m_refCount(1),
	m_pStream(nullptr)
{
	IncDllRef();
}

KritaThumbnailProvider::~KritaThumbnailProvider()
{
	DecDllRef();
}

IFACEMETHODIMP KritaThumbnailProvider::QueryInterface(REFIID riid, void **ppv)
{
	static const QITAB qit[] = {
		QITABENT(KritaThumbnailProvider, IThumbnailProvider),
		QITABENT(KritaThumbnailProvider, IInitializeWithStream),
		{ nullptr },
	};
	return QISearch(this, qit, riid, ppv);
}

IFACEMETHODIMP_(ULONG) KritaThumbnailProvider::AddRef()
{
	return InterlockedIncrement(&m_refCount);
}

IFACEMETHODIMP_(ULONG) KritaThumbnailProvider::Release()
{
	unsigned long refCount = InterlockedDecrement(&m_refCount);
	if (refCount == 0) {
		if (m_pStream) {
			m_pStream->Release();
		}
		delete this;
	}
	return refCount;
}

IFACEMETHODIMP KritaThumbnailProvider::Initialize(IStream *pStream, DWORD grfMode)
{
	if (m_pStream) {
		return HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED);
	}

	HRESULT hr = pStream->QueryInterface(&m_pStream);
	if (FAILED(hr)) {
		return hr;
	}

	// TODO: Handle errors from libzip?

	zip_ptr<zip_source_t> src(zip_source_IStream_create(pStream, nullptr));
	if (!src) {
		return E_NOTIMPL;
	}
	zip_ptr<zip_t> zf(zip_open_from_source(src.get(), ZIP_RDONLY, nullptr));
	if (!zf) {
		return E_NOTIMPL;
	}
	std::unique_ptr<Document> pDocument(new (std::nothrow) Document(std::move(zf), std::move(src)));
	if (!pDocument->Init()) {
		return E_NOTIMPL;
	}
	m_pDocument = std::move(pDocument);
}

IFACEMETHODIMP KritaThumbnailProvider::GetThumbnail(UINT cx, HBITMAP *phbmp, WTS_ALPHATYPE *pdwAlpha)
{
	if (!phbmp || !pdwAlpha) {
		return E_INVALIDARG;
	}

	HRESULT hr;

	*phbmp = nullptr;
	*pdwAlpha = WTSAT_ARGB;

	if (!m_pDocument) {
		return E_UNEXPECTED;
	}

	HGLOBAL hImageContent;
	hr = getThumbnailPngFromArchive(cx, hImageContent);
	if (FAILED(hr)) {
		return hr;
	}

	IStream *pStream;
	hr = CreateStreamOnHGlobal(hImageContent, TRUE, &pStream);
	if (FAILED(hr)) {
		GlobalFree(hImageContent);
		return hr;
	}

	hr = getThumbnailFromPngStream(cx, pStream, *phbmp);
	if (FAILED(hr)) {
		return hr;
	}

	if (*phbmp) {
		return S_OK;
	}
	return E_FAIL;
}

HRESULT KritaThumbnailProvider::getThumbnailPngFromArchive(UINT cx, HGLOBAL &hImageContent_out) const
{
	const char *szImageFileName = nullptr;
	if (cx > 256) {
		szImageFileName = "mergedimage.png";
	}

	if (!szImageFileName || FAILED(getThumbnailPngFromArchiveByName(cx, szImageFileName, hImageContent_out))) {
		// Try preview.png for .kra files
		szImageFileName = "preview.png";
		if (FAILED(getThumbnailPngFromArchiveByName(cx, szImageFileName, hImageContent_out))) {
			// Try Thumbnails/thumbnail.png for .ora files
			szImageFileName = "Thumbnails/thumbnail.png";
			if (FAILED(getThumbnailPngFromArchiveByName(cx, szImageFileName, hImageContent_out))) {
				if (cx > 256) {
					return E_NOTIMPL;
				} else {
					// Try mergedimage.png if thumbnail can't be used
					szImageFileName = "mergedimage.png";
					if (FAILED(getThumbnailPngFromArchiveByName(cx, szImageFileName, hImageContent_out))) {
						return E_NOTIMPL;
					}
				}
			}
		}
	}

	return S_OK;
}

HRESULT KritaThumbnailProvider::getThumbnailPngFromArchiveByName(UINT cx, const char *const filename, HGLOBAL &hImageContent_out) const
{
	size_t imageSize;
	if (!m_pDocument->getFileSize(filename, imageSize)) {
		return E_NOTIMPL;
	}

	hImageContent_out = GlobalAlloc(GMEM_MOVEABLE, imageSize);
	if (!hImageContent_out) {
		return HRESULT_FROM_WIN32(GetLastError());
	}
	LPVOID pImageContent = GlobalLock(hImageContent_out);
	if (!pImageContent) {
		GlobalFree(hImageContent_out);
		return HRESULT_FROM_WIN32(GetLastError());
	}

	if (!m_pDocument->getFileContent(filename, static_cast<char *>(pImageContent), imageSize)) {
		GlobalUnlock(hImageContent_out);
		GlobalFree(hImageContent_out);
		return E_NOTIMPL;
	}

	GlobalUnlock(hImageContent_out);
	return S_OK;
}

HRESULT KritaThumbnailProvider::getThumbnailFromPngStream(UINT cx, IStream *pStream, HBITMAP &hbmp_out)
{
	ULONG_PTR token;
	Gdiplus::GdiplusStartupInput input;
	if (Gdiplus::GdiplusStartup(&token, &input, nullptr) != Gdiplus::Ok) {
		pStream->Release();
		return E_FAIL;
	}

	HRESULT hr = getThumbnailFromPngStreamGdiplus(cx, pStream, hbmp_out);

	Gdiplus::GdiplusShutdown(token);

	if (FAILED(hr)) {
		return hr;
	}
	return S_OK;
}

HRESULT KritaThumbnailProvider::getThumbnailFromPngStreamGdiplus(UINT cx, IStream *pStream, HBITMAP &hbmp_out)
{
	std::unique_ptr<Gdiplus::Bitmap> pImageBitmap;
	HRESULT hr = getBitmapFromPngStreamGdiplus(pStream, pImageBitmap);
	if (FAILED(hr)) {
		return hr;
	}

	hr = getThumbnailFromBitmap(cx, pImageBitmap.get(), hbmp_out);

	if (FAILED(hr)) {
		return hr;
	}
	return S_OK;
}

HRESULT KritaThumbnailProvider::getBitmapFromPngStreamGdiplus(IStream *pStream, std::unique_ptr<Gdiplus::Bitmap> &pImageBitmap_out)
{
	std::unique_ptr<Gdiplus::Bitmap> pImageBitmap(new Gdiplus::Bitmap(pStream));
	pStream->Release();
	if (pImageBitmap->GetLastStatus() != Gdiplus::Ok) {
		return E_FAIL;
	}
	pImageBitmap_out = std::move(pImageBitmap);

	return S_OK;
}

HRESULT KritaThumbnailProvider::getThumbnailFromBitmap(UINT cx, Gdiplus::Bitmap *pImageBitmap, HBITMAP &hbmp_out)
{
	unsigned long imageHeight = pImageBitmap->GetHeight();
	unsigned long imageWidth = pImageBitmap->GetWidth();
	unsigned long dstHeight, dstWidth;
	if (imageHeight <= cx && imageWidth <= cx) {
		// If image fits into or is smaller than requested size, don't scale at all
		dstWidth = imageWidth;
		dstHeight = imageHeight;
	} else if (imageHeight == imageWidth) {
		dstWidth = cx;
		dstHeight = cx;
	} else if (imageHeight > imageWidth) {
		dstWidth = cx * imageWidth / imageHeight;
		dstHeight = cx;
	} else {
		dstWidth = cx;
		dstHeight = cx * imageHeight / imageWidth;
	}

	std::unique_ptr<Gdiplus::Bitmap> pDstBitmap(new Gdiplus::Bitmap(dstWidth, dstHeight, PixelFormat32bppARGB));
	if (pDstBitmap->GetLastStatus() != Gdiplus::Ok) {
		return E_FAIL;
	}
	{
		Gdiplus::Graphics g(pDstBitmap.get());
		g.DrawImage(pImageBitmap, 0, 0, dstWidth, dstHeight);
	}
	pDstBitmap->GetHBITMAP(Gdiplus::Color::Transparent, &hbmp_out);

	return S_OK;
}
<commit_msg>Fix missing return value<commit_after>/*
 * Copyright (c) 2016 Alvin Wong <alvinhochun@gmail.com>
 *
 * 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 "dllmain.h"
#include "KritaThumbnailProvider.h"
#include "zip_source_IStream.h"
#include "document.h"

#include <zip.h>

#include <memory>
#include <new>

#include <gdiplus.h>
#include <shlwapi.h>

#pragma comment(lib, "gdiplus.lib")
#pragma comment(lib, "shlwapi.lib")

using namespace kritashellex;

KritaThumbnailProvider::KritaThumbnailProvider() :
	m_refCount(1),
	m_pStream(nullptr)
{
	IncDllRef();
}

KritaThumbnailProvider::~KritaThumbnailProvider()
{
	DecDllRef();
}

IFACEMETHODIMP KritaThumbnailProvider::QueryInterface(REFIID riid, void **ppv)
{
	static const QITAB qit[] = {
		QITABENT(KritaThumbnailProvider, IThumbnailProvider),
		QITABENT(KritaThumbnailProvider, IInitializeWithStream),
		{ nullptr },
	};
	return QISearch(this, qit, riid, ppv);
}

IFACEMETHODIMP_(ULONG) KritaThumbnailProvider::AddRef()
{
	return InterlockedIncrement(&m_refCount);
}

IFACEMETHODIMP_(ULONG) KritaThumbnailProvider::Release()
{
	unsigned long refCount = InterlockedDecrement(&m_refCount);
	if (refCount == 0) {
		if (m_pStream) {
			m_pStream->Release();
		}
		delete this;
	}
	return refCount;
}

IFACEMETHODIMP KritaThumbnailProvider::Initialize(IStream *pStream, DWORD grfMode)
{
	if (m_pStream) {
		return HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED);
	}

	HRESULT hr = pStream->QueryInterface(&m_pStream);
	if (FAILED(hr)) {
		return hr;
	}

	// TODO: Handle errors from libzip?

	zip_ptr<zip_source_t> src(zip_source_IStream_create(pStream, nullptr));
	if (!src) {
		return E_NOTIMPL;
	}
	zip_ptr<zip_t> zf(zip_open_from_source(src.get(), ZIP_RDONLY, nullptr));
	if (!zf) {
		return E_NOTIMPL;
	}
	std::unique_ptr<Document> pDocument(new (std::nothrow) Document(std::move(zf), std::move(src)));
	if (!pDocument->Init()) {
		return E_NOTIMPL;
	}
	m_pDocument = std::move(pDocument);

	return S_OK;
}

IFACEMETHODIMP KritaThumbnailProvider::GetThumbnail(UINT cx, HBITMAP *phbmp, WTS_ALPHATYPE *pdwAlpha)
{
	if (!phbmp || !pdwAlpha) {
		return E_INVALIDARG;
	}

	HRESULT hr;

	*phbmp = nullptr;
	*pdwAlpha = WTSAT_ARGB;

	if (!m_pDocument) {
		return E_UNEXPECTED;
	}

	HGLOBAL hImageContent;
	hr = getThumbnailPngFromArchive(cx, hImageContent);
	if (FAILED(hr)) {
		return hr;
	}

	IStream *pStream;
	hr = CreateStreamOnHGlobal(hImageContent, TRUE, &pStream);
	if (FAILED(hr)) {
		GlobalFree(hImageContent);
		return hr;
	}

	hr = getThumbnailFromPngStream(cx, pStream, *phbmp);
	if (FAILED(hr)) {
		return hr;
	}

	if (*phbmp) {
		return S_OK;
	}
	return E_FAIL;
}

HRESULT KritaThumbnailProvider::getThumbnailPngFromArchive(UINT cx, HGLOBAL &hImageContent_out) const
{
	const char *szImageFileName = nullptr;
	if (cx > 256) {
		szImageFileName = "mergedimage.png";
	}

	if (!szImageFileName || FAILED(getThumbnailPngFromArchiveByName(cx, szImageFileName, hImageContent_out))) {
		// Try preview.png for .kra files
		szImageFileName = "preview.png";
		if (FAILED(getThumbnailPngFromArchiveByName(cx, szImageFileName, hImageContent_out))) {
			// Try Thumbnails/thumbnail.png for .ora files
			szImageFileName = "Thumbnails/thumbnail.png";
			if (FAILED(getThumbnailPngFromArchiveByName(cx, szImageFileName, hImageContent_out))) {
				if (cx > 256) {
					return E_NOTIMPL;
				} else {
					// Try mergedimage.png if thumbnail can't be used
					szImageFileName = "mergedimage.png";
					if (FAILED(getThumbnailPngFromArchiveByName(cx, szImageFileName, hImageContent_out))) {
						return E_NOTIMPL;
					}
				}
			}
		}
	}

	return S_OK;
}

HRESULT KritaThumbnailProvider::getThumbnailPngFromArchiveByName(UINT cx, const char *const filename, HGLOBAL &hImageContent_out) const
{
	size_t imageSize;
	if (!m_pDocument->getFileSize(filename, imageSize)) {
		return E_NOTIMPL;
	}

	hImageContent_out = GlobalAlloc(GMEM_MOVEABLE, imageSize);
	if (!hImageContent_out) {
		return HRESULT_FROM_WIN32(GetLastError());
	}
	LPVOID pImageContent = GlobalLock(hImageContent_out);
	if (!pImageContent) {
		GlobalFree(hImageContent_out);
		return HRESULT_FROM_WIN32(GetLastError());
	}

	if (!m_pDocument->getFileContent(filename, static_cast<char *>(pImageContent), imageSize)) {
		GlobalUnlock(hImageContent_out);
		GlobalFree(hImageContent_out);
		return E_NOTIMPL;
	}

	GlobalUnlock(hImageContent_out);
	return S_OK;
}

HRESULT KritaThumbnailProvider::getThumbnailFromPngStream(UINT cx, IStream *pStream, HBITMAP &hbmp_out)
{
	ULONG_PTR token;
	Gdiplus::GdiplusStartupInput input;
	if (Gdiplus::GdiplusStartup(&token, &input, nullptr) != Gdiplus::Ok) {
		pStream->Release();
		return E_FAIL;
	}

	HRESULT hr = getThumbnailFromPngStreamGdiplus(cx, pStream, hbmp_out);

	Gdiplus::GdiplusShutdown(token);

	if (FAILED(hr)) {
		return hr;
	}
	return S_OK;
}

HRESULT KritaThumbnailProvider::getThumbnailFromPngStreamGdiplus(UINT cx, IStream *pStream, HBITMAP &hbmp_out)
{
	std::unique_ptr<Gdiplus::Bitmap> pImageBitmap;
	HRESULT hr = getBitmapFromPngStreamGdiplus(pStream, pImageBitmap);
	if (FAILED(hr)) {
		return hr;
	}

	hr = getThumbnailFromBitmap(cx, pImageBitmap.get(), hbmp_out);

	if (FAILED(hr)) {
		return hr;
	}
	return S_OK;
}

HRESULT KritaThumbnailProvider::getBitmapFromPngStreamGdiplus(IStream *pStream, std::unique_ptr<Gdiplus::Bitmap> &pImageBitmap_out)
{
	std::unique_ptr<Gdiplus::Bitmap> pImageBitmap(new Gdiplus::Bitmap(pStream));
	pStream->Release();
	if (pImageBitmap->GetLastStatus() != Gdiplus::Ok) {
		return E_FAIL;
	}
	pImageBitmap_out = std::move(pImageBitmap);

	return S_OK;
}

HRESULT KritaThumbnailProvider::getThumbnailFromBitmap(UINT cx, Gdiplus::Bitmap *pImageBitmap, HBITMAP &hbmp_out)
{
	unsigned long imageHeight = pImageBitmap->GetHeight();
	unsigned long imageWidth = pImageBitmap->GetWidth();
	unsigned long dstHeight, dstWidth;
	if (imageHeight <= cx && imageWidth <= cx) {
		// If image fits into or is smaller than requested size, don't scale at all
		dstWidth = imageWidth;
		dstHeight = imageHeight;
	} else if (imageHeight == imageWidth) {
		dstWidth = cx;
		dstHeight = cx;
	} else if (imageHeight > imageWidth) {
		dstWidth = cx * imageWidth / imageHeight;
		dstHeight = cx;
	} else {
		dstWidth = cx;
		dstHeight = cx * imageHeight / imageWidth;
	}

	std::unique_ptr<Gdiplus::Bitmap> pDstBitmap(new Gdiplus::Bitmap(dstWidth, dstHeight, PixelFormat32bppARGB));
	if (pDstBitmap->GetLastStatus() != Gdiplus::Ok) {
		return E_FAIL;
	}
	{
		Gdiplus::Graphics g(pDstBitmap.get());
		g.DrawImage(pImageBitmap, 0, 0, dstWidth, dstHeight);
	}
	pDstBitmap->GetHBITMAP(Gdiplus::Color::Transparent, &hbmp_out);

	return S_OK;
}
<|endoftext|>


<commit_before>#include <string>

#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/tcp.h>

#include "client.h"

using namespace std;

namespace rpc {

void Future::wait() {
    Pthread_mutex_lock(&ready_m_);
    while (!ready_) {
        Pthread_cond_wait(&ready_cond_, &ready_m_);
    }
    Pthread_mutex_unlock(&ready_m_);
}

void Future::notify_ready() {
    Pthread_mutex_lock(&ready_m_);
    ready_ = true;
    Pthread_cond_signal(&ready_cond_);
    Pthread_mutex_unlock(&ready_m_);
    if (attr_.callback != nullptr) {
        attr_.callback(this);
    }
}

void Client::invalidate_pending_futures() {
    list<Future*> futures;
    pending_fu_l_.lock();
    while (pending_fu_.empty() == false) {
        futures.push_back(pending_fu_.begin()->second);
        pending_fu_.erase(pending_fu_.begin());
    }
    pending_fu_l_.unlock();

    for (list<Future*>::iterator it = futures.begin(); it != futures.end(); ++it) {
        Future* fu = *it;
        if (fu != NULL) {
            fu->error_code_ = ENOTCONN;
            fu->notify_ready();

            // since we removed it from pending_fu_
            fu->release();
        }
    }

}

void Client::close() {
    if (status_ == CONNECTED) {
        pollmgr_->remove(this);
        ::close(sock_);
        status_ = CLOSED;

        invalidate_pending_futures();
    }
    status_ = CLOSED;
}

int Client::connect(const char* addr) {
    string addr_str(addr);
    size_t idx = addr_str.find(":");
    if (idx == string::npos) {
        Log_error("rpc::Client: bad connect address: %s", addr);
        errno = EINVAL;
        return -1;
    }
    string host = addr_str.substr(0, idx);
    string port = addr_str.substr(idx + 1);

    struct addrinfo hints, *result, *rp;
    memset(&hints, 0, sizeof(struct addrinfo));

    hints.ai_family = AF_INET; // ipv4
    hints.ai_socktype = SOCK_STREAM; // tcp

    int r = getaddrinfo(host.c_str(), port.c_str(), &hints, &result);
    if (r != 0) {
        Log_error("rpc::Client: getaddrinfo(): %s", gai_strerror(r));
        return -1;
    }

    for (rp = result; rp != NULL; rp = rp->ai_next) {
        sock_ = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
        if (sock_ == -1) {
            continue;
        }

        const int yes = 1;
        verify(setsockopt(sock_, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == 0);
        verify(setsockopt(sock_, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == 0);

        if (::connect(sock_, rp->ai_addr, rp->ai_addrlen) == 0) {
            break;
        }
        ::close(sock_);
        sock_ = -1;
    }
    freeaddrinfo(result);

    if (rp == NULL) {
        // failed to connect
        Log_error("rpc::Client: connect(%s): %s", addr, strerror(errno));
        return -1;
    }

    verify(set_nonblocking(sock_, true) == 0);
    Log_info("rpc::Client: connected to %s", addr);

    status_ = CONNECTED;
    pollmgr_->add(this);

    return 0;
}

void Client::handle_error() {
    close();
}

void Client::handle_write(const io_ratelimit& rate) {
    if (status_ != CONNECTED) {
        return;
    }

    out_l_.lock();
    Marshal::read_barrier barrier = out_.get_read_barrier();
    out_l_.unlock();

    out_.write_to_fd(sock_, barrier, rate);

    out_l_.lock();
    if (out_.empty()) {
        pollmgr_->update_mode(this, Pollable::READ);
    }
    out_l_.unlock();
}

void Client::handle_read() {
    if (status_ != CONNECTED) {
        return;
    }

    int bytes_read = in_.read_from_fd(sock_);
    if (bytes_read == 0) {
        return;
    }

    for (;;) {
        i32 packet_size;
        int n_peek = in_.peek(&packet_size, sizeof(i32));
        if (n_peek == sizeof(i32) && in_.content_size_gt(packet_size + sizeof(i32) - 1)) {
            // consume the packet size
            verify(in_.read(&packet_size, sizeof(i32)) == sizeof(i32));

            i64 reply_xid;
            i32 error_code;

            in_ >> reply_xid >> error_code;

            pending_fu_l_.lock();
            unordered_map<i64, Future*>::iterator it = pending_fu_.find(reply_xid);
            if (it != pending_fu_.end()) {
                Future* fu = it->second;
                verify(fu->xid_ == reply_xid);
                pending_fu_.erase(it);
                pending_fu_l_.unlock();

                fu->error_code_ = error_code;
                fu->reply_.read_from_marshal(in_, packet_size - sizeof(reply_xid) - sizeof(error_code));

                fu->notify_ready();

                // since we removed it from pending_fu_
                fu->release();
            } else {
                pending_fu_l_.unlock();
            }

        } else {
            // packet incomplete or no more packets to process
            break;
        }
    }
}

int Client::poll_mode() {
    int mode = Pollable::READ;
    out_l_.lock();
    if (!out_.empty()) {
        mode |= Pollable::WRITE;
    }
    out_l_.unlock();
    return mode;
}

Future* Client::begin_request(i32 rpc_id, const FutureAttr& attr /* =... */) {
    out_l_.lock();

    if (status_ != CONNECTED) {
        return NULL;
    }

    Future* fu = new Future(xid_counter_.next(), attr);
    pending_fu_l_.lock();
    pending_fu_[fu->xid_] = fu;
    pending_fu_.size();
    pending_fu_l_.unlock();

    // check if the client gets closed in the meantime
    if (status_ != CONNECTED) {
        pending_fu_l_.lock();
        unordered_map<i64, Future*>::iterator it = pending_fu_.find(fu->xid_);
        if (it != pending_fu_.end()) {
            it->second->release();
            pending_fu_.erase(it);
        }
        pending_fu_l_.unlock();

        return NULL;
    }

    bmark_ = out_.set_bookmark(sizeof(i32)); // will fill packet size later

    *this << fu->xid_;
    *this << rpc_id;

    // one ref is already in pending_fu_
    return (Future *) fu->ref_copy();
}

void Client::end_request() {
    // set reply size in packet
    if (bmark_ != NULL) {
        i32 request_size = out_.get_and_reset_write_cnt();
        out_.write_bookmark(bmark_, &request_size);
        out_.update_read_barrier();
        delete bmark_;
        bmark_ = NULL;
    }

    // always enable write events since the code above gauranteed there
    // will be some data to send
    pollmgr_->update_mode(this, Pollable::READ | Pollable::WRITE);

    out_l_.unlock();
}

ClientPool::ClientPool(PollMgr* pollmgr /* =? */, int parallel_connections /* =? */)
        : parallel_connections_(parallel_connections) {

    if (pollmgr == NULL) {
        pollmgr_ = new PollMgr;
    } else {
        pollmgr_ = (PollMgr *) pollmgr->ref_copy();
    }
}

ClientPool::~ClientPool() {
    for (auto& it : cache_) {
        for (int i = 0; i < parallel_connections_; i++) {
            it.second[i]->close_and_release();
        }
        delete[] it.second;
    }
    pollmgr_->release();
}

Client* ClientPool::get_client(const string& addr) {
    Client* cl = NULL;
    l_.lock();
    map<string, Client**>::iterator it = cache_.find(addr);
    if (it != cache_.end()) {
        cl = it->second[rand_() % parallel_connections_];
    } else {
        Client** parallel_clients = new Client*[parallel_connections_];
        int i;
        bool ok = true;
        for (i = 0; i < parallel_connections_; i++) {
            parallel_clients[i] = new Client(this->pollmgr_);
            if (parallel_clients[i]->connect(addr.c_str()) != 0) {
                ok = false;
                break;
            }
        }
        if (ok) {
            cl = parallel_clients[rand_() % parallel_connections_];
            cache_.insert(std::map<std::string, rpc::Client**>::value_type(addr, parallel_clients));
        } else {
            // close connections
            while (i >= 0) {
                parallel_clients[i]->close_and_release();
                i--;
            }
            delete[] parallel_clients;
        }
    }
    l_.unlock();
    return cl;
}

}
<commit_msg>use full locking for now<commit_after>#include <string>

#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/tcp.h>

#include "client.h"

using namespace std;

namespace rpc {

void Future::wait() {
    Pthread_mutex_lock(&ready_m_);
    while (!ready_) {
        Pthread_cond_wait(&ready_cond_, &ready_m_);
    }
    Pthread_mutex_unlock(&ready_m_);
}

void Future::notify_ready() {
    Pthread_mutex_lock(&ready_m_);
    ready_ = true;
    Pthread_cond_signal(&ready_cond_);
    Pthread_mutex_unlock(&ready_m_);
    if (attr_.callback != nullptr) {
        attr_.callback(this);
    }
}

void Client::invalidate_pending_futures() {
    list<Future*> futures;
    pending_fu_l_.lock();
    while (pending_fu_.empty() == false) {
        futures.push_back(pending_fu_.begin()->second);
        pending_fu_.erase(pending_fu_.begin());
    }
    pending_fu_l_.unlock();

    for (list<Future*>::iterator it = futures.begin(); it != futures.end(); ++it) {
        Future* fu = *it;
        if (fu != NULL) {
            fu->error_code_ = ENOTCONN;
            fu->notify_ready();

            // since we removed it from pending_fu_
            fu->release();
        }
    }

}

void Client::close() {
    if (status_ == CONNECTED) {
        pollmgr_->remove(this);
        ::close(sock_);
        status_ = CLOSED;

        invalidate_pending_futures();
    }
    status_ = CLOSED;
}

int Client::connect(const char* addr) {
    string addr_str(addr);
    size_t idx = addr_str.find(":");
    if (idx == string::npos) {
        Log_error("rpc::Client: bad connect address: %s", addr);
        errno = EINVAL;
        return -1;
    }
    string host = addr_str.substr(0, idx);
    string port = addr_str.substr(idx + 1);

    struct addrinfo hints, *result, *rp;
    memset(&hints, 0, sizeof(struct addrinfo));

    hints.ai_family = AF_INET; // ipv4
    hints.ai_socktype = SOCK_STREAM; // tcp

    int r = getaddrinfo(host.c_str(), port.c_str(), &hints, &result);
    if (r != 0) {
        Log_error("rpc::Client: getaddrinfo(): %s", gai_strerror(r));
        return -1;
    }

    for (rp = result; rp != NULL; rp = rp->ai_next) {
        sock_ = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
        if (sock_ == -1) {
            continue;
        }

        const int yes = 1;
        verify(setsockopt(sock_, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == 0);
        verify(setsockopt(sock_, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == 0);

        if (::connect(sock_, rp->ai_addr, rp->ai_addrlen) == 0) {
            break;
        }
        ::close(sock_);
        sock_ = -1;
    }
    freeaddrinfo(result);

    if (rp == NULL) {
        // failed to connect
        Log_error("rpc::Client: connect(%s): %s", addr, strerror(errno));
        return -1;
    }

    verify(set_nonblocking(sock_, true) == 0);
    Log_info("rpc::Client: connected to %s", addr);

    status_ = CONNECTED;
    pollmgr_->add(this);

    return 0;
}

void Client::handle_error() {
    close();
}

void Client::handle_write(const io_ratelimit& rate) {
    if (status_ != CONNECTED) {
        return;
    }

    out_l_.lock();
    Marshal::read_barrier barrier = out_.get_read_barrier();
//    out_l_.unlock();

    out_.write_to_fd(sock_, barrier, rate);

//    out_l_.lock();
    if (out_.empty()) {
        pollmgr_->update_mode(this, Pollable::READ);
    }
    out_l_.unlock();
}

void Client::handle_read() {
    if (status_ != CONNECTED) {
        return;
    }

    int bytes_read = in_.read_from_fd(sock_);
    if (bytes_read == 0) {
        return;
    }

    for (;;) {
        i32 packet_size;
        int n_peek = in_.peek(&packet_size, sizeof(i32));
        if (n_peek == sizeof(i32) && in_.content_size_gt(packet_size + sizeof(i32) - 1)) {
            // consume the packet size
            verify(in_.read(&packet_size, sizeof(i32)) == sizeof(i32));

            i64 reply_xid;
            i32 error_code;

            in_ >> reply_xid >> error_code;

            pending_fu_l_.lock();
            unordered_map<i64, Future*>::iterator it = pending_fu_.find(reply_xid);
            if (it != pending_fu_.end()) {
                Future* fu = it->second;
                verify(fu->xid_ == reply_xid);
                pending_fu_.erase(it);
                pending_fu_l_.unlock();

                fu->error_code_ = error_code;
                fu->reply_.read_from_marshal(in_, packet_size - sizeof(reply_xid) - sizeof(error_code));

                fu->notify_ready();

                // since we removed it from pending_fu_
                fu->release();
            } else {
                pending_fu_l_.unlock();
            }

        } else {
            // packet incomplete or no more packets to process
            break;
        }
    }
}

int Client::poll_mode() {
    int mode = Pollable::READ;
    out_l_.lock();
    if (!out_.empty()) {
        mode |= Pollable::WRITE;
    }
    out_l_.unlock();
    return mode;
}

Future* Client::begin_request(i32 rpc_id, const FutureAttr& attr /* =... */) {
    out_l_.lock();

    if (status_ != CONNECTED) {
        return NULL;
    }

    Future* fu = new Future(xid_counter_.next(), attr);
    pending_fu_l_.lock();
    pending_fu_[fu->xid_] = fu;
    pending_fu_.size();
    pending_fu_l_.unlock();

    // check if the client gets closed in the meantime
    if (status_ != CONNECTED) {
        pending_fu_l_.lock();
        unordered_map<i64, Future*>::iterator it = pending_fu_.find(fu->xid_);
        if (it != pending_fu_.end()) {
            it->second->release();
            pending_fu_.erase(it);
        }
        pending_fu_l_.unlock();

        return NULL;
    }

    bmark_ = out_.set_bookmark(sizeof(i32)); // will fill packet size later

    *this << fu->xid_;
    *this << rpc_id;

    // one ref is already in pending_fu_
    return (Future *) fu->ref_copy();
}

void Client::end_request() {
    // set reply size in packet
    if (bmark_ != NULL) {
        i32 request_size = out_.get_and_reset_write_cnt();
        out_.write_bookmark(bmark_, &request_size);
        out_.update_read_barrier();
        delete bmark_;
        bmark_ = NULL;
    }

    // always enable write events since the code above gauranteed there
    // will be some data to send
    pollmgr_->update_mode(this, Pollable::READ | Pollable::WRITE);

    out_l_.unlock();
}

ClientPool::ClientPool(PollMgr* pollmgr /* =? */, int parallel_connections /* =? */)
        : parallel_connections_(parallel_connections) {

    if (pollmgr == NULL) {
        pollmgr_ = new PollMgr;
    } else {
        pollmgr_ = (PollMgr *) pollmgr->ref_copy();
    }
}

ClientPool::~ClientPool() {
    for (auto& it : cache_) {
        for (int i = 0; i < parallel_connections_; i++) {
            it.second[i]->close_and_release();
        }
        delete[] it.second;
    }
    pollmgr_->release();
}

Client* ClientPool::get_client(const string& addr) {
    Client* cl = NULL;
    l_.lock();
    map<string, Client**>::iterator it = cache_.find(addr);
    if (it != cache_.end()) {
        cl = it->second[rand_() % parallel_connections_];
    } else {
        Client** parallel_clients = new Client*[parallel_connections_];
        int i;
        bool ok = true;
        for (i = 0; i < parallel_connections_; i++) {
            parallel_clients[i] = new Client(this->pollmgr_);
            if (parallel_clients[i]->connect(addr.c_str()) != 0) {
                ok = false;
                break;
            }
        }
        if (ok) {
            cl = parallel_clients[rand_() % parallel_connections_];
            cache_.insert(std::map<std::string, rpc::Client**>::value_type(addr, parallel_clients));
        } else {
            // close connections
            while (i >= 0) {
                parallel_clients[i]->close_and_release();
                i--;
            }
            delete[] parallel_clients;
        }
    }
    l_.unlock();
    return cl;
}

}
<|endoftext|>


<commit_before>#include <vector>
#include <complex>
#include <fstream>
#include <ctime>
#include <thread>

#include "kernels_halide_gpu.h"
#include "mkHalideBuf.h"
#include "cfg.h"

#ifdef GCF32
#define GCF_FILE "gcf32.dat"
#else
#define GCF_FILE "gcf16.dat"
#endif

using namespace std;

typedef complex<double> complexd;

// Config
const double t2 = 0.2/2.0;
const int gcf_pad = 0;
const int over2 = over*over;
const int gcf_storage_size = over * gcf_size * (over * gcf_size + gcf_pad);
// const int grid_size = 8192;
const int grid_size = 2048;

const int grid_pitch = grid_size + grid_pad;
const int full_size = grid_pitch * grid_size;

const int num_of_vis = num_baselines * num_times;
const int num_of_doubles = num_of_vis * 5;

template <typename T>
void writeImgToDisk(const char * fname, T * out){
  // FILE * f = fopen(fname, "wb");
  FILE * f;
  // if (f == NULL) {
  if(fopen_s(&f, fname, "wb") != 0){
    printf("Can't open %s\n", fname);
    return;
  }
  printf("Writing %s ...\n", fname);
  for (int r = 0; r < grid_size; r++, out += grid_pitch)
    fwrite(out, sizeof(T), grid_size, f);
  fclose(f);
}

// Normalization is done inplace!
inline void normalizeCPU(
    complexd src[]
  , int grid_pitch
  , int grid_size
  )
{
  int siz = grid_size*grid_pitch;
  double norm = 1.0/double(siz);
  for (int i = 0; i < siz; i++) {
    src[i] *= norm;
  }
}

typedef vector<double> vecd;

// v should be preallocated with right size
int readFileToVector(vecd & v, const char * fname){
  ifstream is(fname, ios::binary);
  if (is.fail()) {
    printf("Can't open %s.\n", fname);
    return -1;
  }
  is.read(reinterpret_cast<char*>(v.data()), v.size() * sizeof(double));
  if (is.fail()) {
    printf("Can't read %s.\n", fname);
    return -2;
  }
  return 0;
}

#define __CK if (res != 0) {printf("Error: %d\n", res); return res; }

int main(/* int argc, char * argv[] */)
{
  int res;
  vecd vis(num_of_doubles);
  printf("Read visibilities!\n");
  res = readFileToVector(vis, "vis.dat"); __CK
  vecd gcf(gcf_storage_size * 2); // complex
  printf("Read GCF!\n");
  res = readFileToVector(gcf, GCF_FILE); __CK

  vecd uvg(full_size * 2, 0); // complex

  buffer_t
      vis_buffer = mkHalideBuf<double>(num_of_vis,5)
    , gcf_buffer = mkHalideBuf<double>(over2, gcf_size, gcf_size, 2)
    , uvg_buffer = mkHalideBuf<double>(grid_size, grid_size, 2)
    ;

  vis_buffer.host = tohost(vis.data());
  gcf_buffer.host = tohost(gcf.data());
  uvg_buffer.host = tohost(uvg.data());

  // Juct to make args different
  auto tfunc = [&](int n, double s) {
    return [&] {
      volatile clock_t ti = clock();
      printf("%d started!\n", n);
      if ( kern_scatter_gpu(t2/s, grid_size, &vis_buffer, &gcf_buffer, &uvg_buffer) != 0 ){
        printf("Broken!\n");
      }
      printf("%d finished in %f secs!\n", n, (double)(clock() - ti) / CLOCKS_PER_SEC);
    };
  };

  std::thread th1(tfunc(1, 1.0));
  std::thread th2(tfunc(2, 1.5));
  th1.join();
  th2.join();
  printf("Done. Normalizing ...\n");

  normalizeCPU(
      reinterpret_cast<complexd*>(uvg.data())
    , grid_pitch
    , grid_size
    );

  printf("Write!\n");
  writeImgToDisk("grid.dat", reinterpret_cast<complexd*>(uvg.data()));

  return 0;
}
<commit_msg>Remove garbage.<commit_after><|endoftext|>