<commit_before>/**
 *  @copyright Copyright 2016 The J-PET Framework Authors. All rights reserved.
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may find a copy of the License in the LICENCE file.
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *  @file TimeCalibTools.cpp
 */

#include <boost/algorithm/string/predicate.hpp> /// for starts_with
#include <algorithm> /// for any_of()
#include <sstream>
#include "TimeCalibTools.h"
#include "JPetLoggerInclude.h"

double TimeCalibTools::getTimeCalibCorrection(const TOMBChToCorrection& timeCalibration, const unsigned int channel)
{
  if (timeCalibration.find(channel) == timeCalibration.end()) {
    WARNING("No time calibration available for this channel");
    return 0.0;
  } else {
    return timeCalibration.at(channel);
  }
}

TimeCalibTools::TOMBChToCorrection TimeCalibTools::loadTimeCalibration(const std::string& calibFile, const TimeCalibTools::TOMBChMap& tombMap)
{
  INFO("Loading time calibration from:" + calibFile);
  auto calibRecords = readCalibrationRecordsFromFile(calibFile);
  return generateTimeCalibration(calibRecords, tombMap);
}

TimeCalibTools::TOMBChToCorrection TimeCalibTools::generateTimeCalibration(const std::vector<TimeCalibRecord>& calibRecords,  const TimeCalibTools::TOMBChMap& tombMap)
{
  TOMBChToCorrection timeCalibration;
  if (areCorrectTimeCalibRecords(calibRecords)) {
    std::transform(calibRecords.begin(),
                   calibRecords.end(),
                   std::inserter(timeCalibration, timeCalibration.begin()),
    [&tombMap](const TimeCalibRecord & r) {
      auto key = std::make_tuple(r.layer, r.slot, r.side, r.threshold);
      auto correction = r.offset_value_leading;
      if (tombMap.find(key) != tombMap.end()) {
        auto tombCh = tombMap.at(key);
        return std::make_pair(tombCh, correction);
      } else {
        ERROR("No TOMB channel number in TOMB MAP for the combination: layer=" + std::to_string(r.layer) + ",slot=" + std::to_string(r.slot) + ",side=" + std::to_string(r.side) + ",threshold=" + std::to_string(r.threshold));
        return std::make_pair(-1, 0.0);
      }
    });
  } else {
    ERROR("Empty calibration will be returned");
  }
  return timeCalibration;
}

std::vector<TimeCalibRecord> TimeCalibTools::readCalibrationRecordsFromFile(const std::string& calibFile)
{
  using namespace std;
  namespace ba = boost::algorithm;

  std::vector<TimeCalibRecord> timeCalibRecords;
  string line;
  TimeCalibRecord record = { -1, -1, JPetPM::SideA, -1, 0.0, -1.0, 0.0, -1.0, -1.0 };
  ifstream inputFile(calibFile);

  while (getline(inputFile, line)) {
    /// Lines starting with # are comments and they are ignored.
    if (ba::starts_with(line, "#")) {
      continue;
    } else {
      if (fillTimeCalibRecord(line, record)) {
        timeCalibRecords.push_back(record);
      } else {
        ERROR("Line from the time calibration file seems to be incorrect:" + line);
      }
    }
  }
  return timeCalibRecords;
}

bool TimeCalibTools::areCorrectTimeCalibRecords(const std::vector<TimeCalibRecord>& records)
{
  const auto kMinSlot = 1;
  const auto kMaxSlot = 96;
  const auto kMinLayer = 1;
  const auto kMaxLayer = 3;
  const auto kMinThr = 1;
  const auto kMaxThr = 4;
  return ! std::any_of(
           records.begin(),
           records.end(),
  [](const TimeCalibRecord & r) {
    return ((r.layer < kMinLayer) ||
            (r.layer > kMaxLayer) ||
            (r.slot < kMinSlot) ||
            (r.slot > kMaxSlot) ||
            (r.threshold < kMinThr) ||
            (r.threshold > kMaxThr)
           );
  });
}

bool TimeCalibTools::fillTimeCalibRecord(const std::string& input, TimeCalibRecord& outRecord)
{
  using namespace std;
  int layer = -1;
  int slot = -1;
  char side = 'A';
  int thr = -1;
  double o_val_lead = 0;
  double o_uncert_lead = 0;
  double o_val_trail = 0;
  double o_uncert_trail = 0;
  double quality = 0;
  istringstream ss(input);
  ss >> layer >> slot >> side >> thr >> o_val_lead >> o_uncert_lead >> o_val_trail >> o_uncert_trail >> quality;
  if (ss.fail() || (side != 'A' && side != 'B')) {
    return false;
  } else {
    outRecord.layer = layer;
    outRecord.slot = slot;
    if (side == 'A') {
      outRecord.side = JPetPM::SideA;
    } else {
      outRecord.side = JPetPM::SideB;
    }
    outRecord.threshold = thr;
    outRecord.offset_value_leading = o_val_lead;
    outRecord.offset_uncertainty_leading = o_uncert_lead;
    outRecord.offset_value_trailing = o_val_trail;
    outRecord.offset_uncertainty_trailing = o_uncert_trail;
    outRecord.quality = quality;
    return true;
  }
}
<commit_msg>Change WARNING to DEBUG if no calibration given TimeCalibTools<commit_after>/**
 *  @copyright Copyright 2016 The J-PET Framework Authors. All rights reserved.
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may find a copy of the License in the LICENCE file.
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *  @file TimeCalibTools.cpp
 */

#include <boost/algorithm/string/predicate.hpp> /// for starts_with
#include <algorithm> /// for any_of()
#include <sstream>
#include "TimeCalibTools.h"
#include "JPetLoggerInclude.h"

double TimeCalibTools::getTimeCalibCorrection(const TOMBChToCorrection& timeCalibration, const unsigned int channel)
{
  if (timeCalibration.find(channel) == timeCalibration.end()) {
    DEBUG("No time calibration available for this channel");
    return 0.0;
  } else {
    return timeCalibration.at(channel);
  }
}

TimeCalibTools::TOMBChToCorrection TimeCalibTools::loadTimeCalibration(const std::string& calibFile, const TimeCalibTools::TOMBChMap& tombMap)
{
  INFO("Loading time calibration from:" + calibFile);
  auto calibRecords = readCalibrationRecordsFromFile(calibFile);
  return generateTimeCalibration(calibRecords, tombMap);
}

TimeCalibTools::TOMBChToCorrection TimeCalibTools::generateTimeCalibration(const std::vector<TimeCalibRecord>& calibRecords,  const TimeCalibTools::TOMBChMap& tombMap)
{
  TOMBChToCorrection timeCalibration;
  if (areCorrectTimeCalibRecords(calibRecords)) {
    std::transform(calibRecords.begin(),
                   calibRecords.end(),
                   std::inserter(timeCalibration, timeCalibration.begin()),
    [&tombMap](const TimeCalibRecord & r) {
      auto key = std::make_tuple(r.layer, r.slot, r.side, r.threshold);
      auto correction = r.offset_value_leading;
      if (tombMap.find(key) != tombMap.end()) {
        auto tombCh = tombMap.at(key);
        return std::make_pair(tombCh, correction);
      } else {
        ERROR("No TOMB channel number in TOMB MAP for the combination: layer=" + std::to_string(r.layer) + ",slot=" + std::to_string(r.slot) + ",side=" + std::to_string(r.side) + ",threshold=" + std::to_string(r.threshold));
        return std::make_pair(-1, 0.0);
      }
    });
  } else {
    ERROR("Empty calibration will be returned");
  }
  return timeCalibration;
}

std::vector<TimeCalibRecord> TimeCalibTools::readCalibrationRecordsFromFile(const std::string& calibFile)
{
  using namespace std;
  namespace ba = boost::algorithm;

  std::vector<TimeCalibRecord> timeCalibRecords;
  string line;
  TimeCalibRecord record = { -1, -1, JPetPM::SideA, -1, 0.0, -1.0, 0.0, -1.0, -1.0 };
  ifstream inputFile(calibFile);

  while (getline(inputFile, line)) {
    /// Lines starting with # are comments and they are ignored.
    if (ba::starts_with(line, "#")) {
      continue;
    } else {
      if (fillTimeCalibRecord(line, record)) {
        timeCalibRecords.push_back(record);
      } else {
        ERROR("Line from the time calibration file seems to be incorrect:" + line);
      }
    }
  }
  return timeCalibRecords;
}

bool TimeCalibTools::areCorrectTimeCalibRecords(const std::vector<TimeCalibRecord>& records)
{
  const auto kMinSlot = 1;
  const auto kMaxSlot = 96;
  const auto kMinLayer = 1;
  const auto kMaxLayer = 3;
  const auto kMinThr = 1;
  const auto kMaxThr = 4;
  return ! std::any_of(
           records.begin(),
           records.end(),
  [](const TimeCalibRecord & r) {
    return ((r.layer < kMinLayer) ||
            (r.layer > kMaxLayer) ||
            (r.slot < kMinSlot) ||
            (r.slot > kMaxSlot) ||
            (r.threshold < kMinThr) ||
            (r.threshold > kMaxThr)
           );
  });
}

bool TimeCalibTools::fillTimeCalibRecord(const std::string& input, TimeCalibRecord& outRecord)
{
  using namespace std;
  int layer = -1;
  int slot = -1;
  char side = 'A';
  int thr = -1;
  double o_val_lead = 0;
  double o_uncert_lead = 0;
  double o_val_trail = 0;
  double o_uncert_trail = 0;
  double quality = 0;
  istringstream ss(input);
  ss >> layer >> slot >> side >> thr >> o_val_lead >> o_uncert_lead >> o_val_trail >> o_uncert_trail >> quality;
  if (ss.fail() || (side != 'A' && side != 'B')) {
    return false;
  } else {
    outRecord.layer = layer;
    outRecord.slot = slot;
    if (side == 'A') {
      outRecord.side = JPetPM::SideA;
    } else {
      outRecord.side = JPetPM::SideB;
    }
    outRecord.threshold = thr;
    outRecord.offset_value_leading = o_val_lead;
    outRecord.offset_uncertainty_leading = o_uncert_lead;
    outRecord.offset_value_trailing = o_val_trail;
    outRecord.offset_uncertainty_trailing = o_uncert_trail;
    outRecord.quality = quality;
    return true;
  }
}
<|endoftext|>


<commit_before>/* Copyright (C) 2003 MySQL AB

   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#include <ndb_global.h>
#include <ndb_opt_defaults.h>
#include <IPCConfig.hpp>
#include <NdbOut.hpp>
#include <NdbHost.h>

#include <TransporterDefinitions.hpp>
#include <TransporterRegistry.hpp>
#include <Properties.hpp>

#include <mgmapi_configuration.hpp>
#include <mgmapi_config_parameters.h>

#if defined DEBUG_TRANSPORTER
#define DEBUG(t) ndbout << __FILE__ << ":" << __LINE__ << ":" << t << endl;
#else
#define DEBUG(t)
#endif

IPCConfig::IPCConfig(Properties * p)
{
  theNoOfRemoteNodes = 0;
  the_ownId = 0;
  if(p != 0)
    props = new Properties(* p);
  else
    props = 0;
}

IPCConfig::~IPCConfig()
{
  if(props != 0){
    delete props;
  }
}

int
IPCConfig::init(){
  Uint32 nodeId;

  if(props == 0) return -1;
  if(!props->get("LocalNodeId", &nodeId)) {
    DEBUG( "Did not find local node id." );
    return -1;
  }
  the_ownId = nodeId;

  Uint32 noOfConnections;
  if(!props->get("NoOfConnections", &noOfConnections)) {
    DEBUG( "Did not find noOfConnections." );
    return -1;
  }

  for(Uint32 i = 0; i<noOfConnections; i++){
    const Properties * tmp;
    Uint32 node1, node2;

    if(!props->get("Connection", i, &tmp)) {
      DEBUG( "Did not find Connection." );
      return -1;
    }
    if(!tmp->get("NodeId1", &node1)) {
      DEBUG( "Did not find NodeId1." );
      return -1;
    }
    if(!tmp->get("NodeId2", &node2)) {
      DEBUG( "Did not find NodeId2." );
      return -1;
    }

    if(node1 == the_ownId && node2 != the_ownId)
      if(!addRemoteNodeId(node2)) {
	DEBUG( "addRemoteNodeId(node2) failed." );
	return -1;
      }

    if(node1 != the_ownId && node2 == the_ownId)
      if(!addRemoteNodeId(node1)) {
	DEBUG( "addRemoteNodeId(node2) failed." );
	return -1;
      }
  }
  return 0;
}

bool
IPCConfig::addRemoteNodeId(NodeId nodeId){
  for(int i = 0; i<theNoOfRemoteNodes; i++)
    if(theRemoteNodeIds[i] == nodeId)
      return false;
  theRemoteNodeIds[theNoOfRemoteNodes] = nodeId;
  theNoOfRemoteNodes++;
  return true;
}

/**
 * Supply a nodeId,
 *  and get next higher node id
 * Returns false if none found
 */
bool
IPCConfig::getNextRemoteNodeId(NodeId & nodeId) const {
  NodeId returnNode = MAX_NODES + 1;
  for(int i = 0; i<theNoOfRemoteNodes; i++)
    if(theRemoteNodeIds[i] > nodeId){
      if(theRemoteNodeIds[i] < returnNode){
	returnNode = theRemoteNodeIds[i];
      }
    }
  if(returnNode == (MAX_NODES + 1))
    return false;
  nodeId = returnNode;
  return true;
}

Uint32
IPCConfig::getREPHBFrequency(NodeId id) const {
  const Properties * tmp;
  Uint32 out;

  /**
   *  Todo: Fix correct heartbeat
   */
  if (!props->get("Node", id, &tmp) ||
      !tmp->get("HeartbeatIntervalRepRep", &out)) {
    DEBUG("Illegal Node or HeartbeatIntervalRepRep in config.");
    out = 10000;
  }

  return out;
}

const char*
IPCConfig::getNodeType(NodeId id) const {
  const char * out;
  const Properties * tmp;

  if (!props->get("Node", id, &tmp) || !tmp->get("Type", &out)) {
    DEBUG("Illegal Node or NodeType in config.");
    out = "Unknown";
  }

  return out;
}

#include <mgmapi.h>
Uint32
IPCConfig::configureTransporters(Uint32 nodeId,
				 const class ndb_mgm_configuration & config,
				 class TransporterRegistry & tr){
  TransporterConfiguration conf;

  DBUG_ENTER("IPCConfig::configureTransporters");

  /**
   * Iterate over all MGM's an construct a connectstring
   * create mgm_handle and give it to the Transporter Registry
   */
  {
    const char *separator= "";
    BaseString connect_string;
    ndb_mgm_configuration_iterator iter(config, CFG_SECTION_NODE);
    for(iter.first(); iter.valid(); iter.next())
    {
      Uint32 type;
      if(iter.get(CFG_TYPE_OF_SECTION, &type)) continue;
      if(type != NODE_TYPE_MGM) continue;
      const char* hostname;
      Uint32 port;
      if(iter.get(CFG_NODE_HOST, &hostname)) continue;
      if( strlen(hostname) == 0 ) continue;
      if(iter.get(CFG_MGM_PORT, &port)) continue;
      connect_string.appfmt("%s%s:port",separator,hostname,port);
      separator= ",";
    }
    NdbMgmHandle h= ndb_mgm_create_handle();
    if ( h && connect_string.length() > 0 )
    {
      ndb_mgm_set_connectstring(h,connect_string.c_str());
      tr.set_mgm_handle(h);
    }
  }

  Uint32 noOfTransportersCreated= 0;
  ndb_mgm_configuration_iterator iter(config, CFG_SECTION_CONNECTION);

  for(iter.first(); iter.valid(); iter.next()){

    Uint32 nodeId1, nodeId2, remoteNodeId;
    const char * remoteHostName= 0, * localHostName= 0;
    if(iter.get(CFG_CONNECTION_NODE_1, &nodeId1)) continue;
    if(iter.get(CFG_CONNECTION_NODE_2, &nodeId2)) continue;

    if(nodeId1 != nodeId && nodeId2 != nodeId) continue;
    remoteNodeId = (nodeId == nodeId1 ? nodeId2 : nodeId1);

    {
      const char * host1= 0, * host2= 0;
      iter.get(CFG_CONNECTION_HOSTNAME_1, &host1);
      iter.get(CFG_CONNECTION_HOSTNAME_2, &host2);
      localHostName  = (nodeId == nodeId1 ? host1 : host2);
      remoteHostName = (nodeId == nodeId1 ? host2 : host1);
    }

    Uint32 sendSignalId = 1;
    Uint32 checksum = 1;
    if(iter.get(CFG_CONNECTION_SEND_SIGNAL_ID, &sendSignalId)) continue;
    if(iter.get(CFG_CONNECTION_CHECKSUM, &checksum)) continue;

    Uint32 type = ~0;
    if(iter.get(CFG_TYPE_OF_SECTION, &type)) continue;

    Uint32 server_port= 0;
    if(iter.get(CFG_CONNECTION_SERVER_PORT, &server_port)) break;

    /*
      We check the node type. MGM node becomes server.
    */
    Uint32 node1type, node2type;
    ndb_mgm_configuration_iterator node1iter(config, CFG_SECTION_NODE);
    ndb_mgm_configuration_iterator node2iter(config, CFG_SECTION_NODE);
    node1iter.find(CFG_NODE_ID,nodeId1);
    node2iter.find(CFG_NODE_ID,nodeId2);
    node1iter.get(CFG_TYPE_OF_SECTION,&node1type);
    node2iter.get(CFG_TYPE_OF_SECTION,&node2type);

    conf.serverNodeId= (nodeId1 < nodeId2)? nodeId1:nodeId2;

    conf.isMgmConnection= false;
    if(node2type==NODE_TYPE_MGM)
    {
      conf.isMgmConnection= true;
      conf.serverNodeId= nodeId2;
    }
    else if(node1type==NODE_TYPE_MGM)
    {
      conf.isMgmConnection= true;
      conf.serverNodeId= nodeId1;
    }
    else if (nodeId == conf.serverNodeId) {
      tr.add_transporter_interface(remoteNodeId, localHostName, server_port);
    }

    DBUG_PRINT("info", ("Transporter between this node %d and node %d using port %d, signalId %d, checksum %d",
               nodeId, remoteNodeId, server_port, sendSignalId, checksum));
    /*
      This may be a dynamic port. It depends on when we're getting
      our configuration. If we've been restarted, we'll be getting
      a configuration with our old dynamic port in it, hence the number
      here is negative (and we try the old port number first).

      On a first-run, server_port will be zero (with dynamic ports)

      If we're not using dynamic ports, we don't do anything.
    */
    if((int)server_port<0)
      server_port= -server_port;

    conf.localNodeId    = nodeId;
    conf.remoteNodeId   = remoteNodeId;
    conf.checksum       = checksum;
    conf.signalId       = sendSignalId;
    conf.port           = server_port;
    conf.localHostName  = localHostName;
    conf.remoteHostName = remoteHostName;

    switch(type){
    case CONNECTION_TYPE_SHM:
      if(iter.get(CFG_SHM_KEY, &conf.shm.shmKey)) break;
      if(iter.get(CFG_SHM_BUFFER_MEM, &conf.shm.shmSize)) break;

      Uint32 tmp;
      if(iter.get(CFG_SHM_SIGNUM, &tmp)) break;
      conf.shm.signum= tmp;

      if(!tr.createSHMTransporter(&conf)){
        DBUG_PRINT("error", ("Failed to create SHM Transporter from %d to %d",
	           conf.localNodeId, conf.remoteNodeId));
	ndbout << "Failed to create SHM Transporter from: "
	       << conf.localNodeId << " to: " << conf.remoteNodeId << endl;
      } else {
	noOfTransportersCreated++;
      }
      DBUG_PRINT("info", ("Created SHM Transporter using shmkey %d, "
			  "buf size = %d", conf.shm.shmKey, conf.shm.shmSize));

      break;

    case CONNECTION_TYPE_SCI:
      if(iter.get(CFG_SCI_SEND_LIMIT, &conf.sci.sendLimit)) break;
      if(iter.get(CFG_SCI_BUFFER_MEM, &conf.sci.bufferSize)) break;
      if (nodeId == nodeId1) {
        if(iter.get(CFG_SCI_HOST2_ID_0, &conf.sci.remoteSciNodeId0)) break;
        if(iter.get(CFG_SCI_HOST2_ID_1, &conf.sci.remoteSciNodeId1)) break;
      } else {
        if(iter.get(CFG_SCI_HOST1_ID_0, &conf.sci.remoteSciNodeId0)) break;
        if(iter.get(CFG_SCI_HOST1_ID_1, &conf.sci.remoteSciNodeId1)) break;
      }
      if (conf.sci.remoteSciNodeId1 == 0) {
        conf.sci.nLocalAdapters = 1;
      } else {
        conf.sci.nLocalAdapters = 2;
      }
     if(!tr.createSCITransporter(&conf)){
        DBUG_PRINT("error", ("Failed to create SCI Transporter from %d to %d",
	           conf.localNodeId, conf.remoteNodeId));
	ndbout << "Failed to create SCI Transporter from: "
	       << conf.localNodeId << " to: " << conf.remoteNodeId << endl;
      } else {
        DBUG_PRINT("info", ("Created SCI Transporter: Adapters = %d, "
			    "remote SCI node id %d",
                   conf.sci.nLocalAdapters, conf.sci.remoteSciNodeId0));
        DBUG_PRINT("info", ("Host 1 = %s, Host 2 = %s, sendLimit = %d, "
			    "buf size = %d", conf.localHostName,
			    conf.remoteHostName, conf.sci.sendLimit,
			    conf.sci.bufferSize));
        if (conf.sci.nLocalAdapters > 1) {
          DBUG_PRINT("info", ("Fault-tolerant with 2 Remote Adapters, "
			      "second remote SCI node id = %d",
			      conf.sci.remoteSciNodeId1));
        }
	noOfTransportersCreated++;
	continue;
      }
     break;

    case CONNECTION_TYPE_TCP:
      if(iter.get(CFG_TCP_SEND_BUFFER_SIZE, &conf.tcp.sendBufferSize)) break;
      if(iter.get(CFG_TCP_RECEIVE_BUFFER_SIZE, &conf.tcp.maxReceiveSize)) break;

      const char * proxy;
      if (!iter.get(CFG_TCP_PROXY, &proxy)) {
	if (strlen(proxy) > 0 && nodeId2 == nodeId) {
	  // TODO handle host:port
	  conf.port = atoi(proxy);
	}
      }

      if(!tr.createTCPTransporter(&conf)){
	ndbout << "Failed to create TCP Transporter from: "
	       << nodeId << " to: " << remoteNodeId << endl;
      } else {
	noOfTransportersCreated++;
      }
      DBUG_PRINT("info", ("Created TCP Transporter: sendBufferSize = %d, "
			  "maxReceiveSize = %d", conf.tcp.sendBufferSize,
			  conf.tcp.maxReceiveSize));
      break;
    case CONNECTION_TYPE_OSE:
      if(iter.get(CFG_OSE_PRIO_A_SIZE, &conf.ose.prioASignalSize)) break;
      if(iter.get(CFG_OSE_PRIO_B_SIZE, &conf.ose.prioBSignalSize)) break;

      if(!tr.createOSETransporter(&conf)){
	ndbout << "Failed to create OSE Transporter from: "
	       << nodeId << " to: " << remoteNodeId << endl;
      } else {
	noOfTransportersCreated++;
      }
      break;

    default:
      ndbout << "Unknown transporter type from: " << nodeId <<
	" to: " << remoteNodeId << endl;
      break;
    } // switch
  } // for

  DBUG_RETURN(noOfTransportersCreated);
}

<commit_msg>BUG#10893 Cluster hangs on initial startup<commit_after>/* Copyright (C) 2003 MySQL AB

   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#include <ndb_global.h>
#include <ndb_opt_defaults.h>
#include <IPCConfig.hpp>
#include <NdbOut.hpp>
#include <NdbHost.h>

#include <TransporterDefinitions.hpp>
#include <TransporterRegistry.hpp>
#include <Properties.hpp>

#include <mgmapi_configuration.hpp>
#include <mgmapi_config_parameters.h>

#if defined DEBUG_TRANSPORTER
#define DEBUG(t) ndbout << __FILE__ << ":" << __LINE__ << ":" << t << endl;
#else
#define DEBUG(t)
#endif

IPCConfig::IPCConfig(Properties * p)
{
  theNoOfRemoteNodes = 0;
  the_ownId = 0;
  if(p != 0)
    props = new Properties(* p);
  else
    props = 0;
}

IPCConfig::~IPCConfig()
{
  if(props != 0){
    delete props;
  }
}

int
IPCConfig::init(){
  Uint32 nodeId;

  if(props == 0) return -1;
  if(!props->get("LocalNodeId", &nodeId)) {
    DEBUG( "Did not find local node id." );
    return -1;
  }
  the_ownId = nodeId;

  Uint32 noOfConnections;
  if(!props->get("NoOfConnections", &noOfConnections)) {
    DEBUG( "Did not find noOfConnections." );
    return -1;
  }

  for(Uint32 i = 0; i<noOfConnections; i++){
    const Properties * tmp;
    Uint32 node1, node2;

    if(!props->get("Connection", i, &tmp)) {
      DEBUG( "Did not find Connection." );
      return -1;
    }
    if(!tmp->get("NodeId1", &node1)) {
      DEBUG( "Did not find NodeId1." );
      return -1;
    }
    if(!tmp->get("NodeId2", &node2)) {
      DEBUG( "Did not find NodeId2." );
      return -1;
    }

    if(node1 == the_ownId && node2 != the_ownId)
      if(!addRemoteNodeId(node2)) {
	DEBUG( "addRemoteNodeId(node2) failed." );
	return -1;
      }

    if(node1 != the_ownId && node2 == the_ownId)
      if(!addRemoteNodeId(node1)) {
	DEBUG( "addRemoteNodeId(node2) failed." );
	return -1;
      }
  }
  return 0;
}

bool
IPCConfig::addRemoteNodeId(NodeId nodeId){
  for(int i = 0; i<theNoOfRemoteNodes; i++)
    if(theRemoteNodeIds[i] == nodeId)
      return false;
  theRemoteNodeIds[theNoOfRemoteNodes] = nodeId;
  theNoOfRemoteNodes++;
  return true;
}

/**
 * Supply a nodeId,
 *  and get next higher node id
 * Returns false if none found
 */
bool
IPCConfig::getNextRemoteNodeId(NodeId & nodeId) const {
  NodeId returnNode = MAX_NODES + 1;
  for(int i = 0; i<theNoOfRemoteNodes; i++)
    if(theRemoteNodeIds[i] > nodeId){
      if(theRemoteNodeIds[i] < returnNode){
	returnNode = theRemoteNodeIds[i];
      }
    }
  if(returnNode == (MAX_NODES + 1))
    return false;
  nodeId = returnNode;
  return true;
}

Uint32
IPCConfig::getREPHBFrequency(NodeId id) const {
  const Properties * tmp;
  Uint32 out;

  /**
   *  Todo: Fix correct heartbeat
   */
  if (!props->get("Node", id, &tmp) ||
      !tmp->get("HeartbeatIntervalRepRep", &out)) {
    DEBUG("Illegal Node or HeartbeatIntervalRepRep in config.");
    out = 10000;
  }

  return out;
}

const char*
IPCConfig::getNodeType(NodeId id) const {
  const char * out;
  const Properties * tmp;

  if (!props->get("Node", id, &tmp) || !tmp->get("Type", &out)) {
    DEBUG("Illegal Node or NodeType in config.");
    out = "Unknown";
  }

  return out;
}

#include <mgmapi.h>
Uint32
IPCConfig::configureTransporters(Uint32 nodeId,
				 const class ndb_mgm_configuration & config,
				 class TransporterRegistry & tr){
  TransporterConfiguration conf;

  DBUG_ENTER("IPCConfig::configureTransporters");

  /**
   * Iterate over all MGM's an construct a connectstring
   * create mgm_handle and give it to the Transporter Registry
   */
  {
    const char *separator= "";
    BaseString connect_string;
    ndb_mgm_configuration_iterator iter(config, CFG_SECTION_NODE);
    for(iter.first(); iter.valid(); iter.next())
    {
      Uint32 type;
      if(iter.get(CFG_TYPE_OF_SECTION, &type)) continue;
      if(type != NODE_TYPE_MGM) continue;
      const char* hostname;
      Uint32 port;
      if(iter.get(CFG_NODE_HOST, &hostname)) continue;
      if( strlen(hostname) == 0 ) continue;
      if(iter.get(CFG_MGM_PORT, &port)) continue;
      connect_string.appfmt("%s%s:%u",separator,hostname,port);
      separator= ",";
    }
    NdbMgmHandle h= ndb_mgm_create_handle();
    if ( h && connect_string.length() > 0 )
    {
      ndb_mgm_set_connectstring(h,connect_string.c_str());
      tr.set_mgm_handle(h);
    }
  }

  Uint32 noOfTransportersCreated= 0;
  ndb_mgm_configuration_iterator iter(config, CFG_SECTION_CONNECTION);

  for(iter.first(); iter.valid(); iter.next()){

    Uint32 nodeId1, nodeId2, remoteNodeId;
    const char * remoteHostName= 0, * localHostName= 0;
    if(iter.get(CFG_CONNECTION_NODE_1, &nodeId1)) continue;
    if(iter.get(CFG_CONNECTION_NODE_2, &nodeId2)) continue;

    if(nodeId1 != nodeId && nodeId2 != nodeId) continue;
    remoteNodeId = (nodeId == nodeId1 ? nodeId2 : nodeId1);

    {
      const char * host1= 0, * host2= 0;
      iter.get(CFG_CONNECTION_HOSTNAME_1, &host1);
      iter.get(CFG_CONNECTION_HOSTNAME_2, &host2);
      localHostName  = (nodeId == nodeId1 ? host1 : host2);
      remoteHostName = (nodeId == nodeId1 ? host2 : host1);
    }

    Uint32 sendSignalId = 1;
    Uint32 checksum = 1;
    if(iter.get(CFG_CONNECTION_SEND_SIGNAL_ID, &sendSignalId)) continue;
    if(iter.get(CFG_CONNECTION_CHECKSUM, &checksum)) continue;

    Uint32 type = ~0;
    if(iter.get(CFG_TYPE_OF_SECTION, &type)) continue;

    Uint32 server_port= 0;
    if(iter.get(CFG_CONNECTION_SERVER_PORT, &server_port)) break;

    /*
      We check the node type. MGM node becomes server.
    */
    Uint32 node1type, node2type;
    ndb_mgm_configuration_iterator node1iter(config, CFG_SECTION_NODE);
    ndb_mgm_configuration_iterator node2iter(config, CFG_SECTION_NODE);
    node1iter.find(CFG_NODE_ID,nodeId1);
    node2iter.find(CFG_NODE_ID,nodeId2);
    node1iter.get(CFG_TYPE_OF_SECTION,&node1type);
    node2iter.get(CFG_TYPE_OF_SECTION,&node2type);

    conf.serverNodeId= (nodeId1 < nodeId2)? nodeId1:nodeId2;

    conf.isMgmConnection= false;
    if(node2type==NODE_TYPE_MGM)
    {
      conf.isMgmConnection= true;
      conf.serverNodeId= nodeId2;
    }
    else if(node1type==NODE_TYPE_MGM)
    {
      conf.isMgmConnection= true;
      conf.serverNodeId= nodeId1;
    }
    else if (nodeId == conf.serverNodeId) {
      tr.add_transporter_interface(remoteNodeId, localHostName, server_port);
    }

    DBUG_PRINT("info", ("Transporter between this node %d and node %d using port %d, signalId %d, checksum %d",
               nodeId, remoteNodeId, server_port, sendSignalId, checksum));
    /*
      This may be a dynamic port. It depends on when we're getting
      our configuration. If we've been restarted, we'll be getting
      a configuration with our old dynamic port in it, hence the number
      here is negative (and we try the old port number first).

      On a first-run, server_port will be zero (with dynamic ports)

      If we're not using dynamic ports, we don't do anything.
    */
    if((int)server_port<0)
      server_port= -server_port;

    conf.localNodeId    = nodeId;
    conf.remoteNodeId   = remoteNodeId;
    conf.checksum       = checksum;
    conf.signalId       = sendSignalId;
    conf.port           = server_port;
    conf.localHostName  = localHostName;
    conf.remoteHostName = remoteHostName;

    switch(type){
    case CONNECTION_TYPE_SHM:
      if(iter.get(CFG_SHM_KEY, &conf.shm.shmKey)) break;
      if(iter.get(CFG_SHM_BUFFER_MEM, &conf.shm.shmSize)) break;

      Uint32 tmp;
      if(iter.get(CFG_SHM_SIGNUM, &tmp)) break;
      conf.shm.signum= tmp;

      if(!tr.createSHMTransporter(&conf)){
        DBUG_PRINT("error", ("Failed to create SHM Transporter from %d to %d",
	           conf.localNodeId, conf.remoteNodeId));
	ndbout << "Failed to create SHM Transporter from: "
	       << conf.localNodeId << " to: " << conf.remoteNodeId << endl;
      } else {
	noOfTransportersCreated++;
      }
      DBUG_PRINT("info", ("Created SHM Transporter using shmkey %d, "
			  "buf size = %d", conf.shm.shmKey, conf.shm.shmSize));

      break;

    case CONNECTION_TYPE_SCI:
      if(iter.get(CFG_SCI_SEND_LIMIT, &conf.sci.sendLimit)) break;
      if(iter.get(CFG_SCI_BUFFER_MEM, &conf.sci.bufferSize)) break;
      if (nodeId == nodeId1) {
        if(iter.get(CFG_SCI_HOST2_ID_0, &conf.sci.remoteSciNodeId0)) break;
        if(iter.get(CFG_SCI_HOST2_ID_1, &conf.sci.remoteSciNodeId1)) break;
      } else {
        if(iter.get(CFG_SCI_HOST1_ID_0, &conf.sci.remoteSciNodeId0)) break;
        if(iter.get(CFG_SCI_HOST1_ID_1, &conf.sci.remoteSciNodeId1)) break;
      }
      if (conf.sci.remoteSciNodeId1 == 0) {
        conf.sci.nLocalAdapters = 1;
      } else {
        conf.sci.nLocalAdapters = 2;
      }
     if(!tr.createSCITransporter(&conf)){
        DBUG_PRINT("error", ("Failed to create SCI Transporter from %d to %d",
	           conf.localNodeId, conf.remoteNodeId));
	ndbout << "Failed to create SCI Transporter from: "
	       << conf.localNodeId << " to: " << conf.remoteNodeId << endl;
      } else {
        DBUG_PRINT("info", ("Created SCI Transporter: Adapters = %d, "
			    "remote SCI node id %d",
                   conf.sci.nLocalAdapters, conf.sci.remoteSciNodeId0));
        DBUG_PRINT("info", ("Host 1 = %s, Host 2 = %s, sendLimit = %d, "
			    "buf size = %d", conf.localHostName,
			    conf.remoteHostName, conf.sci.sendLimit,
			    conf.sci.bufferSize));
        if (conf.sci.nLocalAdapters > 1) {
          DBUG_PRINT("info", ("Fault-tolerant with 2 Remote Adapters, "
			      "second remote SCI node id = %d",
			      conf.sci.remoteSciNodeId1));
        }
	noOfTransportersCreated++;
	continue;
      }
     break;

    case CONNECTION_TYPE_TCP:
      if(iter.get(CFG_TCP_SEND_BUFFER_SIZE, &conf.tcp.sendBufferSize)) break;
      if(iter.get(CFG_TCP_RECEIVE_BUFFER_SIZE, &conf.tcp.maxReceiveSize)) break;

      const char * proxy;
      if (!iter.get(CFG_TCP_PROXY, &proxy)) {
	if (strlen(proxy) > 0 && nodeId2 == nodeId) {
	  // TODO handle host:port
	  conf.port = atoi(proxy);
	}
      }

      if(!tr.createTCPTransporter(&conf)){
	ndbout << "Failed to create TCP Transporter from: "
	       << nodeId << " to: " << remoteNodeId << endl;
      } else {
	noOfTransportersCreated++;
      }
      DBUG_PRINT("info", ("Created TCP Transporter: sendBufferSize = %d, "
			  "maxReceiveSize = %d", conf.tcp.sendBufferSize,
			  conf.tcp.maxReceiveSize));
      break;
    case CONNECTION_TYPE_OSE:
      if(iter.get(CFG_OSE_PRIO_A_SIZE, &conf.ose.prioASignalSize)) break;
      if(iter.get(CFG_OSE_PRIO_B_SIZE, &conf.ose.prioBSignalSize)) break;

      if(!tr.createOSETransporter(&conf)){
	ndbout << "Failed to create OSE Transporter from: "
	       << nodeId << " to: " << remoteNodeId << endl;
      } else {
	noOfTransportersCreated++;
      }
      break;

    default:
      ndbout << "Unknown transporter type from: " << nodeId <<
	" to: " << remoteNodeId << endl;
      break;
    } // switch
  } // for

  DBUG_RETURN(noOfTransportersCreated);
}

<|endoftext|>


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

  This source file is part of the Avogadro project.

  Copyright 2017 Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

******************************************************************************/

#include "downloaderwidget.h"
#include "ui_downloaderwidget.h"
#include "zipextracter.h"

#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QStandardPaths>

#include <QtWidgets/QGraphicsRectItem>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QTableWidget>
#include <QtWidgets/QTableWidgetItem>

#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>
#include <QtNetwork/QNetworkRequest>

using json = nlohmann::json;

namespace Avogadro {
namespace QtPlugins {

DownloaderWidget::DownloaderWidget(QWidget* parent)
  : QDialog(parent), m_ui(new Ui::DownloaderWidget)
{
  m_filePath =
    QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
  m_NetworkAccessManager = new QNetworkAccessManager(this);
  m_ui->setupUi(this);
  connect(m_ui->downloadButton, SIGNAL(clicked(bool)), this,
          SLOT(getCheckedRepos()));
  connect(m_ui->repoTable, SIGNAL(cellClicked(int, int)), this,
          SLOT(downloadREADME(int, int)));

  m_ui->repoTable->setColumnCount(4);
  m_ui->repoTable->setSelectionBehavior(QAbstractItemView::SelectRows);
  m_ui->repoTable->setHorizontalHeaderLabels(QStringList() << "Update"
                                                           << "Name"
                                                           << "Description"
                                                           << "Releases");
  m_ui->repoTable->horizontalHeader()->setStretchLastSection(true);

  m_ui->repoTable->setRowCount(0);

  getRepoData();
}

DownloaderWidget::~DownloaderWidget()
{
  delete m_ui;
}

// download master plugin.json from Avogadro.cc
void DownloaderWidget::getRepoData()
{
  QString url = "https://avogadro.cc/plugins.json";
  QNetworkRequest request;
  request.setRawHeader("Accept", "text/html,application/xhtml+xml,application/"
                                 "xml;q=0.9,image/webp,*/*;q=0.8");
  request.setRawHeader("User-Agent",
                       "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                       "AppleWebKit/537.36 (KHTML, like Gecko) "
                       "Chrome/54.0.2840.71 Safari/537.36");
  request.setRawHeader("Accept-Language", "en - US, en; q = 0.8");
  request.setUrl(url); // Set the url
  m_reply = m_NetworkAccessManager->get(request);
  connect(m_reply, SIGNAL(finished()), this, SLOT(updateRepoData()));
}

// Process the master plugin.json hosted on Avogadro.cc
void DownloaderWidget::updateRepoData()
{
  if (m_reply->error() == QNetworkReply::NoError) {
    // Reading the data from the response
    QByteArray bytes = m_reply->readAll();

    // parse the json
    m_root = json::parse(bytes.data());
    int numRepos = m_root.size();
    m_ui->repoTable->setRowCount(numRepos);
    m_repoList.clear();
    for (int i = 0; i < numRepos; i++) {
      m_repoList.push_back(repo());

      const auto& currentRoot = m_root[i];

      // Loop through the keys
      for (auto it = currentRoot.cbegin(); it != currentRoot.cend(); ++it) {
        if (it.key() == "name" && it.value().is_string())
          m_repoList[i].name = it.value().get<std::string>().c_str();
        else if (it.key() == "description" && it.value().is_string())
          m_repoList[i].description = it.value().get<std::string>().c_str();
        else if (it.key() == "release_version" && it.value().is_string())
          m_repoList[i].releaseVersion = it.value().get<std::string>().c_str();
        else if (it.key() == "type" && it.value().is_string())
          m_repoList[i].type = it.value().get<std::string>().c_str();
        else if (it.key() == "updated_at" && it.value().is_string())
          m_repoList[i].updatedAt = it.value().get<std::string>().c_str();
        else if (it.key() == "zipball_url" && it.value().is_string())
          m_repoList[i].zipballUrl = it.value().get<std::string>().c_str();
        else if (it.key() == "has_release" && it.value().is_boolean())
          m_repoList[i].hasRelease = it.value().get<bool>();
      }

      // readme should be included or at least the repo url so we don't have to
      // do this
      QStringList urlParts = m_repoList[i].zipballUrl.split("/");
      urlParts.removeLast();
      urlParts.removeLast(); // remove /zipball/(version/branch)
      urlParts.append("readme");
      QString readmeUrl = urlParts.join("/");

      m_repoList[i].readmeUrl = readmeUrl;
      QTableWidgetItem* checkbox = new QTableWidgetItem();
      checkbox->setCheckState(Qt::Unchecked);
      m_ui->repoTable->setItem(i, 0, checkbox);
      m_ui->repoTable->setItem(i, 1, new QTableWidgetItem(m_repoList[i].name));
      m_ui->repoTable->setItem(i, 2,
                               new QTableWidgetItem(m_repoList[i].description));
      if (m_repoList[i].hasRelease)
        m_ui->repoTable->setItem(
          i, 3, new QTableWidgetItem(m_repoList[i].releaseVersion));
      else
        m_ui->repoTable->setItem(i, 3,
                                 new QTableWidgetItem(m_repoList[i].updatedAt));
    }
  }
  m_reply->deleteLater();
}

// Grab README data from Github
void DownloaderWidget::downloadREADME(int row, int col)
{
  m_ui->readmeBrowser->clear();
  QString url = m_repoList[row].readmeUrl;
  QNetworkRequest request;
  request.setRawHeader("Accept", "text/html,application/xhtml+xml,application/"
                                 "xml;q=0.9,image/webp,*/*;q=0.8");
  request.setRawHeader("User-Agent",
                       "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                       "AppleWebKit/537.36 (KHTML, like Gecko) "
                       "Chrome/54.0.2840.71 Safari/537.36");
  request.setRawHeader("Accept-Language", "en - US, en; q = 0.8");
  request.setUrl(url); // Set the url

  m_reply = m_NetworkAccessManager->get(request);
  connect(m_reply, SIGNAL(finished()), this, SLOT(showREADME()));
}

// display README when the user clicks a row
void DownloaderWidget::showREADME()
{
  if (m_reply->error() == QNetworkReply::NoError) {
    // Reading the data from the response
    QByteArray bytes = m_reply->readAll();

    // parse the json
    m_root = json::parse(bytes.data());

    QByteArray content("ERROR");
    if (m_root.find("content") != m_root.end() &&
        m_root["content"].is_string()) {
      content = m_root["content"].get<std::string>().c_str();
    }
    m_ui->readmeBrowser->append(QByteArray::fromBase64(content).data());
  }
}

// see which repositories the user checked
void DownloaderWidget::getCheckedRepos()
{
  m_ui->readmeBrowser->clear();
  m_downloadList.clear();
  for (size_t i = 0; i < m_repoList.size(); i++) {
    if (m_ui->repoTable->item(i, 0)->checkState() == Qt::Checked) {
      downloadEntry newEntry;
      newEntry.url = m_repoList[i].zipballUrl;
      newEntry.name = m_repoList[i].name;
      newEntry.type = m_repoList[i].type;
      m_downloadList.append(newEntry);
    }
  }
  downloadNext();
}

// Used to download one zip at a time so we know which plugin data we're getting
void DownloaderWidget::downloadNext()
{
  if (!m_downloadList.isEmpty()) {
    QString url = m_downloadList.last().url;
    QNetworkRequest request;
    request.setRawHeader("Accept",
                         "text/html,application/xhtml+xml,application/"
                         "xml;q=0.9,image/webp,*/*;q=0.8");
    request.setRawHeader("User-Agent",
                         "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                         "AppleWebKit/537.36 (KHTML, like Gecko) "
                         "Chrome/54.0.2840.71 Safari/537.36");
    request.setRawHeader("Accept-Language", "en - US, en; q = 0.8");
    request.setUrl(url); // Set the url

    m_reply = m_NetworkAccessManager->get(request);
    connect(m_reply, SIGNAL(finished()), this, SLOT(handleRedirect()));
  }
}

// The download url for Github is always a redirect to the actual zip
void DownloaderWidget::handleRedirect()
{
  if (m_reply->error() == QNetworkReply::NoError) {
    QVariant statusCode =
      m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
    if (statusCode.toInt() == 302) {
      QVariant possibleRedirectUrl =
        m_reply->attribute(QNetworkRequest::RedirectionTargetAttribute);

      QUrl _urlRedirectedTo = possibleRedirectUrl.toUrl();

      QNetworkRequest request;
      request.setRawHeader("Accept",
                           "text/html,application/xhtml+xml,application/"
                           "xml;q=0.9,image/webp,*/*;q=0.8");
      request.setRawHeader("User-Agent",
                           "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                           "AppleWebKit/537.36 (KHTML, like Gecko) "
                           "Chrome/54.0.2840.71 Safari/537.36");
      request.setRawHeader("Accept-Language", "en - US, en; q = 0.8");
      request.setUrl(_urlRedirectedTo); // Set the url
      m_reply = m_NetworkAccessManager->get(request);
      connect(m_reply, SIGNAL(finished()), this, SLOT(unzipPlugin()));
    }
  } else {
    m_reply->deleteLater();
    m_downloadList.removeLast();
    downloadNext();
  }
}

// Save and unzip the plugin zipball
void DownloaderWidget::unzipPlugin()
{
  if (m_reply->error() == QNetworkReply::NoError) {
    // done with redirect
    QByteArray fileData = m_reply->readAll();
    QDir().mkpath(m_filePath);
    QString repoName = m_downloadList.last().name;
    QString filename = repoName + ".zip";

    QString absolutePath = m_filePath + "/" + filename;
    QString extractdirectory;
    QString subdir = m_downloadList.last().type;

    extractdirectory = m_filePath + "/" + subdir + "/";

    QDir().mkpath(extractdirectory);

    m_ui->readmeBrowser->append("\nDownloading " + filename + " to " +
                                m_filePath);

    QFile out(absolutePath);
    out.open(QIODevice::WriteOnly);
    QDataStream outstr(&out);
    outstr << fileData;

    std::string extractdir = extractdirectory.toStdString();
    std::string absolutep = absolutePath.toStdString();

    ZipExtracter unzip;

    m_ui->readmeBrowser->append("Extracting " + absolutePath + " to " +
                                extractdirectory);
    QList<QString> ret = unzip.extract(extractdir, absolutep);

    if (ret.empty()) {
      m_ui->readmeBrowser->append("Extraction successful");
    } else {
      m_ui->readmeBrowser->append("Error while extracting: " + ret.first());
    }

    out.remove();
    m_reply->deleteLater();
    m_downloadList.removeLast();
    downloadNext();
  }
}

} // namespace QtPlugins
} // namespace Avogadro
<commit_msg>In Qt 5.14 and newer, use Markdown native rendering<commit_after>/******************************************************************************

  This source file is part of the Avogadro project.

  Copyright 2017 Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

******************************************************************************/

#include "downloaderwidget.h"
#include "ui_downloaderwidget.h"
#include "zipextracter.h"

#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QStandardPaths>

#include <QtWidgets/QGraphicsRectItem>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QTableWidget>
#include <QtWidgets/QTableWidgetItem>

#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>
#include <QtNetwork/QNetworkRequest>

using json = nlohmann::json;

namespace Avogadro {
namespace QtPlugins {

DownloaderWidget::DownloaderWidget(QWidget* parent)
  : QDialog(parent), m_ui(new Ui::DownloaderWidget)
{
  m_filePath =
    QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
  m_NetworkAccessManager = new QNetworkAccessManager(this);
  m_ui->setupUi(this);
  connect(m_ui->downloadButton, SIGNAL(clicked(bool)), this,
          SLOT(getCheckedRepos()));
  connect(m_ui->repoTable, SIGNAL(cellClicked(int, int)), this,
          SLOT(downloadREADME(int, int)));

  m_ui->repoTable->setColumnCount(4);
  m_ui->repoTable->setSelectionBehavior(QAbstractItemView::SelectRows);
  m_ui->repoTable->setHorizontalHeaderLabels(QStringList() << "Update"
                                                           << "Name"
                                                           << "Description"
                                                           << "Releases");
  m_ui->repoTable->horizontalHeader()->setStretchLastSection(true);

  m_ui->repoTable->setRowCount(0);

  getRepoData();
}

DownloaderWidget::~DownloaderWidget()
{
  delete m_ui;
}

// download master plugin.json from Avogadro.cc
void DownloaderWidget::getRepoData()
{
  QString url = "https://avogadro.cc/plugins.json";
  QNetworkRequest request;
  request.setRawHeader("Accept", "text/html,application/xhtml+xml,application/"
                                 "xml;q=0.9,image/webp,*/*;q=0.8");
  request.setRawHeader("User-Agent",
                       "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                       "AppleWebKit/537.36 (KHTML, like Gecko) "
                       "Chrome/54.0.2840.71 Safari/537.36");
  request.setRawHeader("Accept-Language", "en - US, en; q = 0.8");
  request.setUrl(url); // Set the url
  m_reply = m_NetworkAccessManager->get(request);
  connect(m_reply, SIGNAL(finished()), this, SLOT(updateRepoData()));
}

// Process the master plugin.json hosted on Avogadro.cc
void DownloaderWidget::updateRepoData()
{
  if (m_reply->error() == QNetworkReply::NoError) {
    // Reading the data from the response
    QByteArray bytes = m_reply->readAll();

    // parse the json
    m_root = json::parse(bytes.data());
    int numRepos = m_root.size();
    m_ui->repoTable->setRowCount(numRepos);
    m_repoList.clear();
    for (int i = 0; i < numRepos; i++) {
      m_repoList.push_back(repo());

      const auto& currentRoot = m_root[i];

      // Loop through the keys
      for (auto it = currentRoot.cbegin(); it != currentRoot.cend(); ++it) {
        if (it.key() == "name" && it.value().is_string())
          m_repoList[i].name = it.value().get<std::string>().c_str();
        else if (it.key() == "description" && it.value().is_string())
          m_repoList[i].description = it.value().get<std::string>().c_str();
        else if (it.key() == "release_version" && it.value().is_string())
          m_repoList[i].releaseVersion = it.value().get<std::string>().c_str();
        else if (it.key() == "type" && it.value().is_string())
          m_repoList[i].type = it.value().get<std::string>().c_str();
        else if (it.key() == "updated_at" && it.value().is_string())
          m_repoList[i].updatedAt = it.value().get<std::string>().c_str();
        else if (it.key() == "zipball_url" && it.value().is_string())
          m_repoList[i].zipballUrl = it.value().get<std::string>().c_str();
        else if (it.key() == "has_release" && it.value().is_boolean())
          m_repoList[i].hasRelease = it.value().get<bool>();
      }

      // readme should be included or at least the repo url so we don't have to
      // do this
      QStringList urlParts = m_repoList[i].zipballUrl.split("/");
      urlParts.removeLast();
      urlParts.removeLast(); // remove /zipball/(version/branch)
      urlParts.append("readme");
      QString readmeUrl = urlParts.join("/");

      m_repoList[i].readmeUrl = readmeUrl;
      QTableWidgetItem* checkbox = new QTableWidgetItem();
      checkbox->setCheckState(Qt::Unchecked);
      m_ui->repoTable->setItem(i, 0, checkbox);
      m_ui->repoTable->setItem(i, 1, new QTableWidgetItem(m_repoList[i].name));
      m_ui->repoTable->setItem(i, 2,
                               new QTableWidgetItem(m_repoList[i].description));
      if (m_repoList[i].hasRelease)
        m_ui->repoTable->setItem(
          i, 3, new QTableWidgetItem(m_repoList[i].releaseVersion));
      else
        m_ui->repoTable->setItem(i, 3,
                                 new QTableWidgetItem(m_repoList[i].updatedAt));
    }
  }
  m_reply->deleteLater();
}

// Grab README data from Github
void DownloaderWidget::downloadREADME(int row, int col)
{
  m_ui->readmeBrowser->clear();
  QString url = m_repoList[row].readmeUrl;
  QNetworkRequest request;
  request.setRawHeader("Accept", "text/html,application/xhtml+xml,application/"
                                 "xml;q=0.9,image/webp,*/*;q=0.8");
  request.setRawHeader("User-Agent",
                       "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                       "AppleWebKit/537.36 (KHTML, like Gecko) "
                       "Chrome/54.0.2840.71 Safari/537.36");
  request.setRawHeader("Accept-Language", "en - US, en; q = 0.8");
  request.setUrl(url); // Set the url

  m_reply = m_NetworkAccessManager->get(request);
  connect(m_reply, SIGNAL(finished()), this, SLOT(showREADME()));
}

// display README when the user clicks a row
void DownloaderWidget::showREADME()
{
  if (m_reply->error() == QNetworkReply::NoError) {
    // Reading the data from the response
    QByteArray bytes = m_reply->readAll();

    // parse the json
    m_root = json::parse(bytes.data());

    QByteArray content("ERROR");
    if (m_root.find("content") != m_root.end() &&
        m_root["content"].is_string()) {
      content = m_root["content"].get<std::string>().c_str();
    }

#if QT_VERSION >= 0x050E00
    m_ui->readmeBrowser->setMarkdown(QByteArray::fromBase64(content).data());
#else
    m_ui->readmeBrowser->append(QByteArray::fromBase64(content).data());
#endif
  }
}

// see which repositories the user checked
void DownloaderWidget::getCheckedRepos()
{
  m_ui->readmeBrowser->clear();
  m_downloadList.clear();
  for (size_t i = 0; i < m_repoList.size(); i++) {
    if (m_ui->repoTable->item(i, 0)->checkState() == Qt::Checked) {
      downloadEntry newEntry;
      newEntry.url = m_repoList[i].zipballUrl;
      newEntry.name = m_repoList[i].name;
      newEntry.type = m_repoList[i].type;
      m_downloadList.append(newEntry);
    }
  }
  downloadNext();
}

// Used to download one zip at a time so we know which plugin data we're getting
void DownloaderWidget::downloadNext()
{
  if (!m_downloadList.isEmpty()) {
    QString url = m_downloadList.last().url;
    QNetworkRequest request;
    request.setRawHeader("Accept",
                         "text/html,application/xhtml+xml,application/"
                         "xml;q=0.9,image/webp,*/*;q=0.8");
    request.setRawHeader("User-Agent",
                         "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                         "AppleWebKit/537.36 (KHTML, like Gecko) "
                         "Chrome/54.0.2840.71 Safari/537.36");
    request.setRawHeader("Accept-Language", "en - US, en; q = 0.8");
    request.setUrl(url); // Set the url

    m_reply = m_NetworkAccessManager->get(request);
    connect(m_reply, SIGNAL(finished()), this, SLOT(handleRedirect()));
  }
}

// The download url for Github is always a redirect to the actual zip
void DownloaderWidget::handleRedirect()
{
  if (m_reply->error() == QNetworkReply::NoError) {
    QVariant statusCode =
      m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
    if (statusCode.toInt() == 302) {
      QVariant possibleRedirectUrl =
        m_reply->attribute(QNetworkRequest::RedirectionTargetAttribute);

      QUrl _urlRedirectedTo = possibleRedirectUrl.toUrl();

      QNetworkRequest request;
      request.setRawHeader("Accept",
                           "text/html,application/xhtml+xml,application/"
                           "xml;q=0.9,image/webp,*/*;q=0.8");
      request.setRawHeader("User-Agent",
                           "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                           "AppleWebKit/537.36 (KHTML, like Gecko) "
                           "Chrome/54.0.2840.71 Safari/537.36");
      request.setRawHeader("Accept-Language", "en - US, en; q = 0.8");
      request.setUrl(_urlRedirectedTo); // Set the url
      m_reply = m_NetworkAccessManager->get(request);
      connect(m_reply, SIGNAL(finished()), this, SLOT(unzipPlugin()));
    }
  } else {
    m_reply->deleteLater();
    m_downloadList.removeLast();
    downloadNext();
  }
}

// Save and unzip the plugin zipball
void DownloaderWidget::unzipPlugin()
{
  if (m_reply->error() == QNetworkReply::NoError) {
    // done with redirect
    QByteArray fileData = m_reply->readAll();
    QDir().mkpath(m_filePath);
    QString repoName = m_downloadList.last().name;
    QString filename = repoName + ".zip";

    QString absolutePath = m_filePath + "/" + filename;
    QString extractdirectory;
    QString subdir = m_downloadList.last().type;

    extractdirectory = m_filePath + "/" + subdir + "/";

    QDir().mkpath(extractdirectory);

    m_ui->readmeBrowser->append("\nDownloading " + filename + " to " +
                                m_filePath);

    QFile out(absolutePath);
    out.open(QIODevice::WriteOnly);
    QDataStream outstr(&out);
    outstr << fileData;

    std::string extractdir = extractdirectory.toStdString();
    std::string absolutep = absolutePath.toStdString();

    ZipExtracter unzip;

    m_ui->readmeBrowser->append("Extracting " + absolutePath + " to " +
                                extractdirectory);
    QList<QString> ret = unzip.extract(extractdir, absolutep);

    if (ret.empty()) {
      m_ui->readmeBrowser->append("Extraction successful");
    } else {
      m_ui->readmeBrowser->append("Error while extracting: " + ret.first());
    }

    out.remove();
    m_reply->deleteLater();
    m_downloadList.removeLast();
    downloadNext();
  }
}

} // namespace QtPlugins
} // namespace Avogadro
<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2009 Torus Knot Software Ltd

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 "OgreStableHeaders.h"
#include "OgreViewport.h"

#include "OgreLogManager.h"
#include "OgreRenderTarget.h"
#include "OgreCamera.h"
#include "OgreMath.h"
#include "OgreRoot.h"
#include "OgreMaterialManager.h"
#include "OgreRenderSystem.h"
#include "OgreRenderWindow.h"

namespace Ogre {
    //---------------------------------------------------------------------
    Viewport::Viewport(Camera* cam, RenderTarget* target, Real left, Real top, Real width, Real height, int ZOrder)
        : mCamera(cam)
        , mTarget(target)
        , mRelLeft(left)
        , mRelTop(top)
        , mRelWidth(width)
        , mRelHeight(height)
        // Actual dimensions will update later
        , mZOrder(ZOrder)
        , mOrientation(OR_PORTRAIT)
        , mBackColour(ColourValue::Black)
        , mClearEveryFrame(true)
		, mClearBuffers(FBT_COLOUR | FBT_DEPTH)
        , mUpdated(false)
        , mShowOverlays(true)
        , mShowSkies(true)
		, mShowShadows(true)
		, mVisibilityMask(0xFFFFFFFF)
		, mRQSequence(0)
		, mMaterialSchemeName(MaterialManager::DEFAULT_SCHEME_NAME)
    {
#if OGRE_COMPILER != OGRE_COMPILER_GCCE
		LogManager::getSingleton().stream(LML_TRIVIAL)
			<< "Creating viewport on target '" << target->getName() << "'"
			<< ", rendering from camera '" << (cam != 0 ? cam->getName() : "NULL") << "'"
			<< ", relative dimensions "	<< std::ios::fixed << std::setprecision(2)
			<< "L: " << left << " T: " << top << " W: " << width << " H: " << height
			<< " ZOrder: " << ZOrder;
#endif

        // Calculate actual dimensions
        _updateDimensions();

        // notify camera
        if(cam) cam->_notifyViewport(this);
    }
    //---------------------------------------------------------------------
    Viewport::~Viewport()
    {

    }
    //---------------------------------------------------------------------
    bool Viewport::_isUpdated(void) const
    {
        return mUpdated;
    }
    //---------------------------------------------------------------------
    void Viewport::_clearUpdatedFlag(void)
    {
        mUpdated = false;
    }
    //---------------------------------------------------------------------
    void Viewport::_updateDimensions(void)
    {
        Real height = (Real) mTarget->getHeight();
        Real width = (Real) mTarget->getWidth();

        mActLeft = (int) (mRelLeft * width);
        mActTop = (int) (mRelTop * height);
        mActWidth = (int) (mRelWidth * width);
        mActHeight = (int) (mRelHeight * height);

        // This will check if the cameras getAutoAspectRatio() property is set.
        // If it's true its aspect ratio is fit to the current viewport
        // If it's false the camera remains unchanged.
        // This allows cameras to be used to render to many viewports,
        // which can have their own dimensions and aspect ratios.

        if (mCamera && mCamera->getAutoAspectRatio())
        {
            mCamera->setAspectRatio((Real) mActWidth / (Real) mActHeight);
        }

#if OGRE_COMPILER != OGRE_COMPILER_GCCE
		LogManager::getSingleton().stream(LML_TRIVIAL)
			<< "Viewport for camera '" << (mCamera != 0 ? mCamera->getName() : "NULL") << "'"
			<< ", actual dimensions "	<< std::ios::fixed << std::setprecision(2)
			<< "L: " << mActLeft << " T: " << mActTop << " W: " << mActWidth << " H: " << mActHeight;
#endif

        mUpdated = true;
    }
	//---------------------------------------------------------------------
	int Viewport::getZOrder(void) const
	{
		return mZOrder;
	}
	//---------------------------------------------------------------------
    RenderTarget* Viewport::getTarget(void) const
    {
        return mTarget;
    }
    //---------------------------------------------------------------------
    Camera* Viewport::getCamera(void) const
    {
        return mCamera;
    }
    //---------------------------------------------------------------------
    Real Viewport::getLeft(void) const
    {
        return mRelLeft;
    }
    //---------------------------------------------------------------------
    Real Viewport::getTop(void) const
    {
        return mRelTop;
    }
    //---------------------------------------------------------------------
    Real Viewport::getWidth(void) const
    {
        return mRelWidth;
    }
    //---------------------------------------------------------------------
    Real Viewport::getHeight(void) const
    {
        return mRelHeight;
    }
    //---------------------------------------------------------------------
    int Viewport::getActualLeft(void) const
    {
        return mActLeft;
    }
    //---------------------------------------------------------------------
    int Viewport::getActualTop(void) const
    {
        return mActTop;
    }
    //---------------------------------------------------------------------
    int Viewport::getActualWidth(void) const
    {
        return mActWidth;
    }
    //---------------------------------------------------------------------
    int Viewport::getActualHeight(void) const
    {
        return mActHeight;
    }
    //---------------------------------------------------------------------
    int Viewport::getOrientation(void)
    {
        return mOrientation;
    }
    //---------------------------------------------------------------------
    void Viewport::setOrientation(Orientation orient)
    {
#if OGRE_PLATFORM != OGRE_PLATFORM_IPHONE
        OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED,
                    "Setting Viewport orientation is only supported on iPhone",
                    __FUNCTION__);
#else
        mOrientation = orient;

        // Tell the render window to resize
		RenderWindow* rw = Root::getSingleton().getAutoCreatedWindow();
        rw->changeOrientation(orient);

		// Update the render system config
        RenderSystem* rs = Root::getSingleton().getRenderSystem();
        if(orient == OR_LANDSCAPELEFT)
            rs->setConfigOption("Orientation", "Landscape Left");
        else if(orient == OR_LANDSCAPERIGHT)
            rs->setConfigOption("Orientation", "Landscape Right");
        else if(orient == OR_PORTRAIT)
            rs->setConfigOption("Orientation", "Portrait");
#endif
    }
    //---------------------------------------------------------------------
    void Viewport::setDimensions(Real left, Real top, Real width, Real height)
    {
        mRelLeft = left;
        mRelTop = top;
        mRelWidth = width;
        mRelHeight = height;
        _updateDimensions();
    }
    //---------------------------------------------------------------------
    void Viewport::update(void)
    {
        if (mCamera)
        {
            // Tell Camera to render into me
            mCamera->_renderScene(this, mShowOverlays);
        }
    }
    //---------------------------------------------------------------------
    void Viewport::setBackgroundColour(const ColourValue& colour)
    {
        mBackColour = colour;
    }
    //---------------------------------------------------------------------
    const ColourValue& Viewport::getBackgroundColour(void) const
    {
        return mBackColour;
    }
    //---------------------------------------------------------------------
    void Viewport::setClearEveryFrame(bool clear, unsigned int buffers)
    {
        mClearEveryFrame = clear;
		mClearBuffers = buffers;
    }
    //---------------------------------------------------------------------
    bool Viewport::getClearEveryFrame(void) const
    {
        return mClearEveryFrame;
    }
    //---------------------------------------------------------------------
    unsigned int Viewport::getClearBuffers(void) const
    {
        return mClearBuffers;
    }
    //---------------------------------------------------------------------
	void Viewport::clear(unsigned int buffers, const ColourValue& col,
						 Real depth, unsigned short stencil)
	{
		RenderSystem* rs = Root::getSingleton().getRenderSystem();
		if (rs)
		{
			Viewport* currentvp = rs->_getViewport();
			rs->_setViewport(this);
			rs->clearFrameBuffer(buffers, col, depth, stencil);
			if (currentvp && currentvp != this)
				rs->_setViewport(currentvp);
		}
	}
    //---------------------------------------------------------------------
    void Viewport::getActualDimensions(int &left, int&top, int &width, int &height) const
    {
        left = mActLeft;
        top = mActTop;
        width = mActWidth;
        height = mActHeight;

    }
    //---------------------------------------------------------------------
    unsigned int Viewport::_getNumRenderedFaces(void) const
    {
		return mCamera ? mCamera->_getNumRenderedFaces() : 0;
    }
    //---------------------------------------------------------------------
    unsigned int Viewport::_getNumRenderedBatches(void) const
    {
		return mCamera ? mCamera->_getNumRenderedBatches() : 0;
    }
    //---------------------------------------------------------------------
    void Viewport::setCamera(Camera* cam)
    {
        mCamera = cam;
		_updateDimensions();
		if(cam) mCamera->_notifyViewport(this);
    }
    //---------------------------------------------------------------------
    void Viewport::setOverlaysEnabled(bool enabled)
    {
        mShowOverlays = enabled;
    }
    //---------------------------------------------------------------------
    bool Viewport::getOverlaysEnabled(void) const
    {
        return mShowOverlays;
    }
    //---------------------------------------------------------------------
    void Viewport::setSkiesEnabled(bool enabled)
    {
        mShowSkies = enabled;
    }
    //---------------------------------------------------------------------
    bool Viewport::getSkiesEnabled(void) const
    {
        return mShowSkies;
    }
    //---------------------------------------------------------------------
    void Viewport::setShadowsEnabled(bool enabled)
    {
        mShowShadows = enabled;
    }
    //---------------------------------------------------------------------
    bool Viewport::getShadowsEnabled(void) const
    {
        return mShowShadows;
    }
	//-----------------------------------------------------------------------
	void Viewport::setRenderQueueInvocationSequenceName(const String& sequenceName)
	{
		mRQSequenceName = sequenceName;
		if (mRQSequenceName.empty())
		{
			mRQSequence = 0;
		}
		else
		{
			mRQSequence =
				Root::getSingleton().getRenderQueueInvocationSequence(mRQSequenceName);
		}
	}
	//-----------------------------------------------------------------------
	const String& Viewport::getRenderQueueInvocationSequenceName(void) const
	{
		return mRQSequenceName;
	}
	//-----------------------------------------------------------------------
	RenderQueueInvocationSequence* Viewport::_getRenderQueueInvocationSequence(void)
	{
		return mRQSequence;
	}
	//-----------------------------------------------------------------------

}
<commit_msg>Fix for bug 253: setOrientation crash when not using the auto-created window.<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2009 Torus Knot Software Ltd

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 "OgreStableHeaders.h"
#include "OgreViewport.h"

#include "OgreLogManager.h"
#include "OgreRenderTarget.h"
#include "OgreCamera.h"
#include "OgreMath.h"
#include "OgreRoot.h"
#include "OgreMaterialManager.h"
#include "OgreRenderSystem.h"
#include "OgreRenderWindow.h"

namespace Ogre {
    //---------------------------------------------------------------------
    Viewport::Viewport(Camera* cam, RenderTarget* target, Real left, Real top, Real width, Real height, int ZOrder)
        : mCamera(cam)
        , mTarget(target)
        , mRelLeft(left)
        , mRelTop(top)
        , mRelWidth(width)
        , mRelHeight(height)
        // Actual dimensions will update later
        , mZOrder(ZOrder)
        , mOrientation(OR_PORTRAIT)
        , mBackColour(ColourValue::Black)
        , mClearEveryFrame(true)
		, mClearBuffers(FBT_COLOUR | FBT_DEPTH)
        , mUpdated(false)
        , mShowOverlays(true)
        , mShowSkies(true)
		, mShowShadows(true)
		, mVisibilityMask(0xFFFFFFFF)
		, mRQSequence(0)
		, mMaterialSchemeName(MaterialManager::DEFAULT_SCHEME_NAME)
    {
#if OGRE_COMPILER != OGRE_COMPILER_GCCE
		LogManager::getSingleton().stream(LML_TRIVIAL)
			<< "Creating viewport on target '" << target->getName() << "'"
			<< ", rendering from camera '" << (cam != 0 ? cam->getName() : "NULL") << "'"
			<< ", relative dimensions "	<< std::ios::fixed << std::setprecision(2)
			<< "L: " << left << " T: " << top << " W: " << width << " H: " << height
			<< " ZOrder: " << ZOrder;
#endif

        // Calculate actual dimensions
        _updateDimensions();

        // notify camera
        if(cam) cam->_notifyViewport(this);
    }
    //---------------------------------------------------------------------
    Viewport::~Viewport()
    {

    }
    //---------------------------------------------------------------------
    bool Viewport::_isUpdated(void) const
    {
        return mUpdated;
    }
    //---------------------------------------------------------------------
    void Viewport::_clearUpdatedFlag(void)
    {
        mUpdated = false;
    }
    //---------------------------------------------------------------------
    void Viewport::_updateDimensions(void)
    {
        Real height = (Real) mTarget->getHeight();
        Real width = (Real) mTarget->getWidth();

        mActLeft = (int) (mRelLeft * width);
        mActTop = (int) (mRelTop * height);
        mActWidth = (int) (mRelWidth * width);
        mActHeight = (int) (mRelHeight * height);

        // This will check if the cameras getAutoAspectRatio() property is set.
        // If it's true its aspect ratio is fit to the current viewport
        // If it's false the camera remains unchanged.
        // This allows cameras to be used to render to many viewports,
        // which can have their own dimensions and aspect ratios.

        if (mCamera && mCamera->getAutoAspectRatio())
        {
            mCamera->setAspectRatio((Real) mActWidth / (Real) mActHeight);
        }

#if OGRE_COMPILER != OGRE_COMPILER_GCCE
		LogManager::getSingleton().stream(LML_TRIVIAL)
			<< "Viewport for camera '" << (mCamera != 0 ? mCamera->getName() : "NULL") << "'"
			<< ", actual dimensions "	<< std::ios::fixed << std::setprecision(2)
			<< "L: " << mActLeft << " T: " << mActTop << " W: " << mActWidth << " H: " << mActHeight;
#endif

        mUpdated = true;
    }
	//---------------------------------------------------------------------
	int Viewport::getZOrder(void) const
	{
		return mZOrder;
	}
	//---------------------------------------------------------------------
    RenderTarget* Viewport::getTarget(void) const
    {
        return mTarget;
    }
    //---------------------------------------------------------------------
    Camera* Viewport::getCamera(void) const
    {
        return mCamera;
    }
    //---------------------------------------------------------------------
    Real Viewport::getLeft(void) const
    {
        return mRelLeft;
    }
    //---------------------------------------------------------------------
    Real Viewport::getTop(void) const
    {
        return mRelTop;
    }
    //---------------------------------------------------------------------
    Real Viewport::getWidth(void) const
    {
        return mRelWidth;
    }
    //---------------------------------------------------------------------
    Real Viewport::getHeight(void) const
    {
        return mRelHeight;
    }
    //---------------------------------------------------------------------
    int Viewport::getActualLeft(void) const
    {
        return mActLeft;
    }
    //---------------------------------------------------------------------
    int Viewport::getActualTop(void) const
    {
        return mActTop;
    }
    //---------------------------------------------------------------------
    int Viewport::getActualWidth(void) const
    {
        return mActWidth;
    }
    //---------------------------------------------------------------------
    int Viewport::getActualHeight(void) const
    {
        return mActHeight;
    }
    //---------------------------------------------------------------------
    int Viewport::getOrientation(void)
    {
        return mOrientation;
    }
    //---------------------------------------------------------------------
    void Viewport::setOrientation(Orientation orient)
    {
#if OGRE_PLATFORM != OGRE_PLATFORM_IPHONE
        OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED,
                    "Setting Viewport orientation is only supported on iPhone",
                    __FUNCTION__);
#else
        mOrientation = orient;

        // Tell the render window to resize.  Try to use the auto created window first.
		RenderWindow* rw = Root::getSingleton().getAutoCreatedWindow();
        if(!rw)
        {
            if(!mTarget)
            {
                OGRE_EXCEPT(Exception:: ERR_RENDERINGAPI_ERROR,
                    "This viewport does not have a valid RenderTarget",
                    __FUNCTION__);
            }

            // If there is no auto created window then use this viewport's RenderTarget
            rw = (RenderWindow *)mTarget;
        }
        rw->changeOrientation(orient);

		// Update the render system config
        RenderSystem* rs = Root::getSingleton().getRenderSystem();
        if(orient == OR_LANDSCAPELEFT)
            rs->setConfigOption("Orientation", "Landscape Left");
        else if(orient == OR_LANDSCAPERIGHT)
            rs->setConfigOption("Orientation", "Landscape Right");
        else if(orient == OR_PORTRAIT)
            rs->setConfigOption("Orientation", "Portrait");
#endif
    }
    //---------------------------------------------------------------------
    void Viewport::setDimensions(Real left, Real top, Real width, Real height)
    {
        mRelLeft = left;
        mRelTop = top;
        mRelWidth = width;
        mRelHeight = height;
        _updateDimensions();
    }
    //---------------------------------------------------------------------
    void Viewport::update(void)
    {
        if (mCamera)
        {
            // Tell Camera to render into me
            mCamera->_renderScene(this, mShowOverlays);
        }
    }
    //---------------------------------------------------------------------
    void Viewport::setBackgroundColour(const ColourValue& colour)
    {
        mBackColour = colour;
    }
    //---------------------------------------------------------------------
    const ColourValue& Viewport::getBackgroundColour(void) const
    {
        return mBackColour;
    }
    //---------------------------------------------------------------------
    void Viewport::setClearEveryFrame(bool clear, unsigned int buffers)
    {
        mClearEveryFrame = clear;
		mClearBuffers = buffers;
    }
    //---------------------------------------------------------------------
    bool Viewport::getClearEveryFrame(void) const
    {
        return mClearEveryFrame;
    }
    //---------------------------------------------------------------------
    unsigned int Viewport::getClearBuffers(void) const
    {
        return mClearBuffers;
    }
    //---------------------------------------------------------------------
	void Viewport::clear(unsigned int buffers, const ColourValue& col,
						 Real depth, unsigned short stencil)
	{
		RenderSystem* rs = Root::getSingleton().getRenderSystem();
		if (rs)
		{
			Viewport* currentvp = rs->_getViewport();
			rs->_setViewport(this);
			rs->clearFrameBuffer(buffers, col, depth, stencil);
			if (currentvp && currentvp != this)
				rs->_setViewport(currentvp);
		}
	}
    //---------------------------------------------------------------------
    void Viewport::getActualDimensions(int &left, int&top, int &width, int &height) const
    {
        left = mActLeft;
        top = mActTop;
        width = mActWidth;
        height = mActHeight;

    }
    //---------------------------------------------------------------------
    unsigned int Viewport::_getNumRenderedFaces(void) const
    {
		return mCamera ? mCamera->_getNumRenderedFaces() : 0;
    }
    //---------------------------------------------------------------------
    unsigned int Viewport::_getNumRenderedBatches(void) const
    {
		return mCamera ? mCamera->_getNumRenderedBatches() : 0;
    }
    //---------------------------------------------------------------------
    void Viewport::setCamera(Camera* cam)
    {
        mCamera = cam;
		_updateDimensions();
		if(cam) mCamera->_notifyViewport(this);
    }
    //---------------------------------------------------------------------
    void Viewport::setOverlaysEnabled(bool enabled)
    {
        mShowOverlays = enabled;
    }
    //---------------------------------------------------------------------
    bool Viewport::getOverlaysEnabled(void) const
    {
        return mShowOverlays;
    }
    //---------------------------------------------------------------------
    void Viewport::setSkiesEnabled(bool enabled)
    {
        mShowSkies = enabled;
    }
    //---------------------------------------------------------------------
    bool Viewport::getSkiesEnabled(void) const
    {
        return mShowSkies;
    }
    //---------------------------------------------------------------------
    void Viewport::setShadowsEnabled(bool enabled)
    {
        mShowShadows = enabled;
    }
    //---------------------------------------------------------------------
    bool Viewport::getShadowsEnabled(void) const
    {
        return mShowShadows;
    }
	//-----------------------------------------------------------------------
	void Viewport::setRenderQueueInvocationSequenceName(const String& sequenceName)
	{
		mRQSequenceName = sequenceName;
		if (mRQSequenceName.empty())
		{
			mRQSequence = 0;
		}
		else
		{
			mRQSequence =
				Root::getSingleton().getRenderQueueInvocationSequence(mRQSequenceName);
		}
	}
	//-----------------------------------------------------------------------
	const String& Viewport::getRenderQueueInvocationSequenceName(void) const
	{
		return mRQSequenceName;
	}
	//-----------------------------------------------------------------------
	RenderQueueInvocationSequence* Viewport::_getRenderQueueInvocationSequence(void)
	{
		return mRQSequence;
	}
	//-----------------------------------------------------------------------

}
<|endoftext|>


<commit_before>/*   _____
 * /\  _  \                     __
 * \ \ \_\ \      __    __  __ /\_\
 *  \ \  __ \   /'_ `\ /\ \/\ \\/\ \
 *   \ \ \/\ \ /\ \_\ \\ \ \_\ \\ \ \
 *    \ \_\ \_\\ \____ \\ \____/ \ \_\
 *     \/_/\/_/ \/____\ \\/___/   \/_/
 *                /\____/
 *                \_/__/
 *
 * Copyright (c) 2011 Joshua Larouche
 *
 *
 * License: (BSD)
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name of Agui nor the names of its contributors may
 *    be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "Agui/Backends/Allegro5/Allegro5Image.hpp"

namespace agui
{

	Allegro5Image::Allegro5Image(void)
	: bmp(NULL), width(0), height(0), autoFree(false)
	{
	}

	Allegro5Image::~Allegro5Image(void)
	{
		if(bmp && autoFree)
		{
			al_destroy_bitmap(bmp);
			bmp = NULL;
		}
	}

	Allegro5Image::Allegro5Image( const std::string& fileName, bool convertMask /*= false*/ )
		:autoFree(true)
	{
		bmp = al_load_bitmap(fileName.c_str());
		if(!bmp)
		{
			throw Exception("Agui Allegro 5 Failed to load image " + fileName);
		}
		width = al_get_bitmap_width(bmp);
		height = al_get_bitmap_height(bmp);

		if(bmp && convertMask)
		{
			al_convert_mask_to_alpha(bmp,al_map_rgb(255,0,255));
		}
	}

	int Allegro5Image::getWidth() const
	{
		return width;
	}

	int Allegro5Image::getHeight() const
	{
		return height;
	}

	ALLEGRO_BITMAP* Allegro5Image::getBitmap() const
	{
		return bmp;
	}

	Color Allegro5Image::getPixel( int x, int y ) const
	{
		if(!bmp)
		{
			throw Exception("Cannot obtain the pixel of a NULL image");
		}
		ALLEGRO_COLOR c = al_get_pixel(bmp, x, y);

		unsigned char r,g,b,a;
		al_unmap_rgba(c, &r, &g, &b, &a);

		return Color(r, g, b, a);;
	}

	void Allegro5Image::setPixel( int x, int y, const Color& color )
	{
		if(!bmp)
		{
			throw Exception("Cannot set the pixel of a NULL image");
		}

		ALLEGRO_COLOR c = al_map_rgba(color.getR(),color.getG(),color.getB(),color.getA());
		ALLEGRO_BITMAP* oldBmp = al_get_target_bitmap();

		al_set_target_bitmap(bmp);
		al_put_pixel(x, y, c);
		al_set_target_bitmap(oldBmp);
	}

	bool Allegro5Image::isAutoFreeing() const
	{
		return autoFree;
	}

	void Allegro5Image::free()
	{
			al_destroy_bitmap(bmp);
			bmp = NULL;
	}

	void Allegro5Image::setBitmap( ALLEGRO_BITMAP* bitmap, bool autoFree /*= false*/ )
	{
		if(this->autoFree)
		{
			free();
		}
		bmp = bitmap;
		width = al_get_bitmap_width(bmp);
		height = al_get_bitmap_height(bmp);
		this->autoFree = autoFree;

	}

}
<commit_msg>Applied  damianroyday's change. need to call al_map_rgba_f instead of integer version.<commit_after>/*   _____
 * /\  _  \                     __
 * \ \ \_\ \      __    __  __ /\_\
 *  \ \  __ \   /'_ `\ /\ \/\ \\/\ \
 *   \ \ \/\ \ /\ \_\ \\ \ \_\ \\ \ \
 *    \ \_\ \_\\ \____ \\ \____/ \ \_\
 *     \/_/\/_/ \/____\ \\/___/   \/_/
 *                /\____/
 *                \_/__/
 *
 * Copyright (c) 2011 Joshua Larouche
 *
 *
 * License: (BSD)
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name of Agui nor the names of its contributors may
 *    be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "Agui/Backends/Allegro5/Allegro5Image.hpp"

namespace agui
{

	Allegro5Image::Allegro5Image(void)
	: bmp(NULL), width(0), height(0), autoFree(false)
	{
	}

	Allegro5Image::~Allegro5Image(void)
	{
		if(bmp && autoFree)
		{
			al_destroy_bitmap(bmp);
			bmp = NULL;
		}
	}

	Allegro5Image::Allegro5Image( const std::string& fileName, bool convertMask /*= false*/ )
		:autoFree(true)
	{
		bmp = al_load_bitmap(fileName.c_str());
		if(!bmp)
		{
			throw Exception("Agui Allegro 5 Failed to load image " + fileName);
		}
		width = al_get_bitmap_width(bmp);
		height = al_get_bitmap_height(bmp);

		if(bmp && convertMask)
		{
			al_convert_mask_to_alpha(bmp,al_map_rgb(255,0,255));
		}
	}

	int Allegro5Image::getWidth() const
	{
		return width;
	}

	int Allegro5Image::getHeight() const
	{
		return height;
	}

	ALLEGRO_BITMAP* Allegro5Image::getBitmap() const
	{
		return bmp;
	}

	Color Allegro5Image::getPixel( int x, int y ) const
	{
		if(!bmp)
		{
			throw Exception("Cannot obtain the pixel of a NULL image");
		}
		ALLEGRO_COLOR c = al_get_pixel(bmp, x, y);

		unsigned char r,g,b,a;
		al_unmap_rgba(c, &r, &g, &b, &a);

		return Color(r, g, b, a);;
	}

	void Allegro5Image::setPixel( int x, int y, const Color& color )
	{
		if(!bmp)
		{
			throw Exception("Cannot set the pixel of a NULL image");
		}

		ALLEGRO_COLOR c = al_map_rgba_f(color.getR(),color.getG(),color.getB(),color.getA());
		ALLEGRO_BITMAP* oldBmp = al_get_target_bitmap();

		al_set_target_bitmap(bmp);
		al_put_pixel(x, y, c);
		al_set_target_bitmap(oldBmp);
	}

	bool Allegro5Image::isAutoFreeing() const
	{
		return autoFree;
	}

	void Allegro5Image::free()
	{
			al_destroy_bitmap(bmp);
			bmp = NULL;
	}

	void Allegro5Image::setBitmap( ALLEGRO_BITMAP* bitmap, bool autoFree /*= false*/ )
	{
		if(this->autoFree)
		{
			free();
		}
		bmp = bitmap;
		width = al_get_bitmap_width(bmp);
		height = al_get_bitmap_height(bmp);
		this->autoFree = autoFree;

	}

}
<|endoftext|>


<commit_before><commit_msg>Resolves: #i124453# check if the resulting polygon...<commit_after><|endoftext|>