<commit_before>/* Copyright (C) 2018, Project Pluto

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

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

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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __has_include
   #if __has_include(<cgi_func.h>)
       #include "cgi_func.h"
   #else
       #error   \
         'cgi_func.h' not found.  This project depends on the 'lunar'\
         library.  See www.github.com/Bill-Gray/lunar .\
         Clone that repository,  'make'  and 'make install' it.
   #endif
#else
   #include "cgi_func.h"
#endif
#include "watdefs.h"

int sat_id_main( const int argc, const char **argv);

int main( const int unused_argc, const char **unused_argv)
{
   const char *argv[20];
   const size_t max_buff_size = 40000;       /* room for 500 obs */
   char *buff = (char *)malloc( max_buff_size);
   char boundary[100], field[30];
   const char *temp_obs_filename = "sat_obs.txt";
   double search_radius = 4.;     /* look 2 degrees for matches */
   double motion_cutoff = 0.015;  /* up to .015'/s motion discrepancy OK */
   double low_speed_cutoff = 0.003;  /* anything slower than this is almost */
   const int argc = 6;               /* certainly not an artsat */
   FILE *lock_file = fopen( "lock.txt", "w");
   size_t bytes_written = 0;
   extern int verbose;
#ifndef _WIN32
   extern char **environ;

   avoid_runaway_process( 15);
#endif         /* _WIN32 */
   INTENTIONALLY_UNUSED_PARAMETER( unused_argc);
   INTENTIONALLY_UNUSED_PARAMETER( unused_argv);
   printf( "Content-type: text/html\n\n");
   printf( "
\n");
   if( !lock_file)
      {
      printf( "
 Server is busy.  Try again in a minute or two.
");
      printf( "
 Your orbit is very important to us!
");
      return( 0);
      }
   fprintf( lock_file, "We're in\n");
#ifndef _WIN32
   for( size_t i = 0; environ[i]; i++)
      fprintf( lock_file, "%s\n", environ[i]);
#endif
   if( !fgets( boundary, sizeof( boundary), stdin))
      {
      printf( "
 No info read from stdin
");
      printf( "
This isn't supposed to happen.
");
      return( 0);
      }
   while( get_multipart_form_data( boundary, field, buff, NULL, max_buff_size) >= 0)
      {
      if( !strcmp( field, "TextArea") || !strcmp( field, "upfile"))
         {
         if( strlen( buff) > 70)
            {
            FILE *ofile = fopen( temp_obs_filename,
                               (bytes_written ? "ab" : "wb"));

            bytes_written += fwrite( buff, 1, strlen( buff), ofile);
            fclose( ofile);
            }
         }
      if( !strcmp( field, "radius"))
         {
         const char *verbosity = strchr( buff, 'v');

         search_radius = atof( buff);
         if( verbosity)
            verbose = atoi( verbosity + 1) + 1;
         }
      if( !strcmp( field, "motion"))
         motion_cutoff = atof( buff);
      if( !strcmp( field, "low_speed"))
         low_speed_cutoff = atof( buff);
      }
   if( verbose)
      printf( "Searching to %f degrees;  %u bytes read from input\n",
                     search_radius, (unsigned)bytes_written);
   argv[0] = "sat_id";
   argv[1] = temp_obs_filename;
   argv[2] = "-t../../tles/tle_list.txt";
   sprintf( field, "-r%.2f", search_radius);
   argv[3] = field;
   sprintf( buff, "-y%f", motion_cutoff);
   argv[4] = buff;
   sprintf( boundary, "-z%f", low_speed_cutoff);
   argv[5] = boundary;
   argv[6] = NULL;
   sat_id_main( argc, argv);
   free( buff);
   printf( "
  ");
   return( 0);
}
<commit_msg>Revised on-line Sat_ID to use 'new' CGI input code.  This allows it to be called with GET,  POST URL-encoded,  and multipart-encoded methods.  See cgi_func.cpp in the 'lunar' repository for details.<commit_after>/* Copyright (C) 2018, Project Pluto

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

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

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

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __has_include
   #if __has_include(<cgi_func.h>)
       #include "cgi_func.h"
   #else
       #error   \
         'cgi_func.h' not found.  This project depends on the 'lunar'\
         library.  See www.github.com/Bill-Gray/lunar .\
         Clone that repository,  'make'  and 'make install' it.
   #endif
#else
   #include "cgi_func.h"
#endif
#include "watdefs.h"

int sat_id_main( const int argc, const char **argv);

int main( const int unused_argc, const char **unused_argv)
{
   const char *argv[20];
   const size_t max_buff_size = 40000;       /* room for 500 obs */
   char *buff = (char *)malloc( max_buff_size), *tptr;
   char field[30];
   const char *temp_obs_filename = "sat_obs.txt";
   double search_radius = 4.;     /* look 2 degrees for matches */
   double motion_cutoff = 0.015;  /* up to .015'/s motion discrepancy OK */
   double low_speed_cutoff = 0.003;  /* anything slower than this is almost */
   const int argc = 6;               /* certainly not an artsat */
   FILE *lock_file = fopen( "lock.txt", "w");
   size_t bytes_written = 0;
   int cgi_status;
   extern int verbose;
#ifndef _WIN32
   extern char **environ;

   avoid_runaway_process( 15);
#endif         /* _WIN32 */
   INTENTIONALLY_UNUSED_PARAMETER( unused_argc);
   INTENTIONALLY_UNUSED_PARAMETER( unused_argv);
   printf( "Content-type: text/html\n\n");
   printf( "
\n");
   if( !lock_file)
      {
      printf( "
 Server is busy.  Try again in a minute or two.
");
      printf( "
 Your orbit is very important to us!
");
      return( 0);
      }
   fprintf( lock_file, "We're in\n");
#ifndef _WIN32
   for( size_t i = 0; environ[i]; i++)
      fprintf( lock_file, "%s\n", environ[i]);
#endif
   cgi_status = initialize_cgi_reading( );
   fprintf( lock_file, "CGI status %d\n", cgi_status);
   if( cgi_status <= 0)
      {
      printf( "
  CGI data reading failed : error %d ", cgi_status);
      printf( "This isn't supposed to happen.
\n");
      return( 0);
      }
   while( !get_cgi_data( field, buff, NULL, max_buff_size))
      {
//    fprintf( lock_file, "Field '%s'\n", field);
      if( !strcmp( field, "TextArea") || !strcmp( field, "upfile"))
         {
         if( strlen( buff) > 70)
            {
            FILE *ofile = fopen( temp_obs_filename,
                               (bytes_written ? "ab" : "wb"));

            fprintf( lock_file, "File opened : %p\n", (void *)ofile);
            if( !ofile)
               {
               printf( "
 Couldn't open %s : %s
\n", temp_obs_filename, strerror( errno));
               fprintf( lock_file, "Couldn't open %s: %s\n", temp_obs_filename, strerror( errno));
               return( -1);
               }
            bytes_written += fwrite( buff, 1, strlen( buff), ofile);
            fclose( ofile);
            }
         }
      if( !strcmp( field, "radius"))
         {
         const char *verbosity = strchr( buff, 'v');

         search_radius = atof( buff);
         if( verbosity)
            verbose = atoi( verbosity + 1) + 1;
         }
      if( !strcmp( field, "motion"))
         motion_cutoff = atof( buff);
      if( !strcmp( field, "low_speed"))
         low_speed_cutoff = atof( buff);
      }
   fprintf( lock_file, "Fields read\n");
// printf( "
Fields read
\n");
   if( verbose)
      printf( "Searching to %f degrees;  %u bytes read from input\n",
                     search_radius, (unsigned)bytes_written);
   argv[0] = "sat_id";
   argv[1] = temp_obs_filename;
   argv[2] = "-t../../tles/tle_list.txt";
   sprintf( field, "-r%.2f", search_radius);
   argv[3] = field;
   sprintf( buff, "-y%f", motion_cutoff);
   argv[4] = buff;
   tptr = buff + strlen( buff) + 1;
   sprintf( tptr, "-z%f", low_speed_cutoff);
   argv[5] = tptr;
   argv[6] = NULL;
   sat_id_main( argc, argv);
   free( buff);
   printf( "
  ");
   return( 0);
}
<|endoftext|>


<commit_before>#ifndef MJOLNIR_GLOBAL_INTEARACTION_BASE
#define MJOLNIR_GLOBAL_INTEARACTION_BASE
#include <mjolnir/core/System.hpp>

namespace mjolnir
{

template<typename traitsT>
class GlobalInteractionBase
{
  public:

    typedef traitsT traits_type;
    typedef System<traits_type> system_type;
    typedef typename traits_type::real_type       real_type;
    typedef typename traits_type::coordinate_type coordinate_type;
    typedef typename traits_type::boundary_type   boundary_type;

  public:

    virtual ~GlobalInteractionBase() = default;

    virtual void initialize(const system_type& sys) = 0;
    virtual void update    (const system_type& sys) = 0;

    virtual void      calc_force (system_type&)             = 0;
    virtual real_type calc_energy(const system_type&) const = 0;

    virtual std::string name() const = 0;
};

} // mjolnir
#endif/* MJOLNIR_GLOBAL_INTEARACTION_BASE */
<commit_msg>fix: add missing include file, remove needless name<commit_after>#ifndef MJOLNIR_GLOBAL_INTEARACTION_BASE
#define MJOLNIR_GLOBAL_INTEARACTION_BASE
#include <mjolnir/core/System.hpp>
#include <string>

namespace mjolnir
{

template<typename traitsT>
class GlobalInteractionBase
{
  public:

    typedef traitsT traits_type;
    typedef System<traits_type> system_type;
    typedef typename traits_type::real_type       real_type;
    typedef typename traits_type::coordinate_type coordinate_type;
    typedef typename traits_type::boundary_type   boundary_type;

  public:

    virtual ~GlobalInteractionBase() = default;

    virtual void initialize(const system_type&) = 0;
    virtual void update    (const system_type&) = 0;

    virtual void      calc_force (system_type&)             = 0;
    virtual real_type calc_energy(const system_type&) const = 0;

    virtual std::string name() const = 0;
};

} // mjolnir
#endif/* MJOLNIR_GLOBAL_INTEARACTION_BASE */
<|endoftext|>


<commit_before>#include "cxxabi.h"

#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>

std::string demangle(char const* name) {
	using namespace abi;
	using namespace std;
	int status;
	unique_ptr<char, void (*)(void*)> result(__cxa_demangle(name,
	                                                        nullptr,
	                                                        nullptr,
	                                                        &status),
	                                         free);
	switch (status) {
	case 0: return result.get();
	case -1: throw bad_alloc();
	case -2: throw logic_error("not a valid name under the C++ ABI mangling rules");
	case -3: throw invalid_argument("one of the arguments is invalid");
	}
	throw logic_error("unexpected status");
}

int main(int argc, char* argv[]) {
	using namespace std;
	if (argc != 2) {
		std::cerr << argv[0] << " " << "NAME" << std::endl;
		return 1;
	}
	cout << demangle(argv[1]) << endl;
	return 0;
}
<commit_msg>cleanup<commit_after>#include "cxxabi.h"

#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>

struct invalid_name: std::invalid_argument {
	using std::invalid_argument::invalid_argument;
};

std::string demangle(char const* name) {
	using namespace abi;
	using namespace std;
	int status;
	unique_ptr<char, void (*)(void*)> result(__cxa_demangle(name,
	                                                        nullptr,
	                                                        nullptr,
	                                                        &status),
	                                         free);
	switch (status) {
	case 0: return result.get();
	case -1: throw bad_alloc();
	case -2: throw invalid_name("not a valid name under the C++ ABI mangling rules");
	case -3: throw invalid_argument("one of the arguments is invalid");
	default: throw logic_error("unexpected status");
	}
}

int main(int argc, char* argv[]) {
	using namespace std;
	if (argc != 2) {
		std::cerr << argv[0] << " " << "NAME" << std::endl;
		return 1;
	}
	try {
		cout << demangle(argv[1]) << endl;
	} catch (invalid_name const& e) {
		cerr << e.what() << endl;
		return 1;
	}
	return 0;
}
<|endoftext|>


<commit_before>#include "Analysis.hh"
#include "G4UnitsTable.hh"
#include "globals.hh"

#include "G4RunManager.hh"
#include "G4Material.hh"

#include "G4HCofThisEvent.hh"
#include "G4Event.hh"
#include "G4ThreeVector.hh"

#include "HistoManager.hh"
#include "PhotonDetHit.cc"
Analysis* Analysis::singleton = 0;
/**
 * Analysis
 *
 * Creates an Analysis object
 */
Analysis::Analysis(){
}
/**
 * Initilize the analysis manager
 *
 * Creates a new HistoManager
 */
void Analysis::Initilize(){
    fHistoManager = new HistoManager();
}
/**
 * Cleaning up the analysis manager
 *
 * Deleting the HistoManager
 */
void Analysis::CleanUp(){
    delete fHistoManager;
}
Analysis::~Analysis(){
}

/**
 * PrepareNewRun
 *
 * @brief - called before each run.
 * There is no need to update the geometry because the geometry
 * is fixed during a run.
 */
void Analysis::PrepareNewRun(const G4Run* ){
    G4AnalysisManager* analysisManager = G4AnalysisManager::Instance();
    if ( analysisManager->IsActive() ) {
        analysisManager->OpenFile();
    }
}

/**
 * PrepareNewEvent
 *
 * @brief - Called before each event
 * Sets the number of optical photons
 */
void Analysis::PrepareNewEvent(const G4Event* ){
    nOPAbsEvent = 0;
    nOPPMTEvent = 0;
}

/**
 * EndOfEvent
 *
 * @param G4Event* event
 */
void Analysis::EndOfEvent(const G4Event* event){
    G4VHitsCollection *hc;
    PhotonDetHit *hit;

    G4AnalysisManager* analysisManager = G4AnalysisManager::Instance();
    // Iterating through the hit collection to accumulate the energy deposition
    G4int numHitColl = event->GetHCofThisEvent()->GetNumberOfCollections();
    for(G4int hitItter = 0; hitItter < numHitColl; hitItter++){
        // Itterating through the hit collection
        hc = event->GetHCofThisEvent()->GetHC(hitItter);
        for(unsigned int i = 0; i < hc->GetSize(); i++){
            hit = (PhotonDetHit*) hc->GetHit(i);
            analysisManager->FillH1(1, hit->GetArrivalTime());
        }
    }

    // The Number of Optical Photons Detected on the PMT
    if(hc != NULL)
        nOPPMTEvent += hc->GetSize();
    else
        G4cout<<"WARNING: Absorber::EndOfEvent - pmtHC is NULL"<<G4endl;

    // Filling the histograms
    analysisManager->FillH1(2,nOPAbsEvent);
    analysisManager->FillH1(3,nOPPMTEvent);

}

/**
 * EndOfRun
 *
 * Called at the end of a run, which summerizes the run
 */
void Analysis::EndOfRun(const G4Run* ){
    G4AnalysisManager* analysisManager = G4AnalysisManager::Instance();
    // Print some output
    G4cout
    << "\n\tAverage Number of Optical Photons: "
    << analysisManager->GetH1(2)->mean()
    << " +/- " << analysisManager->GetH1(2)->rms()
    << G4endl;

    //save histograms
    if ( analysisManager->IsActive() ) {
        analysisManager->Write();
        analysisManager->CloseFile();
    }
}
/**
 * Sets the number of optical photons generated
 */
void Analysis::SetNumOpticalPhotonsGenerated(G4int numPhotons){
    nOPAbsEvent = numPhotons;
}
<commit_msg>fixed compile error<commit_after>#include "Analysis.hh"
#include "G4UnitsTable.hh"
#include "globals.hh"

#include "G4RunManager.hh"
#include "G4Material.hh"

#include "G4HCofThisEvent.hh"
#include "G4Event.hh"
#include "G4ThreeVector.hh"

#include "HistoManager.hh"
#include "PhotonDetHit.hh"
Analysis* Analysis::singleton = 0;
/**
 * Analysis
 *
 * Creates an Analysis object
 */
Analysis::Analysis(){
}
/**
 * Initilize the analysis manager
 *
 * Creates a new HistoManager
 */
void Analysis::Initilize(){
    fHistoManager = new HistoManager();
}
/**
 * Cleaning up the analysis manager
 *
 * Deleting the HistoManager
 */
void Analysis::CleanUp(){
    delete fHistoManager;
}
Analysis::~Analysis(){
}

/**
 * PrepareNewRun
 *
 * @brief - called before each run.
 * There is no need to update the geometry because the geometry
 * is fixed during a run.
 */
void Analysis::PrepareNewRun(const G4Run* ){
    G4AnalysisManager* analysisManager = G4AnalysisManager::Instance();
    if ( analysisManager->IsActive() ) {
        analysisManager->OpenFile();
    }
}

/**
 * PrepareNewEvent
 *
 * @brief - Called before each event
 * Sets the number of optical photons
 */
void Analysis::PrepareNewEvent(const G4Event* ){
    nOPAbsEvent = 0;
    nOPPMTEvent = 0;
}

/**
 * EndOfEvent
 *
 * @param G4Event* event
 */
void Analysis::EndOfEvent(const G4Event* event){
    G4VHitsCollection *hc;
    PhotonDetHit *hit;

    G4AnalysisManager* analysisManager = G4AnalysisManager::Instance();
    // Iterating through the hit collection to accumulate the energy deposition
    G4int numHitColl = event->GetHCofThisEvent()->GetNumberOfCollections();
    for(G4int hitItter = 0; hitItter < numHitColl; hitItter++){
        // Itterating through the hit collection
        hc = event->GetHCofThisEvent()->GetHC(hitItter);
        for(unsigned int i = 0; i < hc->GetSize(); i++){
            hit = (PhotonDetHit*) hc->GetHit(i);
            analysisManager->FillH1(1, hit->GetArrivalTime());
        }
    }

    // The Number of Optical Photons Detected on the PMT
    if(hc != NULL)
        nOPPMTEvent += hc->GetSize();
    else
        G4cout<<"WARNING: Absorber::EndOfEvent - pmtHC is NULL"<<G4endl;

    // Filling the histograms
    analysisManager->FillH1(2,nOPAbsEvent);
    analysisManager->FillH1(3,nOPPMTEvent);

}

/**
 * EndOfRun
 *
 * Called at the end of a run, which summerizes the run
 */
void Analysis::EndOfRun(const G4Run* ){
    G4AnalysisManager* analysisManager = G4AnalysisManager::Instance();
    // Print some output
    G4cout
    << "\n\tAverage Number of Optical Photons: "
    << analysisManager->GetH1(2)->mean()
    << " +/- " << analysisManager->GetH1(2)->rms()
    << G4endl;

    //save histograms
    if ( analysisManager->IsActive() ) {
        analysisManager->Write();
        analysisManager->CloseFile();
    }
}
/**
 * Sets the number of optical photons generated
 */
void Analysis::SetNumOpticalPhotonsGenerated(G4int numPhotons){
    nOPAbsEvent = numPhotons;
}
<|endoftext|>


<commit_before>// C/C++
#include <stdio.h>
#include <string.h>
#include <map>

// E
#include <e/endian.h>
#include <e/unpacker.h>
#include <e/intrusive_ptr.h>

// HyperDex
#include <hyperdex/client.hpp>

// WTF
#include "client/file.h"

using namespace std;

hyperdex::Client* h;
const char* WTF_SPACE = "wtf";
bool verbose = true;
const struct hyperdex_client_attribute* attrs;
size_t attrs_sz;
hyperdex_client_returncode status;
int64_t retval;

void
print_return()
{
    if (verbose) printf("first retval %ld status %d:", retval, status);
    if (verbose) cout << status << endl;
    retval = h->loop(-1, &status);
    if (verbose) printf("final retval %ld status %d:", retval, status);
    if (verbose) cout << status << endl;
}

void
read()
{
    if (status == HYPERDEX_CLIENT_SEARCHDONE) return;

    // Reading
    if (verbose) cout << "[" << attrs_sz << "] attributes" << endl;
    if (attrs == NULL)
    {
        cout << "attrs is NULL" << endl;
    }
    else
    {
        for (size_t i = 0; i < attrs_sz; ++i)
        {
            if (verbose) cout << "\t" << i << ". [" << attrs[i].attr << "]:\t";
            if (strcmp(attrs[i].attr, "path") == 0)
            {
                cout << "[" << string(attrs[i].value, attrs[i].value_sz) << "]" << endl;
            }
            else if (strcmp(attrs[i].attr, "blockmap") == 0)
            {
                e::unpacker up(attrs[i].value, attrs[i].value_sz);
                if (attrs[i].value_sz == 0)
                {
                    cout << endl;
                }
                else
                {
                    cout << "[" << up.as_slice().hex() << "]" << endl;

                    cout << "\t\tblocks: " << endl;
                    e::intrusive_ptr<wtf::file> f = new wtf::file("", 0);
                    up = up >> f;
                    //wtf::file::block_map::const_iterator it;
                    //for (it = f.m_block_map.begin(); it != f.m_block_map.end(); ++it)
                    //{
                    //    lhs << *it->second << std::endl;
                    //}
                    cout << *f << endl;
                    //map<uint64_t, e::intrusive_ptr<wtf::block>> block_map;
                    //file::block_map::const_iterator it;
                    //for (it = rhs.m_block_map.begin(); it != rhs.m_block_map.end(); ++it)
                    //{
                    //    cout << *it->second << endl;
                    //}

                }
            }
            else if (strcmp(attrs[i].attr, "directory") == 0)
            {
                uint64_t is_dir;

                e::unpacker up(attrs[i].value, attrs[i].value_sz);
                up = up >> is_dir;
                e::unpack64be((uint8_t*)&is_dir, &is_dir);
                cout << "[" << is_dir << "]" << endl;
            }
            else if (strcmp(attrs[i].attr, "mode") == 0)
            {
                uint64_t mode;

                e::unpacker up(attrs[i].value, attrs[i].value_sz);
                up = up >> mode;
                e::unpack64be((uint8_t*)&mode, &mode);
                cout << "[" << mode << "]" << endl;
            }
            else
            {
                cout << "<unexpected attribute>" << endl;
            }
        }
    }

    if (verbose) cout << endl;
}

void
put(const char* filename)
{
    if (verbose) cout << ">>>>putting [" << filename << "]" << endl;

    retval = h->put_if_not_exist(WTF_SPACE, filename, strlen(filename), NULL, 0, &status);
    print_return();
    if (verbose) cout << endl;
}

void
del(const char* filename)
{
    if (verbose) cout << ">>>>deleting [" << filename << "]" << endl;

    retval = h->del(WTF_SPACE, filename, strlen(filename), &status);
    print_return();
    if (verbose) cout << endl;
}

void
search(const char* attr, const char* value, hyperpredicate predicate)
{
    if (verbose) cout << ">>>>searching [" << attr << "] for [" << value << "] with [" << predicate << "]" << endl;
    struct hyperdex_client_attribute_check check;
    check.attr = attr;
    check.value = value;
    check.value_sz = strlen(check.value);
    check.datatype = HYPERDATATYPE_STRING;
    check.predicate = predicate;

    status = (hyperdex_client_returncode)NULL;
    // TODO max_int64 results
    retval = h->sorted_search(WTF_SPACE, &check, 1, "path", 100, false, &status, &attrs, &attrs_sz);

    int counter = 0;
    while (status != HYPERDEX_CLIENT_SEARCHDONE && status != HYPERDEX_CLIENT_NONEPENDING)
    {
        if (verbose) cout << ++counter << endl;
        print_return();
        read();
    }
    if (verbose) cout << endl;
}

int
main(int argc, const char* argv[])
{
    //hyperdex::connect_opts conn;
    //h = new hyperdex::Client(conn.host(), conn.port());
    h = new hyperdex::Client("127.0.0.1", 1982);

    if (argc > 1)
    {
        if (strcmp(argv[1], "touch") == 0)
        {
            if (argc > 3) verbose = true;
            if (argc > 2)
            {
                cout << "touch " << argv[2] << endl;
                put(argv[2]);
            }
            else
            {
                cout << "usage: touch <filename>" << endl;
            }
        }
        else if (strcmp(argv[1], "ls") == 0)
        {
            if (argc > 3) verbose = true;
            string query("^");
            if (argc > 2)
            {
                query += string(argv[2]);
            }

            cout << "ls " << query << endl;
            search("path", query.c_str(), HYPERPREDICATE_REGEX);
        }
        else if (strcmp(argv[1], "rm") == 0)
        {
            if (argc > 3) verbose = true;
            if (argc > 2)
            {
                cout << "rm " << argv[2] << endl;
                del(argv[2]);
            }
            else
            {
                cout << "usage: rm <filename>" << endl;
            }
        }
        else if (strcmp(argv[1], "rmall") == 0)
        {
            verbose = true;

            struct hyperdex_client_attribute_check check;
            check.attr = "path";
            check.value = "*";
            check.value_sz = 0;
            check.datatype = HYPERDATATYPE_STRING;
            check.predicate = HYPERPREDICATE_REGEX;

            status = (hyperdex_client_returncode)NULL;
            retval = h->group_del(WTF_SPACE, &check, 1, &status);
            print_return();
        }
        else
        {
            cout << argv[1] << " is not supported" << endl;
        }
    }
    else
    {
        cout << "Commands: touch, ls, rm, rmall" << endl;
        cout << "Set up: echo 'space wtf key path attributes string blockmap, int directory, int mode' | hyperdex add-space -h 127.0.0.1 -p 1982" << endl;
    }

    return EXIT_SUCCESS;
}
<commit_msg>more polished format for metadata dump<commit_after>// C/C++
#include <stdio.h>
#include <string.h>
#include <map>

// E
#include <e/endian.h>
#include <e/unpacker.h>
#include <e/intrusive_ptr.h>

// HyperDex
#include <hyperdex/client.hpp>

// WTF
#include "client/file.h"

using namespace std;

hyperdex::Client* h;
const char* WTF_SPACE = "wtf";
bool verbose = true;
const struct hyperdex_client_attribute* attrs;
size_t attrs_sz;
hyperdex_client_returncode status;
int64_t retval;

void
print_return()
{
    if (verbose) printf("first retval %ld status %d:", retval, status);
    if (verbose) cout << status << endl;
    retval = h->loop(-1, &status);
    if (verbose) printf("final retval %ld status %d:", retval, status);
    if (verbose) cout << status << endl;
}

void
read()
{
    if (status == HYPERDEX_CLIENT_SEARCHDONE) return;

    // Reading
    if (verbose) cout << "[" << attrs_sz << "] attributes" << endl;
    if (attrs == NULL)
    {
        cout << "attrs is NULL" << endl;
    }
    else
    {
        e::intrusive_ptr<wtf::file> f = new wtf::file("", 0);
        for (size_t i = 0; i < attrs_sz; ++i)
        {
            if (verbose) cout << i << ". [" << attrs[i].attr << "]:";
            if (strcmp(attrs[i].attr, "path") == 0)
            {
                string path(attrs[i].value, attrs[i].value_sz);
                cout << "[" << path << "]" << endl;
                f->path(path.c_str());
            }
            else if (strcmp(attrs[i].attr, "blockmap") == 0)
            {
                e::unpacker up(attrs[i].value, attrs[i].value_sz);
                if (attrs[i].value_sz == 0)
                {
                    cout << endl;
                }
                else
                {
                    cout << "[" << up.as_slice().hex() << "]" << endl;
                    up = up >> f;
                }
            }
            else if (strcmp(attrs[i].attr, "directory") == 0)
            {
                uint64_t is_dir;

                e::unpacker up(attrs[i].value, attrs[i].value_sz);
                up = up >> is_dir;
                e::unpack64be((uint8_t*)&is_dir, &is_dir);
                cout << "[" << is_dir << "]" << endl;
                f->is_directory = is_dir == 0 ? false : true;
            }
            else if (strcmp(attrs[i].attr, "mode") == 0)
            {
                uint64_t mode;

                e::unpacker up(attrs[i].value, attrs[i].value_sz);
                up = up >> mode;
                e::unpack64be((uint8_t*)&mode, &mode);
                cout << "[" << mode << "]" << endl;
                f->mode = mode;
            }
            else
            {
                cout << "<unexpected attribute>" << endl;
            }
        }
        cout << *f << endl;
    }
}

void
put(const char* filename)
{
    if (verbose) cout << ">>>>putting [" << filename << "]" << endl;

    retval = h->put_if_not_exist(WTF_SPACE, filename, strlen(filename), NULL, 0, &status);
    print_return();
    if (verbose) cout << endl;
}

void
del(const char* filename)
{
    if (verbose) cout << ">>>>deleting [" << filename << "]" << endl;

    retval = h->del(WTF_SPACE, filename, strlen(filename), &status);
    print_return();
    if (verbose) cout << endl;
}

void
search(const char* attr, const char* value, hyperpredicate predicate)
{
    if (verbose) cout << ">>>>searching [" << attr << "] for [" << value << "] with [" << predicate << "]" << endl;
    struct hyperdex_client_attribute_check check;
    check.attr = attr;
    check.value = value;
    check.value_sz = strlen(check.value);
    check.datatype = HYPERDATATYPE_STRING;
    check.predicate = predicate;

    status = (hyperdex_client_returncode)NULL;
    // TODO max_int64 results
    retval = h->sorted_search(WTF_SPACE, &check, 1, "path", 100, false, &status, &attrs, &attrs_sz);

    int counter = 0;
    while (status != HYPERDEX_CLIENT_SEARCHDONE && status != HYPERDEX_CLIENT_NONEPENDING)
    {
        if (verbose) cout << "(" << ++counter << ")" << endl;
        print_return();
        read();
    }
    if (verbose) cout << endl;
}

int
main(int argc, const char* argv[])
{
    //hyperdex::connect_opts conn;
    //h = new hyperdex::Client(conn.host(), conn.port());
    h = new hyperdex::Client("127.0.0.1", 1982);

    if (argc > 1)
    {
        if (strcmp(argv[1], "touch") == 0)
        {
            if (argc > 3) verbose = true;
            if (argc > 2)
            {
                cout << "touch " << argv[2] << endl;
                put(argv[2]);
            }
            else
            {
                cout << "usage: touch <filename>" << endl;
            }
        }
        else if (strcmp(argv[1], "ls") == 0)
        {
            if (argc > 3) verbose = true;
            string query("^");
            if (argc > 2)
            {
                query += string(argv[2]);
            }

            cout << "ls " << query << endl;
            search("path", query.c_str(), HYPERPREDICATE_REGEX);
        }
        else if (strcmp(argv[1], "rm") == 0)
        {
            if (argc > 3) verbose = true;
            if (argc > 2)
            {
                cout << "rm " << argv[2] << endl;
                del(argv[2]);
            }
            else
            {
                cout << "usage: rm <filename>" << endl;
            }
        }
        else if (strcmp(argv[1], "rmall") == 0)
        {
            verbose = true;

            struct hyperdex_client_attribute_check check;
            check.attr = "path";
            check.value = "*";
            check.value_sz = 0;
            check.datatype = HYPERDATATYPE_STRING;
            check.predicate = HYPERPREDICATE_REGEX;

            status = (hyperdex_client_returncode)NULL;
            retval = h->group_del(WTF_SPACE, &check, 1, &status);
            print_return();
        }
        else
        {
            cout << argv[1] << " is not supported" << endl;
        }
    }
    else
    {
        cout << "Commands: touch, ls, rm, rmall" << endl;
        cout << "Set up: echo 'space wtf key path attributes string blockmap, int directory, int mode' | hyperdex add-space -h 127.0.0.1 -p 1982" << endl;
    }

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>//===- lib/Support/ErrorHandling.cpp - Callbacks for errors ---------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines an API used to indicate fatal error conditions.  Non-fatal
// errors (most of them) should be handled through LLVMContext.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/Twine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/Threading.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Config/config.h"
#include <cassert>
#include <cstdlib>

#if defined(HAVE_UNISTD_H)
# include <unistd.h>
#endif
#if defined(_MSC_VER)
# include <io.h>
# include <fcntl.h>
#endif

using namespace llvm;
using namespace std;

static fatal_error_handler_t ErrorHandler = 0;
static void *ErrorHandlerUserData = 0;

void llvm::install_fatal_error_handler(fatal_error_handler_t handler,
                                       void *user_data) {
  assert(!llvm_is_multithreaded() &&
         "Cannot register error handlers after starting multithreaded mode!\n");
  assert(!ErrorHandler && "Error handler already registered!\n");
  ErrorHandler = handler;
  ErrorHandlerUserData = user_data;
}

void llvm::remove_fatal_error_handler() {
  ErrorHandler = 0;
}

void llvm::report_fatal_error(const char *Reason) {
  report_fatal_error(Twine(Reason));
}

void llvm::report_fatal_error(const std::string &Reason) {
  report_fatal_error(Twine(Reason));
}

void llvm::report_fatal_error(StringRef Reason) {
  report_fatal_error(Twine(Reason));
}

void llvm::report_fatal_error(const Twine &Reason) {
  if (ErrorHandler) {
    ErrorHandler(ErrorHandlerUserData, Reason.str());
  } else {
    // Blast the result out to stderr.  We don't try hard to make sure this
    // succeeds (e.g. handling EINTR) and we can't use errs() here because
    // raw ostreams can call report_fatal_error.
    SmallVector<char, 64> Buffer;
    raw_svector_ostream OS(Buffer);
    OS << "LLVM ERROR: " << Reason << "\n";
    StringRef MessageStr = OS.str();
    ssize_t written = ::write(2, MessageStr.data(), MessageStr.size());
    (void)written; // If something went wrong, we deliberately just give up.
  }

  // If we reached here, we are failing ungracefully. Run the interrupt handlers
  // to make sure any special cleanups get done, in particular that we remove
  // files registered with RemoveFileOnSignal.
  sys::RunInterruptHandlers();

  exit(1);
}

void llvm::llvm_unreachable_internal(const char *msg, const char *file,
                                     unsigned line) {
  // This code intentionally doesn't call the ErrorHandler callback, because
  // llvm_unreachable is intended to be used to indicate "impossible"
  // situations, and not legitimate runtime errors.
  if (msg)
    dbgs() << msg << "\n";
  dbgs() << "UNREACHABLE executed";
  if (file)
    dbgs() << " at " << file << ":" << line;
  dbgs() << "!\n";
  abort();
}
<commit_msg>Like the coding standards say, do not use "using namespace std".<commit_after>//===- lib/Support/ErrorHandling.cpp - Callbacks for errors ---------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines an API used to indicate fatal error conditions.  Non-fatal
// errors (most of them) should be handled through LLVMContext.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/Twine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/Threading.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Config/config.h"
#include <cassert>
#include <cstdlib>

#if defined(HAVE_UNISTD_H)
# include <unistd.h>
#endif
#if defined(_MSC_VER)
# include <io.h>
# include <fcntl.h>
#endif

using namespace llvm;

static fatal_error_handler_t ErrorHandler = 0;
static void *ErrorHandlerUserData = 0;

void llvm::install_fatal_error_handler(fatal_error_handler_t handler,
                                       void *user_data) {
  assert(!llvm_is_multithreaded() &&
         "Cannot register error handlers after starting multithreaded mode!\n");
  assert(!ErrorHandler && "Error handler already registered!\n");
  ErrorHandler = handler;
  ErrorHandlerUserData = user_data;
}

void llvm::remove_fatal_error_handler() {
  ErrorHandler = 0;
}

void llvm::report_fatal_error(const char *Reason) {
  report_fatal_error(Twine(Reason));
}

void llvm::report_fatal_error(const std::string &Reason) {
  report_fatal_error(Twine(Reason));
}

void llvm::report_fatal_error(StringRef Reason) {
  report_fatal_error(Twine(Reason));
}

void llvm::report_fatal_error(const Twine &Reason) {
  if (ErrorHandler) {
    ErrorHandler(ErrorHandlerUserData, Reason.str());
  } else {
    // Blast the result out to stderr.  We don't try hard to make sure this
    // succeeds (e.g. handling EINTR) and we can't use errs() here because
    // raw ostreams can call report_fatal_error.
    SmallVector<char, 64> Buffer;
    raw_svector_ostream OS(Buffer);
    OS << "LLVM ERROR: " << Reason << "\n";
    StringRef MessageStr = OS.str();
    ssize_t written = ::write(2, MessageStr.data(), MessageStr.size());
    (void)written; // If something went wrong, we deliberately just give up.
  }

  // If we reached here, we are failing ungracefully. Run the interrupt handlers
  // to make sure any special cleanups get done, in particular that we remove
  // files registered with RemoveFileOnSignal.
  sys::RunInterruptHandlers();

  exit(1);
}

void llvm::llvm_unreachable_internal(const char *msg, const char *file,
                                     unsigned line) {
  // This code intentionally doesn't call the ErrorHandler callback, because
  // llvm_unreachable is intended to be used to indicate "impossible"
  // situations, and not legitimate runtime errors.
  if (msg)
    dbgs() << msg << "\n";
  dbgs() << "UNREACHABLE executed";
  if (file)
    dbgs() << " at " << file << ":" << line;
  dbgs() << "!\n";
  abort();
}
<|endoftext|>


<commit_before>/*
 * fsm.hpp
 *
 *  Created on: 25 мая 2016 г.
 *      Author: sergey.fedorov
 */

#ifndef AFSM_FSM_HPP_
#define AFSM_FSM_HPP_

#include <afsm/detail/base_states.hpp>
#include <afsm/detail/observer.hpp>
#include <deque>

namespace afsm {

//----------------------------------------------------------------------------
//  State
//----------------------------------------------------------------------------
template < typename T, typename FSM >
class state : public detail::state_base< T > {
public:
    using enclosing_fsm_type    = FSM;
public:
    state(enclosing_fsm_type& fsm)
        : state::state_type{}, fsm_{&fsm}
    {}
    state(state const& rhs) = default;
    state(state&& rhs) = default;
    state(enclosing_fsm_type& fsm, state const& rhs)
        : state::state_type{static_cast<typename state::state_type const&>(rhs)}, fsm_{&fsm}
    {}
    state(enclosing_fsm_type& fsm, state&& rhs)
        : state::state_type{static_cast<typename state::state_type&&>(rhs)}, fsm_{&fsm}
    {}

    state&
    operator = (state const& rhs)
    {
        state{rhs}.swap(*this);
        return *this;
    }
    state&
    operator = (state&& rhs)
    {
        swap(rhs);
        return *this;
    }

    void
    swap(state& rhs) noexcept
    {
        static_cast<typename state::state_type&>(*this).swap(rhs);
    }

    template < typename Event >
    actions::event_process_result
    process_event( Event&& evt )
    {
        return process_event_impl(::std::forward<Event>(evt),
                detail::event_process_selector<
                    Event,
                    typename state::internal_events,
                    typename state::deferred_events>{} );
    }

    enclosing_fsm_type&
    enclosing_fsm()
    { return *fsm_; }
    enclosing_fsm_type const&
    enclosing_fsm() const
    { return *fsm_; }
    void
    enclosing_fsm(enclosing_fsm_type& fsm)
    { fsm_ = &fsm; }

    template < typename Event >
    void
    state_enter(Event&&) {}
    template < typename Event >
    void
    state_exit(Event&&) {}
private:
    template < typename Event >
    actions::event_process_result
    process_event_impl(Event&& evt,
        detail::process_type<actions::event_process_result::process> const&)
    {
        return actions::handle_in_state_event(::std::forward<Event>(evt), *fsm_, *this);
    }
    template < typename Event >
    constexpr actions::event_process_result
    process_event_impl(Event&&,
        detail::process_type<actions::event_process_result::defer> const&)
    {
        return actions::event_process_result::defer;
    }
    template < typename Event >
    constexpr actions::event_process_result
    process_event_impl(Event&&,
        detail::process_type<actions::event_process_result::refuse> const&)
    {
        return actions::event_process_result::refuse;
    }
private:
    enclosing_fsm_type*    fsm_;
};

//----------------------------------------------------------------------------
//  Inner state machine
//----------------------------------------------------------------------------
template < typename T, typename FSM >
class inner_state_machine : public detail::state_machine_base< T, none, inner_state_machine<T, FSM> > {
public:
    using enclosing_fsm_type    = FSM;
    using this_type = inner_state_machine<T, FSM>;
    using base_machine_type     = detail::state_machine_base< T, none, this_type >;
public:
    inner_state_machine(enclosing_fsm_type& fsm)
        : base_machine_type{this}, fsm_{&fsm} {}
    inner_state_machine(inner_state_machine const& rhs)
        : base_machine_type{this, rhs}, fsm_{rhs.fsm_} {}
    inner_state_machine(inner_state_machine&& rhs)
        : base_machine_type{this, ::std::move(rhs)},
          fsm_{rhs.fsm_}
    {
    }

    inner_state_machine(enclosing_fsm_type& fsm, inner_state_machine const& rhs)
        : base_machine_type{static_cast<base_machine_type const&>(rhs)}, fsm_{&fsm} {}
    inner_state_machine(enclosing_fsm_type& fsm, inner_state_machine&& rhs)
        : base_machine_type{static_cast<base_machine_type&&>(rhs)}, fsm_{&fsm} {}

    void
    swap(inner_state_machine& rhs) noexcept
    {
        using ::std::swap;
        static_cast<base_machine_type&>(*this).swap(rhs);
        swap(fsm_, rhs.fsm_);
    }
    inner_state_machine&
    operator = (inner_state_machine const& rhs)
    {
        inner_state_machine tmp{rhs};
        swap(tmp);
        return *this;
    }
    inner_state_machine&
    operator = (inner_state_machine&& rhs)
    {
        swap(rhs);
        return *this;
    }

    template < typename Event >
    actions::event_process_result
    process_event( Event&& event )
    {
        return process_event_impl(*fsm_, ::std::forward<Event>(event),
                detail::event_process_selector<
                    Event,
                    typename inner_state_machine::handled_events,
                    typename inner_state_machine::deferred_events>{} );
    }

    enclosing_fsm_type&
    enclosing_fsm()
    { return *fsm_; }
    enclosing_fsm_type const&
    enclosing_fsm() const
    { return *fsm_; }
    void
    enclosing_fsm(enclosing_fsm_type& fsm)
    { fsm_ = &fsm; }
private:
    using base_machine_type::process_event_impl;
private:
    enclosing_fsm_type*    fsm_;
};

//----------------------------------------------------------------------------
//  State machine
//----------------------------------------------------------------------------
template < typename T, typename Mutex, typename Observer,
        template<typename> class ObserverWrapper >
class state_machine :
        public detail::state_machine_base< T, Mutex,
            state_machine<T, Mutex, Observer> >,
        public ObserverWrapper<Observer> {
public:
    static_assert( ::psst::meta::is_empty< typename T::deferred_events >::value,
            "Outer state machine cannot defer events" );
    using this_type         = state_machine<T, Mutex, Observer>;
    using base_machine_type = detail::state_machine_base< T, Mutex, this_type >;
    using mutex_type        = Mutex;
    using lock_guard        = typename detail::lock_guard_type<mutex_type>::type;
    using observer_wrapper  = ObserverWrapper<Observer>;
public:
    state_machine()
        : base_machine_type{this},
          stack_size_{0},
          mutex_{},
          queued_events_{},
          deferred_mutex_{},
          deferred_events_{}
      {}
    template<typename ... Args>
    explicit
    state_machine(Args&& ... args)
        : base_machine_type(this, ::std::forward<Args>(args)...),
          stack_size_{0},
          mutex_{},
          queued_events_{},
          deferred_mutex_{},
          deferred_events_{}
    {}

    template < typename Event >
    actions::event_process_result
    process_event( Event&& event )
    {
        if (!stack_size_++) {
            auto res = process_event_dispatch(::std::forward<Event>(event));
            // Process enqueued events
            process_event_queue();
            --stack_size_;
            return res;
        } else {
            --stack_size_;
            // Enqueue event
            enqueue_event(::std::forward<Event>(event));
            return actions::event_process_result::defer;
        }
    }
private:
    template < typename Event >
    actions::event_process_result
    process_event_dispatch( Event&& event )
    {
        return process_event_impl(::std::forward<Event>(event),
                    detail::event_process_selector<
                        Event,
                        typename state_machine::handled_events>{} );
    }

    template < typename Event >
    actions::event_process_result
    process_event_impl(Event&& event,
        detail::process_type<actions::event_process_result::process> const& sel)
    {
        using actions::event_process_result;
        observer_wrapper::start_process_event(*this, ::std::forward<Event>(event));
        auto res = base_machine_type::process_event_impl(*this, ::std::forward<Event>(event), sel );
        switch (res) {
            case event_process_result::process:
                observer_wrapper::state_changed(*this);
                // Changed state. Process deferred events
                process_deferred_queue();
                break;
            case event_process_result::process_in_state:
                observer_wrapper::processed_in_state(*this, ::std::forward<Event>(event));
                break;
            case event_process_result::defer:
                // Add event to deferred queue
                defer_event(::std::forward<Event>(event));
                break;
            case event_process_result::refuse:
                // The event cannot be processed in current state
                observer_wrapper::reject_event(*this, ::std::forward<Event>(event));
                break;
            default:
                break;
        }
        return res;
    }
    template < typename Event >
    actions::event_process_result
    process_event_impl(Event&&,
        detail::process_type<actions::event_process_result::refuse> const&)
    {
        static_assert( detail::event_process_selector<
                Event,
                typename state_machine::handled_events,
                typename state_machine::deferred_events>::value
            != actions::event_process_result::refuse,
            "Event type is not handled by this state machine" );
        return actions::event_process_result::refuse;
    }

    template < typename Event >
    void
    enqueue_event(Event&& event)
    {
        lock_guard lock{mutex_};
        observer_wrapper::enqueue_event(*this, ::std::forward<Event>(event));
        Event evt = event;
        queued_events_.emplace_back([&, evt]() mutable {
            return process_event_dispatch(::std::move(evt));
        });
    }

    void
    process_event_queue()
    {
        event_queue postponed;
        {
            lock_guard lock{mutex_};
            ::std::swap(queued_events_, postponed);
        }
        while (!postponed.empty()) {
            observer_wrapper::start_process_events_queue(*this);
            for (auto const& event : postponed) {
                event();
            }
            {
                lock_guard lock{mutex_};
                postponed.clear();
                ::std::swap(queued_events_, postponed);
            }
            observer_wrapper::end_process_events_queue(*this);
        }
    }

    template < typename Event >
    void
    defer_event(Event&& event)
    {
        lock_guard lock{deferred_mutex_};
        observer_wrapper::defer_event(*this, ::std::forward<Event>(event));
        Event evt = event;
        deferred_events_.emplace_back([&, evt]() mutable {
            return process_event_dispatch(::std::move(evt));
        });
    }
    void
    process_deferred_queue()
    {
        using actions::event_process_result;
        if (stack_size_++ <= 1) {
            event_queue deferred;
            {
                lock_guard lock{deferred_mutex_};
                ::std::swap(deferred_events_, deferred);
            }
            while (!deferred.empty()) {
                observer_wrapper::start_process_deferred_queue(*this);
                auto res = event_process_result::refuse;
                while (!deferred.empty()) {
                    auto event = deferred.front();
                    deferred.pop_front();
                    res = event();
                    if (res == event_process_result::process)
                        break;
                }
                {
                    lock_guard lock{deferred_mutex_};
                    deferred_events_.insert(deferred_events_.end(), deferred.begin(), deferred.end());
                    deferred.clear();
                }
                if (res == event_process_result::process) {
                    ::std::swap(deferred_events_, deferred);
                }
                observer_wrapper::end_process_deferred_queue(*this);
            }
        }
        --stack_size_;
    }
private:
    using atomic_counter    = ::std::atomic< ::std::size_t >;
    using event_invokation  = ::std::function< actions::event_process_result() >;
    using event_queue       = ::std::deque< event_invokation >;

    atomic_counter          stack_size_;

    mutex_type              mutex_;
    event_queue             queued_events_;

    mutex_type              deferred_mutex_;
    event_queue             deferred_events_;
};

}  /* namespace afsm */

#endif /* AFSM_FSM_HPP_ */
<commit_msg>Correct event queue processing for multithreaded FSM use<commit_after>/*
 * fsm.hpp
 *
 *  Created on: 25 мая 2016 г.
 *      Author: sergey.fedorov
 */

#ifndef AFSM_FSM_HPP_
#define AFSM_FSM_HPP_

#include <afsm/detail/base_states.hpp>
#include <afsm/detail/observer.hpp>
#include <deque>

namespace afsm {

//----------------------------------------------------------------------------
//  State
//----------------------------------------------------------------------------
template < typename T, typename FSM >
class state : public detail::state_base< T > {
public:
    using enclosing_fsm_type    = FSM;
public:
    state(enclosing_fsm_type& fsm)
        : state::state_type{}, fsm_{&fsm}
    {}
    state(state const& rhs) = default;
    state(state&& rhs) = default;
    state(enclosing_fsm_type& fsm, state const& rhs)
        : state::state_type{static_cast<typename state::state_type const&>(rhs)}, fsm_{&fsm}
    {}
    state(enclosing_fsm_type& fsm, state&& rhs)
        : state::state_type{static_cast<typename state::state_type&&>(rhs)}, fsm_{&fsm}
    {}

    state&
    operator = (state const& rhs)
    {
        state{rhs}.swap(*this);
        return *this;
    }
    state&
    operator = (state&& rhs)
    {
        swap(rhs);
        return *this;
    }

    void
    swap(state& rhs) noexcept
    {
        static_cast<typename state::state_type&>(*this).swap(rhs);
    }

    template < typename Event >
    actions::event_process_result
    process_event( Event&& evt )
    {
        return process_event_impl(::std::forward<Event>(evt),
                detail::event_process_selector<
                    Event,
                    typename state::internal_events,
                    typename state::deferred_events>{} );
    }

    enclosing_fsm_type&
    enclosing_fsm()
    { return *fsm_; }
    enclosing_fsm_type const&
    enclosing_fsm() const
    { return *fsm_; }
    void
    enclosing_fsm(enclosing_fsm_type& fsm)
    { fsm_ = &fsm; }

    template < typename Event >
    void
    state_enter(Event&&) {}
    template < typename Event >
    void
    state_exit(Event&&) {}
private:
    template < typename Event >
    actions::event_process_result
    process_event_impl(Event&& evt,
        detail::process_type<actions::event_process_result::process> const&)
    {
        return actions::handle_in_state_event(::std::forward<Event>(evt), *fsm_, *this);
    }
    template < typename Event >
    constexpr actions::event_process_result
    process_event_impl(Event&&,
        detail::process_type<actions::event_process_result::defer> const&)
    {
        return actions::event_process_result::defer;
    }
    template < typename Event >
    constexpr actions::event_process_result
    process_event_impl(Event&&,
        detail::process_type<actions::event_process_result::refuse> const&)
    {
        return actions::event_process_result::refuse;
    }
private:
    enclosing_fsm_type*    fsm_;
};

//----------------------------------------------------------------------------
//  Inner state machine
//----------------------------------------------------------------------------
template < typename T, typename FSM >
class inner_state_machine : public detail::state_machine_base< T, none, inner_state_machine<T, FSM> > {
public:
    using enclosing_fsm_type    = FSM;
    using this_type = inner_state_machine<T, FSM>;
    using base_machine_type     = detail::state_machine_base< T, none, this_type >;
public:
    inner_state_machine(enclosing_fsm_type& fsm)
        : base_machine_type{this}, fsm_{&fsm} {}
    inner_state_machine(inner_state_machine const& rhs)
        : base_machine_type{this, rhs}, fsm_{rhs.fsm_} {}
    inner_state_machine(inner_state_machine&& rhs)
        : base_machine_type{this, ::std::move(rhs)},
          fsm_{rhs.fsm_}
    {
    }

    inner_state_machine(enclosing_fsm_type& fsm, inner_state_machine const& rhs)
        : base_machine_type{static_cast<base_machine_type const&>(rhs)}, fsm_{&fsm} {}
    inner_state_machine(enclosing_fsm_type& fsm, inner_state_machine&& rhs)
        : base_machine_type{static_cast<base_machine_type&&>(rhs)}, fsm_{&fsm} {}

    void
    swap(inner_state_machine& rhs) noexcept
    {
        using ::std::swap;
        static_cast<base_machine_type&>(*this).swap(rhs);
        swap(fsm_, rhs.fsm_);
    }
    inner_state_machine&
    operator = (inner_state_machine const& rhs)
    {
        inner_state_machine tmp{rhs};
        swap(tmp);
        return *this;
    }
    inner_state_machine&
    operator = (inner_state_machine&& rhs)
    {
        swap(rhs);
        return *this;
    }

    template < typename Event >
    actions::event_process_result
    process_event( Event&& event )
    {
        return process_event_impl(*fsm_, ::std::forward<Event>(event),
                detail::event_process_selector<
                    Event,
                    typename inner_state_machine::handled_events,
                    typename inner_state_machine::deferred_events>{} );
    }

    enclosing_fsm_type&
    enclosing_fsm()
    { return *fsm_; }
    enclosing_fsm_type const&
    enclosing_fsm() const
    { return *fsm_; }
    void
    enclosing_fsm(enclosing_fsm_type& fsm)
    { fsm_ = &fsm; }
private:
    using base_machine_type::process_event_impl;
private:
    enclosing_fsm_type*    fsm_;
};

//----------------------------------------------------------------------------
//  State machine
//----------------------------------------------------------------------------
template < typename T, typename Mutex, typename Observer,
        template<typename> class ObserverWrapper >
class state_machine :
        public detail::state_machine_base< T, Mutex,
            state_machine<T, Mutex, Observer> >,
        public ObserverWrapper<Observer> {
public:
    static_assert( ::psst::meta::is_empty< typename T::deferred_events >::value,
            "Outer state machine cannot defer events" );
    using this_type         = state_machine<T, Mutex, Observer>;
    using base_machine_type = detail::state_machine_base< T, Mutex, this_type >;
    using mutex_type        = Mutex;
    using lock_guard        = typename detail::lock_guard_type<mutex_type>::type;
    using observer_wrapper  = ObserverWrapper<Observer>;
    using event_invokation  = ::std::function< actions::event_process_result() >;
    using event_queue       = ::std::deque< event_invokation >;
public:
    state_machine()
        : base_machine_type{this},
          stack_size_{0},
          mutex_{},
          queued_events_{},
          queue_size_{0},
          deferred_mutex_{},
          deferred_events_{}
      {}
    template<typename ... Args>
    explicit
    state_machine(Args&& ... args)
        : base_machine_type(this, ::std::forward<Args>(args)...),
          stack_size_{0},
          mutex_{},
          queued_events_{},
          queue_size_{0},
          deferred_mutex_{},
          deferred_events_{}
    {}

    template < typename Event >
    actions::event_process_result
    process_event( Event&& event )
    {
        if (!stack_size_++) {
            auto res = process_event_dispatch(::std::forward<Event>(event));
            --stack_size_;
            // Process enqueued events
            process_event_queue();
            return res;
        } else {
            --stack_size_;
            // Enqueue event
            enqueue_event(::std::forward<Event>(event));
            return actions::event_process_result::defer;
        }
    }
private:
    template < typename Event >
    actions::event_process_result
    process_event_dispatch( Event&& event )
    {
        return process_event_impl(::std::forward<Event>(event),
                    detail::event_process_selector<
                        Event,
                        typename state_machine::handled_events>{} );
    }

    template < typename Event >
    actions::event_process_result
    process_event_impl(Event&& event,
        detail::process_type<actions::event_process_result::process> const& sel)
    {
        using actions::event_process_result;
        observer_wrapper::start_process_event(*this, ::std::forward<Event>(event));
        auto res = base_machine_type::process_event_impl(*this, ::std::forward<Event>(event), sel );
        switch (res) {
            case event_process_result::process:
                observer_wrapper::state_changed(*this);
                // Changed state. Process deferred events
                process_deferred_queue();
                break;
            case event_process_result::process_in_state:
                observer_wrapper::processed_in_state(*this, ::std::forward<Event>(event));
                break;
            case event_process_result::defer:
                // Add event to deferred queue
                defer_event(::std::forward<Event>(event));
                break;
            case event_process_result::refuse:
                // The event cannot be processed in current state
                observer_wrapper::reject_event(*this, ::std::forward<Event>(event));
                break;
            default:
                break;
        }
        return res;
    }
    template < typename Event >
    actions::event_process_result
    process_event_impl(Event&&,
        detail::process_type<actions::event_process_result::refuse> const&)
    {
        static_assert( detail::event_process_selector<
                Event,
                typename state_machine::handled_events,
                typename state_machine::deferred_events>::value
            != actions::event_process_result::refuse,
            "Event type is not handled by this state machine" );
        return actions::event_process_result::refuse;
    }

    template < typename Event >
    void
    enqueue_event(Event&& event)
    {
        {
            lock_guard lock{mutex_};
            ++queue_size_;
            observer_wrapper::enqueue_event(*this, ::std::forward<Event>(event));
            Event evt = event;
            queued_events_.emplace_back([&, evt]() mutable {
                return process_event_dispatch(::std::move(evt));
            });
        }
        // Process enqueued events in case we've been waiting for queue
        // mutex release
        process_event_queue();
    }

    void
    lock_and_swap_queue(event_queue& queue)
    {
        lock_guard lock{mutex_};
        ::std::swap(queued_events_, queue);
    }

    void
    process_event_queue()
    {
        if (!stack_size_++) {
            while (queue_size_ > 0) {
                event_queue postponed;
                lock_and_swap_queue(postponed);
                queue_size_ -= postponed.size();
                observer_wrapper::start_process_events_queue(*this);
                for (auto const& event : postponed) {
                    event();
                }
                observer_wrapper::end_process_events_queue(*this);
            }
        }
        --stack_size_;
    }

    template < typename Event >
    void
    defer_event(Event&& event)
    {
        lock_guard lock{deferred_mutex_};
        observer_wrapper::defer_event(*this, ::std::forward<Event>(event));
        Event evt = event;
        deferred_events_.emplace_back([&, evt]() mutable {
            return process_event_dispatch(::std::move(evt));
        });
    }
    void
    process_deferred_queue()
    {
        using actions::event_process_result;
        if (stack_size_++ <= 1) {
            event_queue deferred;
            {
                lock_guard lock{deferred_mutex_};
                ::std::swap(deferred_events_, deferred);
            }
            while (!deferred.empty()) {
                observer_wrapper::start_process_deferred_queue(*this);
                auto res = event_process_result::refuse;
                while (!deferred.empty()) {
                    auto event = deferred.front();
                    deferred.pop_front();
                    res = event();
                    if (res == event_process_result::process)
                        break;
                }
                {
                    lock_guard lock{deferred_mutex_};
                    deferred_events_.insert(deferred_events_.end(), deferred.begin(), deferred.end());
                    deferred.clear();
                }
                if (res == event_process_result::process) {
                    ::std::swap(deferred_events_, deferred);
                }
                observer_wrapper::end_process_deferred_queue(*this);
            }
        }
        --stack_size_;
    }
private:
    using atomic_counter    = ::std::atomic< ::std::size_t >;

    atomic_counter          stack_size_;

    mutex_type              mutex_;
    event_queue             queued_events_;
    atomic_counter          queue_size_;

    mutex_type              deferred_mutex_;
    event_queue             deferred_events_;
};

}  /* namespace afsm */

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


<commit_before>/***************************************************************************
 *   Copyright (c) Victor Titov (DeepSOIC)                                 *
 *                                           (vv.titov@gmail.com) 2015     *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 of the License, or (at your option) any later version.      *
 *                                                                         *
 *   This library  is distributed in the hope that it will be useful,      *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "PreCompiled.h"
#ifndef _PreComp_
#endif

#include "AttachExtension.h"

#include <Base/Console.h>
#include <App/Application.h>

#include <App/FeaturePythonPyImp.h>
#include "AttachExtensionPy.h"

using namespace Part;
using namespace Attacher;

EXTENSION_PROPERTY_SOURCE(Part::AttachExtension, App::DocumentObjectExtension);

AttachExtension::AttachExtension()
   :  _attacher(0)
{
    EXTENSION_ADD_PROPERTY_TYPE(AttacherType, ("Attacher::AttachEngine3D"), "Attachment",(App::PropertyType)(App::Prop_None),"Class name of attach engine object driving the attachment.");
    this->AttacherType.setStatus(App::Property::Status::Hidden, true);

    EXTENSION_ADD_PROPERTY_TYPE(Support, (0,0), "Attachment",(App::PropertyType)(App::Prop_None),"Support of the 2D geometry");

    EXTENSION_ADD_PROPERTY_TYPE(MapMode, (mmDeactivated), "Attachment", App::Prop_None, "Mode of attachment to other object");
    MapMode.setEditorName("PartGui::PropertyEnumAttacherItem");
    MapMode.setEnums(AttachEngine::eMapModeStrings);
    //a rough test if mode string list in Attacher.cpp is in sync with eMapMode enum.
    assert(MapMode.getEnumVector().size() == mmDummy_NumberOfModes);

    EXTENSION_ADD_PROPERTY_TYPE(MapReversed, (false), "Attachment", App::Prop_None, "Reverse Z direction (flip sketch upside down)");

    EXTENSION_ADD_PROPERTY_TYPE(MapPathParameter, (0.0), "Attachment", App::Prop_None, "Sets point of curve to map the sketch to. 0..1 = start..end");

    EXTENSION_ADD_PROPERTY_TYPE(superPlacement, (Base::Placement()), "Attachment", App::Prop_None, "Extra placement to apply in addition to attachment (in local coordinates)");

    // Only show these properties when applicable. Controlled by extensionOnChanged
    this->MapPathParameter.setStatus(App::Property::Status::Hidden, true);
    this->MapReversed.setStatus(App::Property::Status::Hidden, true);
    this->superPlacement.setStatus(App::Property::Status::Hidden, true);

    setAttacher(new AttachEngine3D);//default attacher
    initExtensionType(AttachExtension::getExtensionClassTypeId());
}

AttachExtension::~AttachExtension()
{
    if(_attacher)
        delete _attacher;
}

void AttachExtension::setAttacher(AttachEngine* attacher)
{
    if (_attacher)
        delete _attacher;
    _attacher = attacher;
    if (_attacher){
        const char* typeName = attacher->getTypeId().getName();
        if(strcmp(this->AttacherType.getValue(),typeName)!=0) //make sure we need to change, to break recursive onChange->changeAttacherType->onChange...
            this->AttacherType.setValue(typeName);
        updateAttacherVals();
    } else {
        if (strlen(AttacherType.getValue()) != 0){ //make sure we need to change, to break recursive onChange->changeAttacherType->onChange...
            this->AttacherType.setValue("");
        }
    }
}

bool AttachExtension::changeAttacherType(const char* typeName)
{
    //check if we need to actually change anything
    if (_attacher){
        if (strcmp(_attacher->getTypeId().getName(),typeName)==0){
            return false;
        }
    } else if (strlen(typeName) == 0){
        return false;
    }
    if (strlen(typeName) == 0){
        setAttacher(nullptr);
        return true;
    }
    Base::Type t = Base::Type::fromName(typeName);
    if (t.isDerivedFrom(AttachEngine::getClassTypeId())){
        AttachEngine* pNewAttacher = static_cast<Attacher::AttachEngine*>(Base::Type::createInstanceByName(typeName));
        this->setAttacher(pNewAttacher);
        return true;
    } else {
        std::stringstream errMsg;
        errMsg << "Object if this type is not derived from AttachEngine: " << typeName;
        throw Base::Exception(errMsg.str());
    }
    assert(false);//exec shouldn't ever get here
    return false;
}

bool AttachExtension::positionBySupport()
{
    if (!_attacher)
        throw Base::RuntimeError("AttachExtension: can't positionBySupport, because no AttachEngine is set.");
    updateAttacherVals();
    try {
        if (_attacher->mapMode == mmDeactivated)
            return false;
        getPlacement().setValue(_attacher->calculateAttachedPlacement(getPlacement().getValue()));
        return true;
    } catch (ExceptionCancel) {
        //disabled, don't do anything
        return false;
    };
}

short int AttachExtension::extensionMustExecute(void) {
    return DocumentObjectExtension::extensionMustExecute();
}

App::DocumentObjectExecReturn *AttachExtension::extensionExecute()
{
    if(this->isTouched_Mapping()) {
        try{
            positionBySupport();
        // we let all Base::Exceptions thru, so that App:DocumentObject can take appropriate action
        /*} catch (Base::Exception &e) {
            return new App::DocumentObjectExecReturn(e.what());*/
        // Convert OCC exceptions to Base::Exception
        } catch (Standard_Failure &e){
            throw Base::RuntimeError(e.GetMessageString());
//            return new App::DocumentObjectExecReturn(e.GetMessageString());
        }
    }
    return App::DocumentObjectExtension::extensionExecute();
}

void AttachExtension::extensionOnChanged(const App::Property* prop)
{
    if(! getExtendedObject()->isRestoring()){
        if ((prop == &Support
             || prop == &MapMode
             || prop == &MapPathParameter
             || prop == &MapReversed
             || prop == &superPlacement)){

            bool bAttached = false;
            try{
                bAttached = positionBySupport();
            } catch (Base::Exception &e) {
                getExtendedObject()->setStatus(App::Error, true);
                Base::Console().Error("PositionBySupport: %s",e.what());
                //set error message - how?
            } catch (Standard_Failure &e){
                getExtendedObject()->setStatus(App::Error, true);
                Base::Console().Error("PositionBySupport: %s",e.GetMessageString());
            }

            // Hide properties when not applicable to reduce user confusion

            eMapMode mmode = eMapMode(this->MapMode.getValue());

            bool modeIsPointOnCurve = mmode == mmNormalToPath ||
                mmode == mmFrenetNB || mmode == mmFrenetTN || mmode == mmFrenetTB ||
                mmode == mmRevolutionSection || mmode == mmConcentric;

            // MapPathParameter is only used if there is a reference to one edge and not edge + vertex
            bool hasOneRef = false;
            if (_attacher && _attacher->references.getSubValues().size() == 1) {
                hasOneRef = true;
            }

            this->MapPathParameter.setStatus(App::Property::Status::Hidden, !bAttached || !(modeIsPointOnCurve && hasOneRef));
            this->MapReversed.setStatus(App::Property::Status::Hidden, !bAttached);
            this->superPlacement.setStatus(App::Property::Status::Hidden, !bAttached);
            getPlacement().setReadOnly(bAttached && mmode != mmTranslate); //for mmTranslate, orientation should remain editable even when attached.
        }

    }

    if(prop == &(this->AttacherType)){
        this->changeAttacherType(this->AttacherType.getValue());
    }

    App::DocumentObjectExtension::extensionOnChanged(prop);
}

void AttachExtension::updateAttacherVals()
{
    if (!_attacher)
        return;
    _attacher->setUp(this->Support,
                     eMapMode(this->MapMode.getValue()),
                     this->MapReversed.getValue(),
                     this->MapPathParameter.getValue(),
                     0.0,0.0,
                     this->superPlacement.getValue());
}

App::PropertyPlacement& AttachExtension::getPlacement() {

    if(!getExtendedObject()->isDerivedFrom(App::GeoFeature::getClassTypeId()))
        throw Base::RuntimeError("AttachExtension not added to GeooFeature!");

    return static_cast<App::GeoFeature*>(getExtendedObject())->Placement;
}

PyObject* AttachExtension::getExtensionPyObject(void) {

    if (ExtensionPythonObject.is(Py::_None())){
        // ref counter is set to 1
        ExtensionPythonObject = Py::Object(new AttachExtensionPy(this),true);
    }
    return Py::new_reference_to(ExtensionPythonObject);
}

namespace App {
/// @cond DOXERR
  EXTENSION_PROPERTY_SOURCE_TEMPLATE(Part::AttachExtensionPython, Part::AttachExtension)
/// @endcond

// explicit template instantiation
  template class PartExport ExtensionPythonT<Part::AttachExtension>;
}

<commit_msg>improve readability of attachment error messages<commit_after>/***************************************************************************
 *   Copyright (c) Victor Titov (DeepSOIC)                                 *
 *                                           (vv.titov@gmail.com) 2015     *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 of the License, or (at your option) any later version.      *
 *                                                                         *
 *   This library  is distributed in the hope that it will be useful,      *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "PreCompiled.h"
#ifndef _PreComp_
#endif

#include "AttachExtension.h"

#include <Base/Console.h>
#include <App/Application.h>

#include <App/FeaturePythonPyImp.h>
#include "AttachExtensionPy.h"

using namespace Part;
using namespace Attacher;

EXTENSION_PROPERTY_SOURCE(Part::AttachExtension, App::DocumentObjectExtension);

AttachExtension::AttachExtension()
   :  _attacher(0)
{
    EXTENSION_ADD_PROPERTY_TYPE(AttacherType, ("Attacher::AttachEngine3D"), "Attachment",(App::PropertyType)(App::Prop_None),"Class name of attach engine object driving the attachment.");
    this->AttacherType.setStatus(App::Property::Status::Hidden, true);

    EXTENSION_ADD_PROPERTY_TYPE(Support, (0,0), "Attachment",(App::PropertyType)(App::Prop_None),"Support of the 2D geometry");

    EXTENSION_ADD_PROPERTY_TYPE(MapMode, (mmDeactivated), "Attachment", App::Prop_None, "Mode of attachment to other object");
    MapMode.setEditorName("PartGui::PropertyEnumAttacherItem");
    MapMode.setEnums(AttachEngine::eMapModeStrings);
    //a rough test if mode string list in Attacher.cpp is in sync with eMapMode enum.
    assert(MapMode.getEnumVector().size() == mmDummy_NumberOfModes);

    EXTENSION_ADD_PROPERTY_TYPE(MapReversed, (false), "Attachment", App::Prop_None, "Reverse Z direction (flip sketch upside down)");

    EXTENSION_ADD_PROPERTY_TYPE(MapPathParameter, (0.0), "Attachment", App::Prop_None, "Sets point of curve to map the sketch to. 0..1 = start..end");

    EXTENSION_ADD_PROPERTY_TYPE(superPlacement, (Base::Placement()), "Attachment", App::Prop_None, "Extra placement to apply in addition to attachment (in local coordinates)");

    // Only show these properties when applicable. Controlled by extensionOnChanged
    this->MapPathParameter.setStatus(App::Property::Status::Hidden, true);
    this->MapReversed.setStatus(App::Property::Status::Hidden, true);
    this->superPlacement.setStatus(App::Property::Status::Hidden, true);

    setAttacher(new AttachEngine3D);//default attacher
    initExtensionType(AttachExtension::getExtensionClassTypeId());
}

AttachExtension::~AttachExtension()
{
    if(_attacher)
        delete _attacher;
}

void AttachExtension::setAttacher(AttachEngine* attacher)
{
    if (_attacher)
        delete _attacher;
    _attacher = attacher;
    if (_attacher){
        const char* typeName = attacher->getTypeId().getName();
        if(strcmp(this->AttacherType.getValue(),typeName)!=0) //make sure we need to change, to break recursive onChange->changeAttacherType->onChange...
            this->AttacherType.setValue(typeName);
        updateAttacherVals();
    } else {
        if (strlen(AttacherType.getValue()) != 0){ //make sure we need to change, to break recursive onChange->changeAttacherType->onChange...
            this->AttacherType.setValue("");
        }
    }
}

bool AttachExtension::changeAttacherType(const char* typeName)
{
    //check if we need to actually change anything
    if (_attacher){
        if (strcmp(_attacher->getTypeId().getName(),typeName)==0){
            return false;
        }
    } else if (strlen(typeName) == 0){
        return false;
    }
    if (strlen(typeName) == 0){
        setAttacher(nullptr);
        return true;
    }
    Base::Type t = Base::Type::fromName(typeName);
    if (t.isDerivedFrom(AttachEngine::getClassTypeId())){
        AttachEngine* pNewAttacher = static_cast<Attacher::AttachEngine*>(Base::Type::createInstanceByName(typeName));
        this->setAttacher(pNewAttacher);
        return true;
    } else {
        std::stringstream errMsg;
        errMsg << "Object if this type is not derived from AttachEngine: " << typeName;
        throw Base::Exception(errMsg.str());
    }
    assert(false);//exec shouldn't ever get here
    return false;
}

bool AttachExtension::positionBySupport()
{
    if (!_attacher)
        throw Base::RuntimeError("AttachExtension: can't positionBySupport, because no AttachEngine is set.");
    updateAttacherVals();
    try {
        if (_attacher->mapMode == mmDeactivated)
            return false;
        getPlacement().setValue(_attacher->calculateAttachedPlacement(getPlacement().getValue()));
        return true;
    } catch (ExceptionCancel) {
        //disabled, don't do anything
        return false;
    };
}

short int AttachExtension::extensionMustExecute(void) {
    return DocumentObjectExtension::extensionMustExecute();
}

App::DocumentObjectExecReturn *AttachExtension::extensionExecute()
{
    if(this->isTouched_Mapping()) {
        try{
            positionBySupport();
        // we let all Base::Exceptions thru, so that App:DocumentObject can take appropriate action
        /*} catch (Base::Exception &e) {
            return new App::DocumentObjectExecReturn(e.what());*/
        // Convert OCC exceptions to Base::Exception
        } catch (Standard_Failure &e){
            throw Base::RuntimeError(e.GetMessageString());
//            return new App::DocumentObjectExecReturn(e.GetMessageString());
        }
    }
    return App::DocumentObjectExtension::extensionExecute();
}

void AttachExtension::extensionOnChanged(const App::Property* prop)
{
    if(! getExtendedObject()->isRestoring()){
        if ((prop == &Support
             || prop == &MapMode
             || prop == &MapPathParameter
             || prop == &MapReversed
             || prop == &superPlacement)){

            bool bAttached = false;
            try{
                bAttached = positionBySupport();
            } catch (Base::Exception &e) {
                getExtendedObject()->setStatus(App::Error, true);
                Base::Console().Error("PositionBySupport: %s\n",e.what());
                //set error message - how?
            } catch (Standard_Failure &e){
                getExtendedObject()->setStatus(App::Error, true);
                Base::Console().Error("PositionBySupport: %s\n",e.GetMessageString());
            }

            // Hide properties when not applicable to reduce user confusion

            eMapMode mmode = eMapMode(this->MapMode.getValue());

            bool modeIsPointOnCurve = mmode == mmNormalToPath ||
                mmode == mmFrenetNB || mmode == mmFrenetTN || mmode == mmFrenetTB ||
                mmode == mmRevolutionSection || mmode == mmConcentric;

            // MapPathParameter is only used if there is a reference to one edge and not edge + vertex
            bool hasOneRef = false;
            if (_attacher && _attacher->references.getSubValues().size() == 1) {
                hasOneRef = true;
            }

            this->MapPathParameter.setStatus(App::Property::Status::Hidden, !bAttached || !(modeIsPointOnCurve && hasOneRef));
            this->MapReversed.setStatus(App::Property::Status::Hidden, !bAttached);
            this->superPlacement.setStatus(App::Property::Status::Hidden, !bAttached);
            getPlacement().setReadOnly(bAttached && mmode != mmTranslate); //for mmTranslate, orientation should remain editable even when attached.
        }

    }

    if(prop == &(this->AttacherType)){
        this->changeAttacherType(this->AttacherType.getValue());
    }

    App::DocumentObjectExtension::extensionOnChanged(prop);
}

void AttachExtension::updateAttacherVals()
{
    if (!_attacher)
        return;
    _attacher->setUp(this->Support,
                     eMapMode(this->MapMode.getValue()),
                     this->MapReversed.getValue(),
                     this->MapPathParameter.getValue(),
                     0.0,0.0,
                     this->superPlacement.getValue());
}

App::PropertyPlacement& AttachExtension::getPlacement() {

    if(!getExtendedObject()->isDerivedFrom(App::GeoFeature::getClassTypeId()))
        throw Base::RuntimeError("AttachExtension not added to GeooFeature!");

    return static_cast<App::GeoFeature*>(getExtendedObject())->Placement;
}

PyObject* AttachExtension::getExtensionPyObject(void) {

    if (ExtensionPythonObject.is(Py::_None())){
        // ref counter is set to 1
        ExtensionPythonObject = Py::Object(new AttachExtensionPy(this),true);
    }
    return Py::new_reference_to(ExtensionPythonObject);
}

namespace App {
/// @cond DOXERR
  EXTENSION_PROPERTY_SOURCE_TEMPLATE(Part::AttachExtensionPython, Part::AttachExtension)
/// @endcond

// explicit template instantiation
  template class PartExport ExtensionPythonT<Part::AttachExtension>;
}

<|endoftext|>