<commit_before>// @(#)root/proofplayer:$Id$
// Author: Long Tran-Thanh    22/07/07

/*************************************************************************
 * Copyright (C) 1995-2002, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TPacketizerUnit                                                      //
//                                                                      //
// This packetizer generates packets of generic units, representing the //
// number of times an operation cycle has to be repeated by the worker  //
// node, e.g. the number of Monte carlo events to be generated.         //
// Packets sizes are generated taking into account the performance of   //
// worker nodes, based on the time needed to process previous packets.  //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TPacketizerUnit.h"

#include "Riostream.h"
#include "TDSet.h"
#include "TError.h"
#include "TEventList.h"
#include "TMap.h"
#include "TMessage.h"
#include "TMonitor.h"
#include "TNtupleD.h"
#include "TObject.h"
#include "TParameter.h"
#include "TPerfStats.h"
#include "TProofDebug.h"
#include "TProof.h"
#include "TProofPlayer.h"
#include "TProofServ.h"
#include "TSlave.h"
#include "TSocket.h"
#include "TStopwatch.h"
#include "TTimer.h"
#include "TUrl.h"
#include "TClass.h"
#include "TMath.h"
#include "TObjString.h"

using namespace TMath;
//
// The following utility class manage the state of the
// work to be performed and the slaves involved in the process.
//
// The list of TSlaveStat(s) keep track of the work (being) done
// by each slave
//

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

class TPacketizerUnit::TSlaveStat : public TVirtualPacketizer::TVirtualSlaveStat {

friend class TPacketizerUnit;

private:
   Long64_t  fLastProcessed; // number of processed entries of the last packet
   Double_t  fSpeed;         // estimated current average speed of the processing slave
   Double_t  fTimeInstant;   // stores the time instant when the current packet started
   TNtupleD *fCircNtp;       // Keeps circular info for speed calculations
   Long_t    fCircLvl;       // Circularity level

public:
   TSlaveStat(TSlave *sl, TList *input);
   ~TSlaveStat();

   void        GetCurrentTime();

   const char *GetName() const { return fSlave->GetName(); }

   void        UpdatePerformance(Double_t time);
   TProofProgressStatus *AddProcessed(TProofProgressStatus *st);
};

//______________________________________________________________________________
TPacketizerUnit::TSlaveStat::TSlaveStat(TSlave *slave, TList *input)
                            : fLastProcessed(0),
                              fSpeed(0), fTimeInstant(0), fCircLvl(5)
{
   // Main constructor

   // Initialize the circularity ntple for speed calculations
   fCircNtp = new TNtupleD("Speed Circ Ntp", "Circular process info","tm:ev");
   TProof::GetParameter(input, "PROOF_TPacketizerUnitCircularity", fCircLvl);
   fCircLvl = (fCircLvl > 0) ? fCircLvl : 5;
   fCircNtp->SetCircular(fCircLvl);
   fSlave = slave;
   fStatus = new TProofProgressStatus();
}

//______________________________________________________________________________
TPacketizerUnit::TSlaveStat::~TSlaveStat()
{
   // Destructor

   SafeDelete(fCircNtp);
}

//______________________________________________________________________________
void TPacketizerUnit::TSlaveStat::UpdatePerformance(Double_t time)
{
   // Update the circular ntple

   Double_t ttot = time;
   Double_t *ar = fCircNtp->GetArgs();
   Int_t ne = fCircNtp->GetEntries();
   if (ne <= 0) {
      // First call: just fill one ref entry and return
      fCircNtp->Fill(0., 0);
      fSpeed = 0.;
      return;
   }
   // Fill the entry
   fCircNtp->GetEntry(ne-1);
   ttot = ar[0] + time;
   fCircNtp->Fill(ttot, GetEntriesProcessed());

   // Calculate the speed
   fCircNtp->GetEntry(0);
   Double_t dtime = (ttot > ar[0]) ? ttot - ar[0] : ne+1 ;
   Long64_t nevts = GetEntriesProcessed() - (Long64_t)ar[1];
   fSpeed = nevts / dtime;
   PDB(kPacketizer,2)
      Info("UpdatePerformance", "time:%f, dtime:%f, nevts:%lld, speed: %f",
                                time, dtime, nevts, fSpeed);

}

//______________________________________________________________________________
TProofProgressStatus *TPacketizerUnit::TSlaveStat::AddProcessed(TProofProgressStatus *st)
{
   // Update the status info to the 'st'.
   // return the difference (*st - *fStatus)

   if (st) {
      TProofProgressStatus *diff = new TProofProgressStatus(*st - *fStatus);
      *fStatus += *diff;
      return diff;
   } else {
      Error("AddProcessed", "status arg undefined");
      return 0;
   }
}

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

ClassImp(TPacketizerUnit)

//______________________________________________________________________________
TPacketizerUnit::TPacketizerUnit(TList *slaves, Long64_t num, TList *input,
                                 TProofProgressStatus *st)
                : TVirtualPacketizer(input, st)
{
   // Constructor

   PDB(kPacketizer,1) Info("TPacketizerUnit", "enter (num %lld)", num);

   // Init pointer members
   fSlaveStats = 0;
   fPackets = 0;

   fTimeLimit = 1;
   TProof::GetParameter(input, "PROOF_PacketizerTimeLimit", fTimeLimit);
   PDB(kPacketizer,1)
      Info("TPacketizerUnit", "time limit is %lf", fTimeLimit);
   fProcessing = 0;
   fAssigned = 0;

   fStopwatch = new TStopwatch();

   fPackets = new TList;
   fPackets->SetOwner();

   fSlaveStats = new TMap;
   fSlaveStats->SetOwner(kFALSE);

   TSlave *slave;
   TIter si(slaves);
   while ((slave = (TSlave*) si.Next()))
      fSlaveStats->Add(slave, new TSlaveStat(slave, input));

   fTotalEntries = num;

   fStopwatch->Start();
   PDB(kPacketizer,1) Info("TPacketizerUnit", "return");
}

//______________________________________________________________________________
TPacketizerUnit::~TPacketizerUnit()
{
   // Destructor.

   if (fSlaveStats)
      fSlaveStats->DeleteValues();
   SafeDelete(fSlaveStats);
   SafeDelete(fPackets);
   SafeDelete(fStopwatch);
}

//______________________________________________________________________________
Double_t TPacketizerUnit::GetCurrentTime()
{
   // Get current time

   Double_t retValue = fStopwatch->RealTime();
   fStopwatch->Continue();
   return retValue;
}

//______________________________________________________________________________
TDSetElement *TPacketizerUnit::GetNextPacket(TSlave *sl, TMessage *r)
{
   // Get next packet

   if (!fValid)
      return 0;

   // Find slave
   TSlaveStat *slstat = (TSlaveStat*) fSlaveStats->GetValue(sl);
   R__ASSERT(slstat != 0);

   // Update stats & free old element
   Double_t latency, proctime, proccpu;
   Long64_t bytesRead = -1;
   Long64_t totalEntries = -1; // used only to read an old message type
   Long64_t totev = 0;
   Long64_t numev = -1;

   TProofProgressStatus *status = 0;
   if (!gProofServ || gProofServ->GetProtocol() > 18) {
      (*r) >> latency;
      (*r) >> status;

      // Calculate the progress made in the last packet
      TProofProgressStatus *progress = 0;
      if (status) {
         // upadte the worker status
         numev = status->GetEntries() - slstat->GetEntriesProcessed();
         progress = slstat->AddProcessed(status);
         if (progress) {
            // (*fProgressStatus) += *progress;
            proctime = progress->GetProcTime();
            proccpu  = progress->GetCPUTime();
            totev  = status->GetEntries(); // for backward compatibility
            bytesRead  = progress->GetBytesRead();
            delete progress;
         }
         delete status;
      } else
          Error("GetNextPacket", "no status came in the kPROOF_GETPACKET message");
   } else {

      (*r) >> latency >> proctime >> proccpu;

      // only read new info if available
      if (r->BufferSize() > r->Length()) (*r) >> bytesRead;
      if (r->BufferSize() > r->Length()) (*r) >> totalEntries;
      if (r->BufferSize() > r->Length()) (*r) >> totev;

      numev = totev - slstat->GetEntriesProcessed();
      slstat->GetProgressStatus()->IncEntries(numev);
   }

   fProgressStatus->IncEntries(numev);

   PDB(kPacketizer,2)
      Info("GetNextPacket","worker-%s: fAssigned %lld\t", sl->GetOrdinal(), fAssigned);
   fProcessing = 0;

   PDB(kPacketizer,2)
      Info("GetNextPacket","worker-%s (%s): %lld %7.3lf %7.3lf %7.3lf %lld",
                           sl->GetOrdinal(), sl->GetName(),
                           numev, latency, proctime, proccpu, bytesRead);

   if (gPerfStats != 0) {
      gPerfStats->PacketEvent(sl->GetOrdinal(), sl->GetName(), "", numev,
                              latency, proctime, proccpu, bytesRead);
   }

   if (fAssigned == fTotalEntries) {
      // Send last timer message
      HandleTimer(0);
      SafeDelete(fProgress);
   }

   if (fStop) {
      // Send last timer message
      HandleTimer(0);
      return 0;
   }

   Long64_t num;

   // Get the current time
   Double_t cTime = GetCurrentTime();

   if (slstat->fCircNtp->GetEntries() <= 0) {
      // The calibration phase
      PDB(kPacketizer,2) Info("GetNextPacket"," calibration: "
                              "total entries %lld, workers %d",
                              fTotalEntries, fSlaveStats->GetSize());
      Long64_t avg = fTotalEntries/(fSlaveStats->GetSize());
      num = (avg > 5) ? 5 : avg;

      // Create a reference entry
      slstat->UpdatePerformance(0.);

   } else {
      // Schedule tasks for workers based on the currently estimated processing speeds

      // Update performances
      // slstat->fStatus was updated before;
      slstat->UpdatePerformance(proctime);

      TMapIter *iter = (TMapIter *)fSlaveStats->MakeIterator();
      TSlave * tmpSlave;
      TSlaveStat * tmpStat;

      Double_t sumSpeed = 0;
      Double_t sumBusy = 0;

      // The basic idea is to estimate the optimal finishing time for the process, assuming
      // that the currently measured processing speeds of the slaves remain the same in the future.
      // The optTime can be calculated as follows.
      // Let s_i be the speed of worker i. We assume that worker i will be busy in the
      // next b_i time instant. Therefore we have the following equation:
      //                 SUM((optTime-b_i)*s_i) = (remaining_entries),
      // Hence optTime can be calculated easily:
      //                 optTime = ((remaining_entries) + SUM(b_i*s_i))/SUM(s_i)

      while ((tmpSlave = (TSlave *)iter->Next())) {
         tmpStat = (TSlaveStat *)fSlaveStats->GetValue(tmpSlave);
         // If the slave doesn't response for a long time, its service rate will be considered as 0
         if ((cTime - tmpStat->fTimeInstant) > 4*fTimeLimit)
            tmpStat->fSpeed = 0;
         PDB(kPacketizer,2)
            Info("GetNextPacket",
                 "worker-%s: speed %lf", tmpSlave->GetOrdinal(), tmpStat->fSpeed);
         if (tmpStat->fSpeed > 0) {
            // Calculating the SUM(s_i)
            sumSpeed += tmpStat->fSpeed;
            // There is nothing to do if slave_i is not calibrated or slave i is the current slave
            if ((tmpStat->fTimeInstant) && (cTime - tmpStat->fTimeInstant > 0)) {
               // Calculating the SUM(b_i*s_i)
               //      s_i = tmpStat->fSpeed
               //      b_i = tmpStat->fTimeInstant + tmpStat->fLastProcessed/s_i - cTime)
               //  b_i*s_i = (tmpStat->fTimeInstant - cTime)*s_i + tmpStat->fLastProcessed
               Double_t busyspeed =
                  ((tmpStat->fTimeInstant - cTime)*tmpStat->fSpeed + tmpStat->fLastProcessed);
               if (busyspeed > 0)
                  sumBusy += busyspeed;
            }
         }
      }
      PDB(kPacketizer,2)
         Info("GetNextPacket", "worker-%s: sum speed: %lf, sum busy: %f",
                               sl->GetOrdinal(), sumSpeed, sumBusy);
      // firstly the slave will try to get all of the remaining entries
      if (slstat->fSpeed > 0 &&
         (fTotalEntries - fAssigned)/(slstat->fSpeed) < fTimeLimit) {
         num = (fTotalEntries - fAssigned);
      } else {
         if (slstat->fSpeed > 0) {
            // calculating the optTime
            Double_t optTime = (fTotalEntries - fAssigned + sumBusy)/sumSpeed;
            // if optTime is greater than the official time limit, then the slave gets a number
            // of entries that still fit into the time limit, otherwise it uses the optTime as
            // a time limit
            num = (optTime > fTimeLimit) ? Nint(fTimeLimit*(slstat->fSpeed))
                                         : Nint(optTime*(slstat->fSpeed));
           PDB(kPacketizer,2)
              Info("GetNextPacket", "opTime %lf num %lld speed %lf", optTime, num, slstat->fSpeed);
         } else {
            Long64_t avg = fTotalEntries/(fSlaveStats->GetSize());
            num = (avg > 5) ? 5 : avg;
         }
      }
   }
   // Minimum packet size
   num = (num > 1) ? num : 1;
   fProcessing = (num < (fTotalEntries - fAssigned)) ? num
                                                     : (fTotalEntries - fAssigned);

   // Set the informations of the current slave
   slstat->fLastProcessed = fProcessing;
   // Set the start time of the current packet
   slstat->fTimeInstant = cTime;

   PDB(kPacketizer,2)
      Info("GetNextPacket", "worker-%s: num %lld, processing %lld, remaining %lld",sl->GetOrdinal(),
                            num, fProcessing, (fTotalEntries - fAssigned - fProcessing));
   TDSetElement *elem = new TDSetElement("", "", "", 0, fProcessing);
   elem->SetBit(TDSetElement::kEmpty);

   // Update the total counter
   fAssigned += slstat->fLastProcessed;

   return elem;
}
<commit_msg><commit_after>// @(#)root/proofplayer:$Id$
// Author: Long Tran-Thanh    22/07/07

/*************************************************************************
 * Copyright (C) 1995-2002, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TPacketizerUnit                                                      //
//                                                                      //
// This packetizer generates packets of generic units, representing the //
// number of times an operation cycle has to be repeated by the worker  //
// node, e.g. the number of Monte carlo events to be generated.         //
// Packets sizes are generated taking into account the performance of   //
// worker nodes, based on the time needed to process previous packets.  //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TPacketizerUnit.h"

#include "Riostream.h"
#include "TDSet.h"
#include "TError.h"
#include "TEventList.h"
#include "TMap.h"
#include "TMessage.h"
#include "TMonitor.h"
#include "TNtupleD.h"
#include "TObject.h"
#include "TParameter.h"
#include "TPerfStats.h"
#include "TProofDebug.h"
#include "TProof.h"
#include "TProofPlayer.h"
#include "TProofServ.h"
#include "TSlave.h"
#include "TSocket.h"
#include "TStopwatch.h"
#include "TTimer.h"
#include "TUrl.h"
#include "TClass.h"
#include "TMath.h"
#include "TObjString.h"

using namespace TMath;
//
// The following utility class manage the state of the
// work to be performed and the slaves involved in the process.
//
// The list of TSlaveStat(s) keep track of the work (being) done
// by each slave
//

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

class TPacketizerUnit::TSlaveStat : public TVirtualPacketizer::TVirtualSlaveStat {

friend class TPacketizerUnit;

private:
   Long64_t  fLastProcessed; // number of processed entries of the last packet
   Double_t  fSpeed;         // estimated current average speed of the processing slave
   Double_t  fTimeInstant;   // stores the time instant when the current packet started
   TNtupleD *fCircNtp;       // Keeps circular info for speed calculations
   Long_t    fCircLvl;       // Circularity level

public:
   TSlaveStat(TSlave *sl, TList *input);
   ~TSlaveStat();

   void        GetCurrentTime();

   const char *GetName() const { return fSlave->GetName(); }

   void        UpdatePerformance(Double_t time);
   TProofProgressStatus *AddProcessed(TProofProgressStatus *st);
};

//______________________________________________________________________________
TPacketizerUnit::TSlaveStat::TSlaveStat(TSlave *slave, TList *input)
                            : fLastProcessed(0),
                              fSpeed(0), fTimeInstant(0), fCircLvl(5)
{
   // Main constructor

   // Initialize the circularity ntple for speed calculations
   fCircNtp = new TNtupleD("Speed Circ Ntp", "Circular process info","tm:ev");
   TProof::GetParameter(input, "PROOF_TPacketizerUnitCircularity", fCircLvl);
   fCircLvl = (fCircLvl > 0) ? fCircLvl : 5;
   fCircNtp->SetCircular(fCircLvl);
   fSlave = slave;
   fStatus = new TProofProgressStatus();
}

//______________________________________________________________________________
TPacketizerUnit::TSlaveStat::~TSlaveStat()
{
   // Destructor

   SafeDelete(fCircNtp);
}

//______________________________________________________________________________
void TPacketizerUnit::TSlaveStat::UpdatePerformance(Double_t time)
{
   // Update the circular ntple

   Double_t ttot = time;
   Double_t *ar = fCircNtp->GetArgs();
   Int_t ne = fCircNtp->GetEntries();
   if (ne <= 0) {
      // First call: just fill one ref entry and return
      fCircNtp->Fill(0., 0);
      fSpeed = 0.;
      return;
   }
   // Fill the entry
   fCircNtp->GetEntry(ne-1);
   ttot = ar[0] + time;
   fCircNtp->Fill(ttot, GetEntriesProcessed());

   // Calculate the speed
   fCircNtp->GetEntry(0);
   Double_t dtime = (ttot > ar[0]) ? ttot - ar[0] : ne+1 ;
   Long64_t nevts = GetEntriesProcessed() - (Long64_t)ar[1];
   fSpeed = nevts / dtime;
   PDB(kPacketizer,2)
      Info("UpdatePerformance", "time:%f, dtime:%f, nevts:%lld, speed: %f",
                                time, dtime, nevts, fSpeed);

}

//______________________________________________________________________________
TProofProgressStatus *TPacketizerUnit::TSlaveStat::AddProcessed(TProofProgressStatus *st)
{
   // Update the status info to the 'st'.
   // return the difference (*st - *fStatus)

   if (st) {
      TProofProgressStatus *diff = new TProofProgressStatus(*st - *fStatus);
      *fStatus += *diff;
      return diff;
   } else {
      Error("AddProcessed", "status arg undefined");
      return 0;
   }
}

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

ClassImp(TPacketizerUnit)

//______________________________________________________________________________
TPacketizerUnit::TPacketizerUnit(TList *slaves, Long64_t num, TList *input,
                                 TProofProgressStatus *st)
                : TVirtualPacketizer(input, st)
{
   // Constructor

   PDB(kPacketizer,1) Info("TPacketizerUnit", "enter (num %lld)", num);

   // Init pointer members
   fSlaveStats = 0;
   fPackets = 0;

   fTimeLimit = 1;
   TProof::GetParameter(input, "PROOF_PacketizerTimeLimit", fTimeLimit);
   PDB(kPacketizer,1)
      Info("TPacketizerUnit", "time limit is %lf", fTimeLimit);
   fProcessing = 0;
   fAssigned = 0;

   fStopwatch = new TStopwatch();

   fPackets = new TList;
   fPackets->SetOwner();

   fSlaveStats = new TMap;
   fSlaveStats->SetOwner(kFALSE);

   TSlave *slave;
   TIter si(slaves);
   while ((slave = (TSlave*) si.Next()))
      fSlaveStats->Add(slave, new TSlaveStat(slave, input));

   fTotalEntries = num;

   fStopwatch->Start();
   PDB(kPacketizer,1) Info("TPacketizerUnit", "return");
}

//______________________________________________________________________________
TPacketizerUnit::~TPacketizerUnit()
{
   // Destructor.

   if (fSlaveStats)
      fSlaveStats->DeleteValues();
   SafeDelete(fSlaveStats);
   SafeDelete(fPackets);
   SafeDelete(fStopwatch);
}

//______________________________________________________________________________
Double_t TPacketizerUnit::GetCurrentTime()
{
   // Get current time

   Double_t retValue = fStopwatch->RealTime();
   fStopwatch->Continue();
   return retValue;
}

//______________________________________________________________________________
TDSetElement *TPacketizerUnit::GetNextPacket(TSlave *sl, TMessage *r)
{
   // Get next packet

   if (!fValid)
      return 0;

   // Find slave
   TSlaveStat *slstat = (TSlaveStat*) fSlaveStats->GetValue(sl);
   R__ASSERT(slstat != 0);

   PDB(kPacketizer,2)
      Info("GetNextPacket","worker-%s: fAssigned %lld\t", sl->GetOrdinal(), fAssigned);

   // Update stats & free old element
   Double_t latency, proctime, proccpu;
   Long64_t bytesRead = -1;
   Long64_t totalEntries = -1; // used only to read an old message type
   Long64_t totev = 0;
   Long64_t numev = -1;

   TProofProgressStatus *status = 0;
   if (!gProofServ || gProofServ->GetProtocol() > 18) {
      (*r) >> latency;
      (*r) >> status;

      // Calculate the progress made in the last packet
      TProofProgressStatus *progress = 0;
      if (status) {
         // upadte the worker status
         numev = status->GetEntries() - slstat->GetEntriesProcessed();
         progress = slstat->AddProcessed(status);
         if (progress) {
            // (*fProgressStatus) += *progress;
            proctime = progress->GetProcTime();
            proccpu  = progress->GetCPUTime();
            totev  = status->GetEntries(); // for backward compatibility
            bytesRead  = progress->GetBytesRead();
            delete progress;
         }
         delete status;
      } else
          Error("GetNextPacket", "no status came in the kPROOF_GETPACKET message");
   } else {

      (*r) >> latency >> proctime >> proccpu;

      // only read new info if available
      if (r->BufferSize() > r->Length()) (*r) >> bytesRead;
      if (r->BufferSize() > r->Length()) (*r) >> totalEntries;
      if (r->BufferSize() > r->Length()) (*r) >> totev;

      numev = totev - slstat->GetEntriesProcessed();
      slstat->GetProgressStatus()->IncEntries(numev);
   }

   fProgressStatus->IncEntries(numev);

   fProcessing = 0;

   PDB(kPacketizer,2)
      Info("GetNextPacket","worker-%s (%s): %lld %7.3lf %7.3lf %7.3lf %lld",
                           sl->GetOrdinal(), sl->GetName(),
                           numev, latency, proctime, proccpu, bytesRead);

   if (gPerfStats != 0) {
      gPerfStats->PacketEvent(sl->GetOrdinal(), sl->GetName(), "", numev,
                              latency, proctime, proccpu, bytesRead);
   }

   if (fAssigned == fTotalEntries) {
      // Send last timer message
      HandleTimer(0);
      return 0;
   }

   if (fStop) {
      // Send last timer message
      HandleTimer(0);
      return 0;
   }

   Long64_t num;

   // Get the current time
   Double_t cTime = GetCurrentTime();

   if (slstat->fCircNtp->GetEntries() <= 0) {
      // The calibration phase
      PDB(kPacketizer,2) Info("GetNextPacket"," calibration: "
                              "total entries %lld, workers %d",
                              fTotalEntries, fSlaveStats->GetSize());
      Long64_t avg = fTotalEntries/(fSlaveStats->GetSize());
      num = (avg > 5) ? 5 : avg;

      // Create a reference entry
      slstat->UpdatePerformance(0.);

   } else {
      // Schedule tasks for workers based on the currently estimated processing speeds

      // Update performances
      // slstat->fStatus was updated before;
      slstat->UpdatePerformance(proctime);

      TMapIter *iter = (TMapIter *)fSlaveStats->MakeIterator();
      TSlave * tmpSlave;
      TSlaveStat * tmpStat;

      Double_t sumSpeed = 0;
      Double_t sumBusy = 0;

      // The basic idea is to estimate the optimal finishing time for the process, assuming
      // that the currently measured processing speeds of the slaves remain the same in the future.
      // The optTime can be calculated as follows.
      // Let s_i be the speed of worker i. We assume that worker i will be busy in the
      // next b_i time instant. Therefore we have the following equation:
      //                 SUM((optTime-b_i)*s_i) = (remaining_entries),
      // Hence optTime can be calculated easily:
      //                 optTime = ((remaining_entries) + SUM(b_i*s_i))/SUM(s_i)

      while ((tmpSlave = (TSlave *)iter->Next())) {
         tmpStat = (TSlaveStat *)fSlaveStats->GetValue(tmpSlave);
         // If the slave doesn't response for a long time, its service rate will be considered as 0
         if ((cTime - tmpStat->fTimeInstant) > 4*fTimeLimit)
            tmpStat->fSpeed = 0;
         PDB(kPacketizer,2)
            Info("GetNextPacket",
                 "worker-%s: speed %lf", tmpSlave->GetOrdinal(), tmpStat->fSpeed);
         if (tmpStat->fSpeed > 0) {
            // Calculating the SUM(s_i)
            sumSpeed += tmpStat->fSpeed;
            // There is nothing to do if slave_i is not calibrated or slave i is the current slave
            if ((tmpStat->fTimeInstant) && (cTime - tmpStat->fTimeInstant > 0)) {
               // Calculating the SUM(b_i*s_i)
               //      s_i = tmpStat->fSpeed
               //      b_i = tmpStat->fTimeInstant + tmpStat->fLastProcessed/s_i - cTime)
               //  b_i*s_i = (tmpStat->fTimeInstant - cTime)*s_i + tmpStat->fLastProcessed
               Double_t busyspeed =
                  ((tmpStat->fTimeInstant - cTime)*tmpStat->fSpeed + tmpStat->fLastProcessed);
               if (busyspeed > 0)
                  sumBusy += busyspeed;
            }
         }
      }
      PDB(kPacketizer,2)
         Info("GetNextPacket", "worker-%s: sum speed: %lf, sum busy: %f",
                               sl->GetOrdinal(), sumSpeed, sumBusy);
      // firstly the slave will try to get all of the remaining entries
      if (slstat->fSpeed > 0 &&
         (fTotalEntries - fAssigned)/(slstat->fSpeed) < fTimeLimit) {
         num = (fTotalEntries - fAssigned);
      } else {
         if (slstat->fSpeed > 0) {
            // calculating the optTime
            Double_t optTime = (fTotalEntries - fAssigned + sumBusy)/sumSpeed;
            // if optTime is greater than the official time limit, then the slave gets a number
            // of entries that still fit into the time limit, otherwise it uses the optTime as
            // a time limit
            num = (optTime > fTimeLimit) ? Nint(fTimeLimit*(slstat->fSpeed))
                                         : Nint(optTime*(slstat->fSpeed));
           PDB(kPacketizer,2)
              Info("GetNextPacket", "opTime %lf num %lld speed %lf", optTime, num, slstat->fSpeed);
         } else {
            Long64_t avg = fTotalEntries/(fSlaveStats->GetSize());
            num = (avg > 5) ? 5 : avg;
         }
      }
   }
   // Minimum packet size
   num = (num > 1) ? num : 1;
   fProcessing = (num < (fTotalEntries - fAssigned)) ? num
                                                     : (fTotalEntries - fAssigned);

   // Set the informations of the current slave
   slstat->fLastProcessed = fProcessing;
   // Set the start time of the current packet
   slstat->fTimeInstant = cTime;

   PDB(kPacketizer,2)
      Info("GetNextPacket", "worker-%s: num %lld, processing %lld, remaining %lld",sl->GetOrdinal(),
                            num, fProcessing, (fTotalEntries - fAssigned - fProcessing));
   TDSetElement *elem = new TDSetElement("", "", "", 0, fProcessing);
   elem->SetBit(TDSetElement::kEmpty);

   // Update the total counter
   fAssigned += slstat->fLastProcessed;

   return elem;
}
<|endoftext|>


<commit_before>//Author: Julian Yi
//Date Created: 7 August 2017
//File Description: c++ code for the king.
//Fun Fact: Simon Kim is now Simon King
#include <iostream>
#include <string>
#include "king.h"

King::King(coord pos) : Pieces()
{
	type = PieceType::King;
	position = pos;
}

coordList King::calculateMoves(coord boundary, const squareGrid& square) const
{
	coordList validMoves;

	// Create a vector of coords representing the moves of a king.
	// The king can move diagonally and orthogonally.
	coordList moves = {
		// Diagonal unit vectors.
		{ 1, 1 },{ 1, -1 },{ -1, 1 },{ -1, -1 },
		// Orthogonal unit vectors.
		{ 0, 1 },{ 0, -1 },{ 1, 0 },{ -1, 0 },
	};

	for (auto& move : moves)
	{
		coord newPos = position + move;

		validMoves.push_back(newPos);
		newPos = newPos + move;
	}

	return validMoves;

}

<commit_msg>Removed uneeded line.<commit_after>//Author: Julian Yi
//Date Created: 7 August 2017
//File Description: c++ code for the king.
//Fun Fact: Simon Kim is now Simon King
#include <iostream>
#include <string>
#include "king.h"

King::King(coord pos) : Pieces()
{
	type = PieceType::King;
	position = pos;
}

coordList King::calculateMoves(coord boundary, const squareGrid& square) const
{
	coordList validMoves;

	// Create a vector of coords representing the moves of a king.
	// The king can move diagonally and orthogonally.
	coordList moves = {
		// Diagonal unit vectors.
		{ 1, 1 },{ 1, -1 },{ -1, 1 },{ -1, -1 },
		// Orthogonal unit vectors.
		{ 0, 1 },{ 0, -1 },{ 1, 0 },{ -1, 0 },
	};

	for (auto& move : moves)
	{
		coord newPos = position + move;

		validMoves.push_back(newPos);
	}

	return validMoves;

}

<|endoftext|>


<commit_before>#include <sys/socket.h>

#include "utils.h"
#include "cJSON.h"

#include "client_http.h"

//
// Xapian http client
//

HttpClient::HttpClient(ev::loop_ref *loop, int sock_, DatabasePool *database_pool_, double active_timeout_, double idle_timeout_)
	: BaseClient(loop, sock_, database_pool_, active_timeout_, idle_timeout_)
{
	parser.data = this;
	http_parser_init(&parser, HTTP_REQUEST);
	LOG_CONN(this, "Got connection (sock=%d), %d http client(s) connected.\n", sock, ++total_clients);
}

HttpClient::~HttpClient()
{
	total_clients--;
}

void HttpClient::on_read(const char *buf, ssize_t received)
{
	size_t parsed = http_parser_execute(&parser, &settings, buf, received);
	if (parsed == received) {
		if (parser.state == 1 || parser.state == 18) { // dead or message_complete
			try {
				//					LOG_HTTP_PROTO(this, "METHOD: %d\n", parser.method);
				//					LOG_HTTP_PROTO(this, "PATH: '%s'\n", repr(path).c_str());
				//					LOG_HTTP_PROTO(this, "BODY: '%s'\n", repr(body).c_str());

				std::string content;
				cJSON *json = cJSON_Parse(body.c_str());
				cJSON *query = json ? cJSON_GetObjectItem(json, "query") : NULL;
				cJSON *term = query ? cJSON_GetObjectItem(query, "term") : NULL;
				cJSON *text = term ? cJSON_GetObjectItem(term, "text") : NULL;

				cJSON *root = cJSON_CreateObject();
				cJSON *response = cJSON_CreateObject();
				cJSON_AddItemToObject(root, "response", response);
				if (text) {
					cJSON_AddStringToObject(response, "status", "OK");
					cJSON_AddStringToObject(response, "query", text->valuestring);
					cJSON_AddStringToObject(response, "title", "The title");
					cJSON_AddNumberToObject(response, "items", 7);
					const char *strings[7] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
					cJSON *results = cJSON_CreateArray();
					cJSON_AddItemToObject(response, "results", results);
					for (int i = 0; i < 7; i++) {
						cJSON *result = cJSON_CreateObject();
						cJSON_AddNumberToObject(result, "id", i);
						cJSON_AddStringToObject(result, "name", strings[i]);
						cJSON_AddItemToArray(results, result);
					}
				} else {
					LOG_HTTP_PROTO("Error before: [%s]\n", cJSON_GetErrorPtr());
					cJSON_AddStringToObject(response, "status", "ERROR");
					cJSON_AddStringToObject(response, "message", cJSON_GetErrorPtr());
				}
				cJSON_Delete(json);

				char *out = cJSON_Print(root);
				content = out;
				cJSON_Delete(root);
				free(out);

				char tmp[20];
				std::string http_response;
				http_response += "HTTP/";
				sprintf(tmp, "%d.%d", parser.http_major, parser.http_minor);
				http_response += tmp;
				http_response += " 200 OK\r\n";
				http_response += "Content-Type: application/json\r\n";
				http_response += "Content-Length: ";
				sprintf(tmp, "%ld", content.size());
				http_response += tmp;
				http_response += "\r\n";
				write(http_response + "\r\n" + content);
				if (parser.state == 1) close();
			} catch (...) {
				LOG_ERR(this, "ERROR!\n");
			}
		}
	} else {
		enum http_errno err = HTTP_PARSER_ERRNO(&parser);
		const char *desc = http_errno_description(err);
		const char *msg = err != HPE_OK ? desc : "incomplete request";
		LOG_HTTP_PROTO(this, msg);
		// Handle error. Just close the connection.
		destroy();
	}
}

//
// HTTP parser callbacks.
//

const http_parser_settings HttpClient::settings = {
	.on_message_begin = HttpClient::on_info,
	.on_url = HttpClient::on_data,
	.on_status = HttpClient::on_data,
	.on_header_field = HttpClient::on_data,
	.on_header_value = HttpClient::on_data,
	.on_headers_complete = HttpClient::on_info,
	.on_body = HttpClient::on_data,
	.on_message_complete = HttpClient::on_info
};

int HttpClient::on_info(http_parser* p) {
	HttpClient *self = static_cast<HttpClient *>(p->data);

	LOG_HTTP_PROTO_PARSER(self, "%3d. (INFO)\n", p->state);

	switch (p->state) {
		case 18:  // message_complete
			break;
		case 19:  // message_begin
			self->path.clear();
			self->body.clear();
			break;
	}

	return 0;
}

int HttpClient::on_data(http_parser* p, const char *at, size_t length) {
	HttpClient *self = static_cast<HttpClient *>(p->data);

	LOG_HTTP_PROTO_PARSER(self, "%3d. %s\n", p->state, repr(at, length).c_str());

	switch (p->state) {
		case 32: // path
			self->path = std::string(at, length);
			break;
		case 62: // data
			self->body = std::string(at, length);
			break;
	}

	return 0;
}
<commit_msg>Unformatted json returned<commit_after>#include <sys/socket.h>

#include "utils.h"
#include "cJSON.h"

#include "client_http.h"

//
// Xapian http client
//

HttpClient::HttpClient(ev::loop_ref *loop, int sock_, DatabasePool *database_pool_, double active_timeout_, double idle_timeout_)
	: BaseClient(loop, sock_, database_pool_, active_timeout_, idle_timeout_)
{
	parser.data = this;
	http_parser_init(&parser, HTTP_REQUEST);
	LOG_CONN(this, "Got connection (sock=%d), %d http client(s) connected.\n", sock, ++total_clients);
}

HttpClient::~HttpClient()
{
	total_clients--;
}

void HttpClient::on_read(const char *buf, ssize_t received)
{
	size_t parsed = http_parser_execute(&parser, &settings, buf, received);
	if (parsed == received) {
		if (parser.state == 1 || parser.state == 18) { // dead or message_complete
			try {
				//					LOG_HTTP_PROTO(this, "METHOD: %d\n", parser.method);
				//					LOG_HTTP_PROTO(this, "PATH: '%s'\n", repr(path).c_str());
				//					LOG_HTTP_PROTO(this, "BODY: '%s'\n", repr(body).c_str());

				std::string content;
				cJSON *json = cJSON_Parse(body.c_str());
				cJSON *query = json ? cJSON_GetObjectItem(json, "query") : NULL;
				cJSON *term = query ? cJSON_GetObjectItem(query, "term") : NULL;
				cJSON *text = term ? cJSON_GetObjectItem(term, "text") : NULL;

				cJSON *root = cJSON_CreateObject();
				cJSON *response = cJSON_CreateObject();
				cJSON_AddItemToObject(root, "response", response);
				if (text) {
					cJSON_AddStringToObject(response, "status", "OK");
					cJSON_AddStringToObject(response, "query", text->valuestring);
					cJSON_AddStringToObject(response, "title", "The title");
					cJSON_AddNumberToObject(response, "items", 7);
					const char *strings[7] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
					cJSON *results = cJSON_CreateArray();
					cJSON_AddItemToObject(response, "results", results);
					for (int i = 0; i < 7; i++) {
						cJSON *result = cJSON_CreateObject();
						cJSON_AddNumberToObject(result, "id", i);
						cJSON_AddStringToObject(result, "name", strings[i]);
						cJSON_AddItemToArray(results, result);
					}
				} else {
					LOG_HTTP_PROTO("Error before: [%s]\n", cJSON_GetErrorPtr());
					cJSON_AddStringToObject(response, "status", "ERROR");
					cJSON_AddStringToObject(response, "message", cJSON_GetErrorPtr());
				}
				cJSON_Delete(json);

				bool pretty = false;
				char *out;
				if (pretty) {
					out = cJSON_Print(root);
				} else {
					out = cJSON_PrintUnformatted(root);
				}
				content = out;
				cJSON_Delete(root);
				free(out);

				char tmp[20];
				std::string http_response;
				http_response += "HTTP/";
				sprintf(tmp, "%d.%d", parser.http_major, parser.http_minor);
				http_response += tmp;
				http_response += " 200 OK\r\n";
				http_response += "Content-Type: application/json\r\n";
				http_response += "Content-Length: ";
				sprintf(tmp, "%ld", content.size());
				http_response += tmp;
				http_response += "\r\n";
				write(http_response + "\r\n" + content);
				if (parser.state == 1) close();
			} catch (...) {
				LOG_ERR(this, "ERROR!\n");
			}
		}
	} else {
		enum http_errno err = HTTP_PARSER_ERRNO(&parser);
		const char *desc = http_errno_description(err);
		const char *msg = err != HPE_OK ? desc : "incomplete request";
		LOG_HTTP_PROTO(this, msg);
		// Handle error. Just close the connection.
		destroy();
	}
}

//
// HTTP parser callbacks.
//

const http_parser_settings HttpClient::settings = {
	.on_message_begin = HttpClient::on_info,
	.on_url = HttpClient::on_data,
	.on_status = HttpClient::on_data,
	.on_header_field = HttpClient::on_data,
	.on_header_value = HttpClient::on_data,
	.on_headers_complete = HttpClient::on_info,
	.on_body = HttpClient::on_data,
	.on_message_complete = HttpClient::on_info
};

int HttpClient::on_info(http_parser* p) {
	HttpClient *self = static_cast<HttpClient *>(p->data);

	LOG_HTTP_PROTO_PARSER(self, "%3d. (INFO)\n", p->state);

	switch (p->state) {
		case 18:  // message_complete
			break;
		case 19:  // message_begin
			self->path.clear();
			self->body.clear();
			break;
	}

	return 0;
}

int HttpClient::on_data(http_parser* p, const char *at, size_t length) {
	HttpClient *self = static_cast<HttpClient *>(p->data);

	LOG_HTTP_PROTO_PARSER(self, "%3d. %s\n", p->state, repr(at, length).c_str());

	switch (p->state) {
		case 32: // path
			self->path = std::string(at, length);
			break;
		case 62: // data
			self->body = std::string(at, length);
			break;
	}

	return 0;
}
<|endoftext|>


<commit_before>/*
 * deck.cpp
 *
 *  Created on: Mar 13, 2016
 *      Author: Tumblr
 */

#include <iostream>
#include "deck.h"
#include "stdlib.h"

using namespace std;

Deck::Deck()
	:count{0} {
	// TODO Auto-generated constructor stuff
	well_formed();
}

Deck::~Deck() {
	// TODO Auto-generated destructor stuff
}

Deck::Deck(const Deck &clone)
	:count{clone.count} {
	// TODO cloning stuff here
	// passes clone's data to here
	well_formed();
}

Deck* Deck::operator=(const Deck* clone) {
	// do set equals operations here
	// set this equal to the clone
	return this;
}

Deck& Deck::operator=(const Deck &clone) {
	// do set equals operations here
	// set this equal to the clone
	return *this;
}

// removes the top card of the deck and returns it
// shifting all the cards up one
Card* Deck::draw_card() {
	well_formed();
	if(count == 0) return nullptr;
	Card* ret = deck[0];
	for(unsigned int i = 1; i < count; i++)
		deck[i-1] = deck[i];
	well_formed();
	return ret;
}

// removes the top num cards from the deck and returns
// a "Deck" as the drawn cards. shifts all
// the cards up num
Deck Deck::draw_cards(int num) {
    Deck ret;
	if(!well_formed()) return ret;

    // draws a card from our deck to add
    // to the return deck;
    for(int i = 0; i < num; i++)
        ret.add_card(draw_card());

	well_formed();
	return ret;
}

// randomizes the order of the deck
void Deck::shuffle() {
	if(!well_formed()) return;
	// Traverses through the array swapping each index with a random other index
	for(unsigned int i = 0; i < count; i++) {
		unsigned int r = rand() % count;
		Card* temp;
		temp = deck[i];
		deck[i] = deck[r];
		deck[r] = temp;
	}
	well_formed();
}

// adds a card to the deck and then shuffles the deck
bool Deck::add_card(Card* card) {
	return well_formed();

	// no room to add the card
	if(count == 20) return print_err("No more room to add a card.");

	// adds the card and increments count
	card[count++] = *card;
	cout << card->to_string() << " has been added." << endl;
	shuffle();

	well_formed();
}

// adds a card at the specified index. i.e 0 for the top
bool Deck::add_card(Card* card, unsigned int index) {
	return well_formed();

	// index can not be larger than count
	if(index >= count - 1) return print_err("Index is out of bounds.");

	// no room to add the card
	if(count == 20) return false;

	// moves all the cards after index down one
	for(unsigned int i = count - 1; i > index; i--) {
		deck[i + 1] = deck[i];
	}

	// puts the deck in at index and increments count
	deck[index] = card;
	count++;

	well_formed();
	return true;
}

unsigned int Deck::size() {
	return count;
}

// checks the integrity of the deck and returns false with an error message
// if something is wrong. Returns true otherwise.
// Rules:
//		A Deck may not be larger than 20 cards
//		A deck may not have any nullptr between 0 and count
bool Deck::well_formed() {
	// may not be larger than 60 cards
	if(count > deck.size()) return print_err("Count is larger than 20");
	for(unsigned int i = 0; i < count; i++) {

		// checks to make sure count is not larger than the size of the deck
		if(deck[i] == nullptr) return print_err("Count is larger than size of deck");
		int cardCount = 1;
		for(unsigned int j = i + 1; j < count; j++) {

			// adding it here checks the integrity of the array on our first pass
			if(deck[i] == nullptr) return print_err("Count is larger than size of deck");
			Card c1 = *deck[i];
			Card c2 = *deck[j];
			if(c1.get_name() == c2.get_name()) cardCount++;

			// you may not have more than 4 of any card in a deck
			//if(cardCount > 2) return print_err("You may not have more than 2 of any card");
		}
	}

	// if the integrity of this data structure is held, returns true
	return true;
}

// prints the error message passed and returns false
bool Deck::print_err(string err) {
	cout << err << endl;
	return false;
}

string Deck::to_string() {
	string ret = "TESTING";
	for(unsigned int i = 0; i < count; i++) {
		ret += deck[i]->to_string();
		ret += "TESTING";
	}
	return ret;
}
<commit_msg>solved issue with cards not getting added<commit_after>/*
 * deck.cpp
 *
 *  Created on: Mar 13, 2016
 *      Author: Tumblr
 */

#include <iostream>
#include "deck.h"
#include "stdlib.h"

using namespace std;

Deck::Deck()
	:count{0} {
	// TODO Auto-generated constructor stuff
	well_formed();
}

Deck::~Deck() {
	// TODO Auto-generated destructor stuff
}

Deck::Deck(const Deck &clone)
	:count{clone.count} {
	// TODO cloning stuff here
	// passes clone's data to here
	well_formed();
}

Deck* Deck::operator=(const Deck* clone) {
	// do set equals operations here
	// set this equal to the clone
	return this;
}

Deck& Deck::operator=(const Deck &clone) {
	// do set equals operations here
	// set this equal to the clone
	return *this;
}

// removes the top card of the deck and returns it
// shifting all the cards up one
Card* Deck::draw_card() {
	well_formed();
	if(count == 0) return nullptr;
	Card* ret = deck[0];
	for(unsigned int i = 1; i < count; i++)
		deck[i-1] = deck[i];
	well_formed();
	return ret;
}

// removes the top num cards from the deck and returns
// a "Deck" as the drawn cards. shifts all
// the cards up num
Deck Deck::draw_cards(int num) {
    Deck ret;
	if(!well_formed()) return ret;

    // draws a card from our deck to add
    // to the return deck;
    for(int i = 0; i < num; i++)
        ret.add_card(draw_card());

	well_formed();
	return ret;
}

// randomizes the order of the deck
void Deck::shuffle() {
	if(!well_formed()) return;

	// Traverses through the array swapping each index with a random other index
	for(unsigned int i = 0; i < count; i++) {
		unsigned int r = rand() % count;
		Card* temp;
		temp = deck[i];
		deck[i] = deck[r];
		deck[r] = temp;
	}

	well_formed();
}

// adds a card to the deck and then shuffles the deck
bool Deck::add_card(Card* card) {
	if(!well_formed()) return false;

	// no room to add the card
	if(count == 20) return print_err("No more room to add a card.");

	// adds the card and increments count
	card[count++] = *card;
	cout << card->to_string() << " has been added." << endl;
	shuffle();

	return well_formed();
}

// adds a card at the specified index. i.e 0 for the top
bool Deck::add_card(Card* card, unsigned int index) {
	if(!well_formed()) return false;

	// index can not be larger than count
	if(index >= count - 1) return print_err("Index is out of bounds.");

	// no room to add the card
	if(count == 20) return false;

	// moves all the cards after index down one
	for(unsigned int i = count - 1; i > index; i--) {
		deck[i + 1] = deck[i];
	}

	// puts the deck in at index and increments count
	deck[index] = card;
	count++;

	well_formed();
	return true;
}

unsigned int Deck::size() {
	return count;
}

// checks the integrity of the deck and returns false with an error message
// if something is wrong. Returns true otherwise.
// Rules:
//		A Deck may not be larger than 20 cards
//		A deck may not have any nullptr between 0 and count
bool Deck::well_formed() {
	// may not be larger than 60 cards
	if(count > deck.size()) return print_err("Count is larger than 20");
	for(unsigned int i = 0; i < count; i++) {
		// checks to make sure count is not larger than the size of the deck
		if(deck[i] == nullptr) return print_err("Count is larger than size of deck");
		int cardCount = 1;
		for(unsigned int j = i + 1; j < count; j++) {

			// adding it here checks the integrity of the array on our first pass
			if(deck[i] == nullptr) return print_err("Count is larger than size of deck");
			Card c1 = *deck[i];
			Card c2 = *deck[j];
			if(c1.get_name() == c2.get_name()) cardCount++;

			// you may not have more than 2 of any card in a deck
			//if(cardCount > 2) return print_err("You may not have more than 2 of any card");
		}
	}

	// if the integrity of this data structure is held, returns true
	return true;
}

// prints the error message passed and returns false
bool Deck::print_err(string err) {
	cout << err << endl;
	return false;
}

string Deck::to_string() {
    string ret;
	for(unsigned int i = 0; i < count; i++) {
		ret += deck[i]->to_string();

	}
	return ret;
}
<|endoftext|>


<commit_before>#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent) : QWidget(parent)
{

}
<commit_msg>delte mainwindow cpp<commit_after><|endoftext|>


<commit_before>#include "engine/dukmathbindings.h"

#include <string>
#include <core/sol.h>

#include "core/vec2.h"

#include "core/sol.h"

namespace euphoria::engine
{

    template <typename T>
    void
    bind_vec2(Sol* sol, const std::string& name)
    {
        using V = core::vec2<T>;

        sol->lua.new_usertype<V>
        (
            name,
            sol::constructors<V(T, T)>(),
            "x", &V::x,
            "y", &V::y
        );
    }

    void
    bind_math(Sol* duk)
    {
        bind_vec2<float>(duk, "vec2f");
        // bind_vec2<int>(duk, "vec2i");
    }

}
<commit_msg>removed more lua/sol warnings<commit_after>#include "engine/dukmathbindings.h"

#include <string>

#include "core/cint.h"
#include "core/vec2.h"
#include "core/sol.h"

namespace euphoria::engine
{

    template <typename T>
    void
    bind_vec2(Sol* sol, const std::string& name)
    {
        using V = core::vec2<T>;

        sol::usertype<V> t = sol->lua.new_usertype<V>
        (
            name,
            sol::constructors<V(T, T)>()
        );

        t["x"] = sol::property
        (
            [](const V& v) -> double
            {
                return core::c_float_to_double(v.x);
            },
            [](V& v, double x)
            {
                v.x = core::c_double_to_float(x);
            }
        );

        t["y"] = sol::property
        (
            [](const V& v) -> double
            {
                return core::c_float_to_double(v.y);
            },
            [](V& v, double y)
            {
                v.y = core::c_double_to_float(y);
            }
        );
    }

    void
    bind_math(Sol* duk)
    {
        bind_vec2<float>(duk, "vec2f");
        // bind_vec2<int>(duk, "vec2i");
    }

}
<|endoftext|>


<commit_before>#include <node.h>
#include <node_buffer.h>
#include <nan.h>
#include <string.h>
#include <stdlib.h>

#ifdef _WIN32
# include <io.h>
# include <fcntl.h>
# include <wchar.h>
#endif

#include "magic.h"

using namespace node;
using namespace v8;

struct Baton {
  uv_work_t request;
  NanCallback* callback;

  char* data;
  uint32_t dataLen;
  bool dataIsPath;

  // libmagic info
  const char* path;
  int flags;

  bool error;
  bool free_error;
  char* error_message;

  const char* result;
};

static Persistent<FunctionTemplate> constructor;
static const char* fallbackPath;

class Magic : public ObjectWrap {
  public:
    const char* mpath;
    int mflags;

    Magic(const char* path, int flags) {
      if (path != NULL) {
        /* Windows blows up trying to look up the path '(null)' returned by
           magic_getpath() */
        if (strncmp(path, "(null)", 6) == 0)
          path = NULL;
      }
      mpath = (path == NULL ? strdup(fallbackPath) : path);
      mflags = flags;
    }
    ~Magic() {
      if (mpath != NULL) {
        free((void*)mpath);
        mpath = NULL;
      }
    }

    static NAN_METHOD(New) {
      NanScope();
#ifndef _WIN32
      int mflags = MAGIC_SYMLINK;
#else
      int mflags = MAGIC_NONE;
#endif
      char* path = NULL;
      bool use_bundled = true;

      if (!args.IsConstructCall())
        return NanThrowTypeError("Use `new` to create instances of this object.");

      if (args.Length() > 1) {
        if (args[1]->IsInt32())
          mflags = args[1]->Int32Value();
        else
          return NanThrowTypeError("Second argument must be an integer");
      }

      if (args.Length() > 0) {
        if (args[0]->IsString()) {
          use_bundled = false;
          String::Utf8Value str(args[0]->ToString());
          path = strdup((const char*)(*str));
        } else if (args[0]->IsInt32())
          mflags = args[0]->Int32Value();
        else if (args[0]->IsBoolean() && !args[0]->BooleanValue()) {
          use_bundled = false;
          path = strdup(magic_getpath(NULL, 0/*FILE_LOAD*/));
        } else
          return NanThrowTypeError("First argument must be a string or integer");
      }

      Magic* obj = new Magic((use_bundled ? NULL : path), mflags);
      obj->Wrap(args.This());
      obj->Ref();

      NanReturnValue(args.This());
    }

    static NAN_METHOD(DetectFile) {
      NanScope();
      Magic* obj = ObjectWrap::Unwrap<Magic>(args.This());

      if (!args[0]->IsString())
        return NanThrowTypeError("First argument must be a string");
      if (!args[1]->IsFunction())
        return NanThrowTypeError("Second argument must be a callback function");

      Local<Function> callback = Local<Function>::Cast(args[1]);

      String::Utf8Value str(args[0]->ToString());

      Baton* baton = new Baton();
      baton->error = false;
      baton->free_error = true;
      baton->error_message = NULL;
      baton->request.data = baton;
      baton->callback = new NanCallback(callback);
      baton->data = strdup((const char*)*str);
      baton->dataIsPath = true;
      baton->path = obj->mpath;
      baton->flags = obj->mflags;
      baton->result = NULL;

      int status = uv_queue_work(uv_default_loop(),
                                 &baton->request,
                                 Magic::DetectWork,
                                 (uv_after_work_cb)Magic::DetectAfter);
      assert(status == 0);

      NanReturnUndefined();
    }

    static NAN_METHOD(Detect) {
      NanScope();
      Magic* obj = ObjectWrap::Unwrap<Magic>(args.This());

      if (args.Length() < 2)
        return NanThrowTypeError("Expecting 2 arguments");
      if (!Buffer::HasInstance(args[0]))
        return NanThrowTypeError("First argument must be a Buffer");
      if (!args[1]->IsFunction())
        return NanThrowTypeError("Second argument must be a callback function");

      Local<Function> callback = Local<Function>::Cast(args[1]);
#if NODE_MAJOR_VERSION == 0 && NODE_MINOR_VERSION < 10
      Local<Object> buffer_obj = args[0]->ToObject();
#else
      Local<Value> buffer_obj = args[0];
#endif

      Baton* baton = new Baton();
      baton->error = false;
      baton->free_error = true;
      baton->error_message = NULL;
      baton->request.data = baton;
      baton->callback = new NanCallback(callback);
      baton->data = Buffer::Data(buffer_obj);
      baton->dataLen = Buffer::Length(buffer_obj);
      baton->dataIsPath = false;
      baton->path = obj->mpath;
      baton->flags = obj->mflags;
      baton->result = NULL;

      int status = uv_queue_work(uv_default_loop(),
                                 &baton->request,
                                 Magic::DetectWork,
                                 (uv_after_work_cb)Magic::DetectAfter);
      assert(status == 0);

      NanReturnUndefined();
    }

    static void DetectWork(uv_work_t* req) {
      Baton* baton = static_cast<Baton*>(req->data);
      const char* result;
      struct magic_set *magic = magic_open(baton->flags
                                           | MAGIC_NO_CHECK_COMPRESS
                                           | MAGIC_ERROR);

      if (magic == NULL) {
#if NODE_MODULE_VERSION <= 0x000B
        baton->error_message = strdup(uv_strerror(
                                        uv_last_error(uv_default_loop())));
#else
# ifdef _MSC_VER
        baton->error_message = strdup(uv_strerror(GetLastError()));
# else
        baton->error_message = strdup(uv_strerror(errno));
# endif
#endif
      } else if (magic_load(magic, baton->path) == -1
                 && magic_load(magic, fallbackPath) == -1) {
        baton->error_message = strdup(magic_error(magic));
        magic_close(magic);
        magic = NULL;
      }

      if (magic == NULL) {
        if (baton->error_message)
          baton->error = true;
        return;
      }

      if (baton->dataIsPath) {
#ifdef _WIN32
        // open the file manually to help cope with potential unicode characters
        // in filename
        const char* ofn = baton->data;
        int flags = O_RDONLY|O_BINARY;
        int fd = -1;
        int wLen;
        wLen = MultiByteToWideChar(CP_UTF8, 0, ofn, -1, NULL, 0);
        if (wLen > 0) {
          wchar_t* wfn = (wchar_t*)malloc(wLen * sizeof(wchar_t));
          if (wfn) {
            int wret = MultiByteToWideChar(CP_UTF8, 0, ofn, -1, wfn, wLen);
            if (wret != 0)
              fd = _wopen(wfn, flags);
            free(wfn);
            wfn = NULL;
          }
        }
        if (fd == -1) {
          baton->error = true;
          baton->free_error = false;
          baton->error_message = "Error while opening file";
          magic_close(magic);
          return;
        }
        result = magic_descriptor(magic, fd);
        _close(fd);
#else
        result = magic_file(magic, baton->data);
#endif
      } else
        result = magic_buffer(magic, (const void*)baton->data, baton->dataLen);

      if (result == NULL) {
        const char* error = magic_error(magic);
        if (error) {
          baton->error = true;
          baton->error_message = strdup(error);
        }
      } else
        baton->result = strdup(result);

      magic_close(magic);
    }

    static void DetectAfter(uv_work_t* req) {
      NanScope();
      Baton* baton = static_cast<Baton*>(req->data);

      if (baton->error) {
        Local<Value> err = NanError(baton->error_message);

        if (baton->free_error)
          free(baton->error_message);

        Local<Value> argv[1] = { err };
        baton->callback->Call(1, argv);
      } else {
        Local<Value> argv[2] = {
          NanNull(),
          Local<Value>(baton->result
                       ? NanNew<String>(baton->result)
                       : NanNew<String>())
        };

        if (baton->result)
          free((void*)baton->result);

        baton->callback->Call(2, argv);
      }

      if (baton->dataIsPath)
        free(baton->data);
      delete baton->callback;
      delete baton;
    }

    static NAN_METHOD(SetFallback) {
      NanScope();

      if (fallbackPath)
        free((void*)fallbackPath);

      if (args.Length() > 0 && args[0]->IsString()
          && args[0]->ToString()->Length() > 0) {
        String::Utf8Value str(args[0]->ToString());
        fallbackPath = strdup((const char*)(*str));
      } else
        fallbackPath = NULL;

      NanReturnUndefined();
    }

    static void Initialize(Handle<Object> target) {
      NanScope();

      Local<FunctionTemplate> tpl = NanNew<FunctionTemplate>(New);

      NanAssignPersistent(constructor, tpl);
      tpl->InstanceTemplate()->SetInternalFieldCount(1);
      tpl->SetClassName(NanNew<String>("Magic"));

      NODE_SET_PROTOTYPE_METHOD(tpl, "detectFile", DetectFile);
      NODE_SET_PROTOTYPE_METHOD(tpl, "detect", Detect);
      target->Set(NanNew<String>("setFallback"),
        NanNew<FunctionTemplate>(SetFallback)->GetFunction());

      target->Set(NanNew<String>("Magic"), tpl->GetFunction());
    }
};

extern "C" {
  void init(Handle<Object> target) {
    NanScope();
    Magic::Initialize(target);
  }

  NODE_MODULE(magic, init);
}
<commit_msg>src: fix errno in node v0.11+<commit_after>#include <node.h>
#include <node_buffer.h>
#include <nan.h>
#include <string.h>
#include <stdlib.h>

#ifdef _WIN32
# include <io.h>
# include <fcntl.h>
# include <wchar.h>
#endif

#include "magic.h"

using namespace node;
using namespace v8;

struct Baton {
  uv_work_t request;
  NanCallback* callback;

  char* data;
  uint32_t dataLen;
  bool dataIsPath;

  // libmagic info
  const char* path;
  int flags;

  bool error;
  bool free_error;
  char* error_message;

  const char* result;
};

static Persistent<FunctionTemplate> constructor;
static const char* fallbackPath;

class Magic : public ObjectWrap {
  public:
    const char* mpath;
    int mflags;

    Magic(const char* path, int flags) {
      if (path != NULL) {
        /* Windows blows up trying to look up the path '(null)' returned by
           magic_getpath() */
        if (strncmp(path, "(null)", 6) == 0)
          path = NULL;
      }
      mpath = (path == NULL ? strdup(fallbackPath) : path);
      mflags = flags;
    }
    ~Magic() {
      if (mpath != NULL) {
        free((void*)mpath);
        mpath = NULL;
      }
    }

    static NAN_METHOD(New) {
      NanScope();
#ifndef _WIN32
      int mflags = MAGIC_SYMLINK;
#else
      int mflags = MAGIC_NONE;
#endif
      char* path = NULL;
      bool use_bundled = true;

      if (!args.IsConstructCall())
        return NanThrowTypeError("Use `new` to create instances of this object.");

      if (args.Length() > 1) {
        if (args[1]->IsInt32())
          mflags = args[1]->Int32Value();
        else
          return NanThrowTypeError("Second argument must be an integer");
      }

      if (args.Length() > 0) {
        if (args[0]->IsString()) {
          use_bundled = false;
          String::Utf8Value str(args[0]->ToString());
          path = strdup((const char*)(*str));
        } else if (args[0]->IsInt32())
          mflags = args[0]->Int32Value();
        else if (args[0]->IsBoolean() && !args[0]->BooleanValue()) {
          use_bundled = false;
          path = strdup(magic_getpath(NULL, 0/*FILE_LOAD*/));
        } else
          return NanThrowTypeError("First argument must be a string or integer");
      }

      Magic* obj = new Magic((use_bundled ? NULL : path), mflags);
      obj->Wrap(args.This());
      obj->Ref();

      NanReturnValue(args.This());
    }

    static NAN_METHOD(DetectFile) {
      NanScope();
      Magic* obj = ObjectWrap::Unwrap<Magic>(args.This());

      if (!args[0]->IsString())
        return NanThrowTypeError("First argument must be a string");
      if (!args[1]->IsFunction())
        return NanThrowTypeError("Second argument must be a callback function");

      Local<Function> callback = Local<Function>::Cast(args[1]);

      String::Utf8Value str(args[0]->ToString());

      Baton* baton = new Baton();
      baton->error = false;
      baton->free_error = true;
      baton->error_message = NULL;
      baton->request.data = baton;
      baton->callback = new NanCallback(callback);
      baton->data = strdup((const char*)*str);
      baton->dataIsPath = true;
      baton->path = obj->mpath;
      baton->flags = obj->mflags;
      baton->result = NULL;

      int status = uv_queue_work(uv_default_loop(),
                                 &baton->request,
                                 Magic::DetectWork,
                                 (uv_after_work_cb)Magic::DetectAfter);
      assert(status == 0);

      NanReturnUndefined();
    }

    static NAN_METHOD(Detect) {
      NanScope();
      Magic* obj = ObjectWrap::Unwrap<Magic>(args.This());

      if (args.Length() < 2)
        return NanThrowTypeError("Expecting 2 arguments");
      if (!Buffer::HasInstance(args[0]))
        return NanThrowTypeError("First argument must be a Buffer");
      if (!args[1]->IsFunction())
        return NanThrowTypeError("Second argument must be a callback function");

      Local<Function> callback = Local<Function>::Cast(args[1]);
#if NODE_MAJOR_VERSION == 0 && NODE_MINOR_VERSION < 10
      Local<Object> buffer_obj = args[0]->ToObject();
#else
      Local<Value> buffer_obj = args[0];
#endif

      Baton* baton = new Baton();
      baton->error = false;
      baton->free_error = true;
      baton->error_message = NULL;
      baton->request.data = baton;
      baton->callback = new NanCallback(callback);
      baton->data = Buffer::Data(buffer_obj);
      baton->dataLen = Buffer::Length(buffer_obj);
      baton->dataIsPath = false;
      baton->path = obj->mpath;
      baton->flags = obj->mflags;
      baton->result = NULL;

      int status = uv_queue_work(uv_default_loop(),
                                 &baton->request,
                                 Magic::DetectWork,
                                 (uv_after_work_cb)Magic::DetectAfter);
      assert(status == 0);

      NanReturnUndefined();
    }

    static void DetectWork(uv_work_t* req) {
      Baton* baton = static_cast<Baton*>(req->data);
      const char* result;
      struct magic_set *magic = magic_open(baton->flags
                                           | MAGIC_NO_CHECK_COMPRESS
                                           | MAGIC_ERROR);

      if (magic == NULL) {
#if NODE_MODULE_VERSION <= 0x000B
        baton->error_message = strdup(uv_strerror(
                                        uv_last_error(uv_default_loop())));
#else
# ifdef _MSC_VER
        baton->error_message = strdup(uv_strerror(GetLastError()));
# else
        baton->error_message = strdup(uv_strerror(-errno));
# endif
#endif
      } else if (magic_load(magic, baton->path) == -1
                 && magic_load(magic, fallbackPath) == -1) {
        baton->error_message = strdup(magic_error(magic));
        magic_close(magic);
        magic = NULL;
      }

      if (magic == NULL) {
        if (baton->error_message)
          baton->error = true;
        return;
      }

      if (baton->dataIsPath) {
#ifdef _WIN32
        // open the file manually to help cope with potential unicode characters
        // in filename
        const char* ofn = baton->data;
        int flags = O_RDONLY|O_BINARY;
        int fd = -1;
        int wLen;
        wLen = MultiByteToWideChar(CP_UTF8, 0, ofn, -1, NULL, 0);
        if (wLen > 0) {
          wchar_t* wfn = (wchar_t*)malloc(wLen * sizeof(wchar_t));
          if (wfn) {
            int wret = MultiByteToWideChar(CP_UTF8, 0, ofn, -1, wfn, wLen);
            if (wret != 0)
              fd = _wopen(wfn, flags);
            free(wfn);
            wfn = NULL;
          }
        }
        if (fd == -1) {
          baton->error = true;
          baton->free_error = false;
          baton->error_message = "Error while opening file";
          magic_close(magic);
          return;
        }
        result = magic_descriptor(magic, fd);
        _close(fd);
#else
        result = magic_file(magic, baton->data);
#endif
      } else
        result = magic_buffer(magic, (const void*)baton->data, baton->dataLen);

      if (result == NULL) {
        const char* error = magic_error(magic);
        if (error) {
          baton->error = true;
          baton->error_message = strdup(error);
        }
      } else
        baton->result = strdup(result);

      magic_close(magic);
    }

    static void DetectAfter(uv_work_t* req) {
      NanScope();
      Baton* baton = static_cast<Baton*>(req->data);

      if (baton->error) {
        Local<Value> err = NanError(baton->error_message);

        if (baton->free_error)
          free(baton->error_message);

        Local<Value> argv[1] = { err };
        baton->callback->Call(1, argv);
      } else {
        Local<Value> argv[2] = {
          NanNull(),
          Local<Value>(baton->result
                       ? NanNew<String>(baton->result)
                       : NanNew<String>())
        };

        if (baton->result)
          free((void*)baton->result);

        baton->callback->Call(2, argv);
      }

      if (baton->dataIsPath)
        free(baton->data);
      delete baton->callback;
      delete baton;
    }

    static NAN_METHOD(SetFallback) {
      NanScope();

      if (fallbackPath)
        free((void*)fallbackPath);

      if (args.Length() > 0 && args[0]->IsString()
          && args[0]->ToString()->Length() > 0) {
        String::Utf8Value str(args[0]->ToString());
        fallbackPath = strdup((const char*)(*str));
      } else
        fallbackPath = NULL;

      NanReturnUndefined();
    }

    static void Initialize(Handle<Object> target) {
      NanScope();

      Local<FunctionTemplate> tpl = NanNew<FunctionTemplate>(New);

      NanAssignPersistent(constructor, tpl);
      tpl->InstanceTemplate()->SetInternalFieldCount(1);
      tpl->SetClassName(NanNew<String>("Magic"));

      NODE_SET_PROTOTYPE_METHOD(tpl, "detectFile", DetectFile);
      NODE_SET_PROTOTYPE_METHOD(tpl, "detect", Detect);
      target->Set(NanNew<String>("setFallback"),
        NanNew<FunctionTemplate>(SetFallback)->GetFunction());

      target->Set(NanNew<String>("Magic"), tpl->GetFunction());
    }
};

extern "C" {
  void init(Handle<Object> target) {
    NanScope();
    Magic::Initialize(target);
  }

  NODE_MODULE(magic, init);
}
<|endoftext|>


<commit_before>#include "merger.hpp"
#include <boost/program_options.hpp>
#include <boost/filesystem.hpp>
#include <iostream>
#include <fstream>
#include <string>

// program version
const auto version = "0.2alpha";

void merge( boost::program_options::variables_map const& vm )
{
  std::ifstream left, right;
  // we need to check for failbit in case that opening failed...
  left.exceptions( std::ifstream::failbit | std::ifstream::badbit );
  right.exceptions( std::ifstream::failbit | std::ifstream::badbit );

  left.open( vm["left"].as<std::string>() );
  right.open( vm["right"].as<std::string>() );

  // ... but failbit is set in some EOF conditions by getline,
  // so disable its checking after file is open
  left.exceptions( std::ifstream::badbit );
  right.exceptions( std::ifstream::badbit );

  merger::Merger m{
    vm["separator"].as<char>(),
    vm.count( "ignore-quotes" ) > 0,
    vm.count( "date" ) > 0,
    vm.count( "drop-empty" ) > 0,
    vm["header"].as<std::size_t>()
  };

  if (vm.count( "out" )) {
    // optional output file specified - using it as output
    std::ofstream out;
    out.exceptions( std::ofstream::failbit | std::ofstream::badbit );
    out.open( vm["out"].as<std::string>() );
    out.exceptions( std::ofstream::badbit );

    m.merge( left, right, out );

  } else {
    // no output specified - using standart output
    m.merge( left, right, std::cout );
  }
}

int main( int argc, char* argv[] )
{
  // executable name
  auto name = boost::filesystem::path{ argv[0] }.filename().string();

  try {
    // parse parameters
    namespace po = boost::program_options;

    po::options_description desc{ "Allowed options" };
    desc.add_options()
      ("help,h", "print this help message")
      ("version,v", "print program version")
      ("ignore-quotes,q", "no special treatment for quoted text")
      ("date,d", "compare by date/time")
      ("drop-empty,D", "discard lines without match in all sources")
      ("separator,s", po::value<char>()->default_value( ',' ), "set separator")
      ("header,H", po::value<std::size_t>()->default_value( 0 ), "size of the header (left header will also be copied to the output)")
      ;
    po::options_description hidden{ "Hidden options" };
    hidden.add_options()
      ("left", po::value<std::string>(), "left file")
      ("right", po::value<std::string>(), "right file")
      ("out", po::value<std::string>(), "output file")
      ;

    po::options_description cmdline;
    cmdline.add( desc ).add( hidden );

    po::positional_options_description p;
    p.add( "left", 1 ).add( "right", 1 ).add( "out", 1 );

    po::variables_map vm;
    po::store( po::command_line_parser{ argc, argv }.options( cmdline ).positional( p ).run(), vm );
    po::notify( vm );

    // check parameters
    if (vm.count( "help" )) {
      std::cout << "Usage:\n  " << name << " [OPTIONS] LEFT-FILE RIGHT-FILE [OUTPUT]\n\n"
        << desc << std::endl;
      return 0;
    }

    if (vm.count( "version" )) {
      std::cout << name << " version: " << version << std::endl;
      return 0;
    }

    if (!vm.count( "left" ) || !vm.count( "right" )) {
      std::cerr << name << ": at least 2 files have to be provided" << std::endl;
      return 1;
    }

    // the actual program
    merge( vm );

  } catch (std::ios_base::failure const& e) {
    // I/O error occured - terminating
    // TODO: more informative message
    std::cerr << name << ": file I/O error: " << e.what() << std::endl;
    return 1;

  } catch (std::exception const& e) {
    // some other error occured
    std::cerr << name << ": " << e.what() << std::endl;
    return 1;
  }
}
<commit_msg>Version bump to 0.2<commit_after>#include "merger.hpp"
#include <boost/program_options.hpp>
#include <boost/filesystem.hpp>
#include <iostream>
#include <fstream>
#include <string>

// program version
const auto version = "0.2";

void merge( boost::program_options::variables_map const& vm )
{
  std::ifstream left, right;
  // we need to check for failbit in case that opening failed...
  left.exceptions( std::ifstream::failbit | std::ifstream::badbit );
  right.exceptions( std::ifstream::failbit | std::ifstream::badbit );

  left.open( vm["left"].as<std::string>() );
  right.open( vm["right"].as<std::string>() );

  // ... but failbit is set in some EOF conditions by getline,
  // so disable its checking after file is open
  left.exceptions( std::ifstream::badbit );
  right.exceptions( std::ifstream::badbit );

  merger::Merger m{
    vm["separator"].as<char>(),
    vm.count( "ignore-quotes" ) > 0,
    vm.count( "date" ) > 0,
    vm.count( "drop-empty" ) > 0,
    vm["header"].as<std::size_t>()
  };

  if (vm.count( "out" )) {
    // optional output file specified - using it as output
    std::ofstream out;
    out.exceptions( std::ofstream::failbit | std::ofstream::badbit );
    out.open( vm["out"].as<std::string>() );
    out.exceptions( std::ofstream::badbit );

    m.merge( left, right, out );

  } else {
    // no output specified - using standart output
    m.merge( left, right, std::cout );
  }
}

int main( int argc, char* argv[] )
{
  // executable name
  auto name = boost::filesystem::path{ argv[0] }.filename().string();

  try {
    // parse parameters
    namespace po = boost::program_options;

    po::options_description desc{ "Allowed options" };
    desc.add_options()
      ("help,h", "print this help message")
      ("version,v", "print program version")
      ("ignore-quotes,q", "no special treatment for quoted text")
      ("date,d", "compare by date/time")
      ("drop-empty,D", "discard lines without match in all sources")
      ("separator,s", po::value<char>()->default_value( ',' ), "set separator")
      ("header,H", po::value<std::size_t>()->default_value( 0 ), "size of the header (left header will also be copied to the output)")
      ;
    po::options_description hidden{ "Hidden options" };
    hidden.add_options()
      ("left", po::value<std::string>(), "left file")
      ("right", po::value<std::string>(), "right file")
      ("out", po::value<std::string>(), "output file")
      ;

    po::options_description cmdline;
    cmdline.add( desc ).add( hidden );

    po::positional_options_description p;
    p.add( "left", 1 ).add( "right", 1 ).add( "out", 1 );

    po::variables_map vm;
    po::store( po::command_line_parser{ argc, argv }.options( cmdline ).positional( p ).run(), vm );
    po::notify( vm );

    // check parameters
    if (vm.count( "help" )) {
      std::cout << "Usage:\n  " << name << " [OPTIONS] LEFT-FILE RIGHT-FILE [OUTPUT]\n\n"
        << desc << std::endl;
      return 0;
    }

    if (vm.count( "version" )) {
      std::cout << name << " version: " << version << std::endl;
      return 0;
    }

    if (!vm.count( "left" ) || !vm.count( "right" )) {
      std::cerr << name << ": at least 2 files have to be provided" << std::endl;
      return 1;
    }

    // the actual program
    merge( vm );

  } catch (std::ios_base::failure const& e) {
    // I/O error occured - terminating
    // TODO: more informative message
    std::cerr << name << ": file I/O error: " << e.what() << std::endl;
    return 1;

  } catch (std::exception const& e) {
    // some other error occured
    std::cerr << name << ": " << e.what() << std::endl;
    return 1;
  }
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, Karsten Heinze <karsten.heinze@sidenotes.de>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// 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 HOLDER 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 <iomanip>
#include <iostream>
#include <memory>
#include <string>

#include <libtecla.h>

#include "types.hpp"
#include "sesame/Instance.hpp"
#include "sesame/commands/InstanceTask.hpp"
#include "sesame/utils/string.hpp"
#include "sesame/utils/completion.hpp"
#include "sesame/utils/Parser.hpp"
#include "sesame/utils/ParseResult.hpp"
#include "sesame/utils/TeclaReader.hpp"

using sesame::commands::InstanceTask;

String buildPrompt( std::shared_ptr<sesame::Instance>& instance );
String usage( const char* command );

int main( int argc, char** argv)
{
   // Set locale!
   sesame::utils::setLocale();

   // Start.
   std::shared_ptr<sesame::Instance> instance;

   // File passed?
   if ( argc > 2 )
   {
      std::cout << usage( argv[ 0 ] ) << std::endl;
      return 1;
   }
   else if ( argc == 2 )
   {
      try
      {
         InstanceTask task( InstanceTask::OPEN, argv[ 1 ] );
         task.run( instance );
      }
      catch ( std::runtime_error& e )
      {
         std::cerr << "ERROR: " << e.what() << std::endl;;
         return 1;
      }
   }

   sesame::utils::TeclaReader reader( 1024, 2048 );
   reader.addCompletion( cpl_complete_sesame, static_cast<void*>( &instance ) );
   sesame::utils::Parser parser;
   sesame::utils::ParseResult parseResult;
   String normalized;

   do
   {
      // Build prompt.
      String prompt( buildPrompt( instance ) );

      // Read line.
      try
      {
         normalized = reader.readLine( prompt );
      }
      catch ( std::runtime_error& e )
      {
         std::cerr << "ERROR: " << e.what() << std::endl;
         break;
      }

      if ( normalized == "\n" )
      {
         continue;
      }
      else if ( normalized.find( "edit-mode " ) == 0 )
      {
         if ( normalized == "edit-mode vi\n" )
         {
            if ( ! reader.setEditMode( "vi" ) )
            {
               std::cerr << "ERROR: failed to set edit-mode" << std::endl;
            }
         }
         else if ( normalized == "edit-mode emacs\n" )
         {
            if ( ! reader.setEditMode( "emacs" ) )
            {
               std::cerr << "ERROR: failed to set edit-mode" << std::endl;
            }
         }
         else
         {
            std::cerr << "ERROR: edit-mode not supported" << std::endl;
         }
      }
      else if ( normalized == "clear\n" )
      {
         if ( ! reader.clear() )
         {
            std::cerr << "ERROR: failed to clear terminal" << std::endl;
         }
      }
      else if ( normalized == "quit\n" )
      {
         try
         {
            InstanceTask task( InstanceTask::CLOSE );
            task.run( instance );
         }
         catch ( std::runtime_error& e )
         {
            std::cerr << "ERROR: " << e.what() << std::endl;;
         }

         // Quit only if instance was closed!
         if ( ! instance )
         {
            break;
         }
      }
      else
      {
         parseResult = parser.parse( normalized );
         if ( parseResult.isValid() )
         {
            if ( ! parseResult.getCommandToken().empty() )
            {
               //std::cout << parseResult << std::endl;
               if ( parseResult.getCommand() != nullptr )
               {
                  try
                  {
                     parseResult.getCommand()->run( instance );
                  }
                  catch ( std::runtime_error& e )
                  {
                     std::cerr << "ERROR: " << e.what() << std::endl;
                  }
               }
            }
         }
         else
         {
            std::cerr << parseResult << std::endl;
         }
      }
   }
   while ( true );

   return 0;
}

String buildPrompt( std::shared_ptr<sesame::Instance>& instance )
{
   String prompt( "sesame> " );
   if ( instance )
   {
      StringStream s;
      s << "sesame #" << std::hex << std::setw( 8 ) << std::setfill( '0' ) << instance->getId() << "> ";
      prompt = s.str();
   }

   return prompt;
}

String usage( const char* command )
{
   StringStream s;
   s << "usage: " << command << " [FILE]";
   return s.str();
}
<commit_msg>run close cmd only if instance is open<commit_after>// Copyright (c) 2015, Karsten Heinze <karsten.heinze@sidenotes.de>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// 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 HOLDER 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 <iomanip>
#include <iostream>
#include <memory>
#include <string>

#include <libtecla.h>

#include "types.hpp"
#include "sesame/Instance.hpp"
#include "sesame/commands/InstanceTask.hpp"
#include "sesame/utils/string.hpp"
#include "sesame/utils/completion.hpp"
#include "sesame/utils/Parser.hpp"
#include "sesame/utils/ParseResult.hpp"
#include "sesame/utils/TeclaReader.hpp"

using sesame::commands::InstanceTask;

String buildPrompt( std::shared_ptr<sesame::Instance>& instance );
String usage( const char* command );

int main( int argc, char** argv)
{
   // Set locale!
   sesame::utils::setLocale();

   // Start.
   std::shared_ptr<sesame::Instance> instance;

   // File passed?
   if ( argc > 2 )
   {
      std::cout << usage( argv[ 0 ] ) << std::endl;
      return 1;
   }
   else if ( argc == 2 )
   {
      try
      {
         InstanceTask task( InstanceTask::OPEN, argv[ 1 ] );
         task.run( instance );
      }
      catch ( std::runtime_error& e )
      {
         std::cerr << "ERROR: " << e.what() << std::endl;;
         return 1;
      }
   }

   sesame::utils::TeclaReader reader( 1024, 2048 );
   reader.addCompletion( cpl_complete_sesame, static_cast<void*>( &instance ) );
   sesame::utils::Parser parser;
   sesame::utils::ParseResult parseResult;
   String normalized;

   do
   {
      // Build prompt.
      String prompt( buildPrompt( instance ) );

      // Read line.
      try
      {
         normalized = reader.readLine( prompt );
      }
      catch ( std::runtime_error& e )
      {
         std::cerr << "ERROR: " << e.what() << std::endl;
         break;
      }

      if ( normalized == "\n" )
      {
         continue;
      }
      else if ( normalized.find( "edit-mode " ) == 0 )
      {
         if ( normalized == "edit-mode vi\n" )
         {
            if ( ! reader.setEditMode( "vi" ) )
            {
               std::cerr << "ERROR: failed to set edit-mode" << std::endl;
            }
         }
         else if ( normalized == "edit-mode emacs\n" )
         {
            if ( ! reader.setEditMode( "emacs" ) )
            {
               std::cerr << "ERROR: failed to set edit-mode" << std::endl;
            }
         }
         else
         {
            std::cerr << "ERROR: edit-mode not supported" << std::endl;
         }
      }
      else if ( normalized == "clear\n" )
      {
         if ( ! reader.clear() )
         {
            std::cerr << "ERROR: failed to clear terminal" << std::endl;
         }
      }
      else if ( normalized == "quit\n" )
      {
         if ( instance )
         {
            try
            {
               InstanceTask task( InstanceTask::CLOSE );
               task.run( instance );
            }
            catch ( std::runtime_error& e )
            {
               std::cerr << "ERROR: " << e.what() << std::endl;;
            }
         }

         // Quit only if no instance is open!
         if ( ! instance )
         {
            break;
         }
      }
      else
      {
         parseResult = parser.parse( normalized );
         if ( parseResult.isValid() )
         {
            if ( ! parseResult.getCommandToken().empty() )
            {
               //std::cout << parseResult << std::endl;
               if ( parseResult.getCommand() != nullptr )
               {
                  try
                  {
                     parseResult.getCommand()->run( instance );
                  }
                  catch ( std::runtime_error& e )
                  {
                     std::cerr << "ERROR: " << e.what() << std::endl;
                  }
               }
            }
         }
         else
         {
            std::cerr << parseResult << std::endl;
         }
      }
   }
   while ( true );

   return 0;
}

String buildPrompt( std::shared_ptr<sesame::Instance>& instance )
{
   String prompt( "sesame> " );
   if ( instance )
   {
      StringStream s;
      s << "sesame #" << std::hex << std::setw( 8 ) << std::setfill( '0' ) << instance->getId() << "> ";
      prompt = s.str();
   }

   return prompt;
}

String usage( const char* command )
{
   StringStream s;
   s << "usage: " << command << " [FILE]";
   return s.str();
}
<|endoftext|>


<commit_before>/* -*- coding: utf-8 -*-
*   Copyright (c) 2010, Tim Kleinschmit.  This file is
*   licensed under the General Public License version 3 or later.
*   See the COPYRIGHT file.
*/

#include <QtGui/QApplication>
#include <QtCore/QTranslator>
#include <QtCore/QLibraryInfo>

#include "const.h"
#include "mainwindow.h"
#include "iconloader.h"

int main(int argc, char *argv[])
{
    // Settings stuff
    QCoreApplication::setApplicationName ( APP_NAME );
    QCoreApplication::setApplicationVersion ( APP_VERSION );
    QCoreApplication::setOrganizationDomain ( APP_URL );
    QCoreApplication::setOrganizationName ( APP_NAME);

    // verify the user if not run as root
#ifdef Q_OS_UNIX
    if ( geteuid () == 0 ) {
        qWarning ()<< APP_NAME + QObject::tr ( " is not supposed to be run as root" );
        exit(0);
    }
#endif
    // initiliaze the resource datas
    Q_INIT_RESOURCE( data );

    // only one session of simba
    QApplication a( argc, argv );

    // check tray exist
    if ( !QSystemTrayIcon::isSystemTrayAvailable ())
        qWarning ()<< QObject::tr ( "I couldn't detect any system tray on this system." );

    // install qt translator
    QTranslator qtTranslator;
    qtTranslator.load( "qt_" + QLocale::system ().name (), QLibraryInfo::location ( QLibraryInfo::TranslationsPath ));
    a.installTranslator( &qtTranslator );

    // Icons
    IconLoader::Init ();

    // delivery the cli argument
    MainWindow w( QCoreApplication::arguments ());
    w.show ();
    return a.exec ();
}

<commit_msg>Fix geteuid compile error<commit_after>/* -*- coding: utf-8 -*-
*   Copyright (c) 2010, Tim Kleinschmit.  This file is
*   licensed under the General Public License version 3 or later.
*   See the COPYRIGHT file.
*/

#include <QtGui/QApplication>
#include <QtCore/QTranslator>
#include <QtCore/QLibraryInfo>

#include "const.h"
#include "mainwindow.h"
#include "iconloader.h"
#include <unistd.h>

int main(int argc, char *argv[])
{
    // Settings stuff
    QCoreApplication::setApplicationName ( APP_NAME );
    QCoreApplication::setApplicationVersion ( APP_VERSION );
    QCoreApplication::setOrganizationDomain ( APP_URL );
    QCoreApplication::setOrganizationName ( APP_NAME);

    // verify the user if not run as root
#ifdef Q_OS_UNIX
    if ( geteuid () == 0 ) {
        qWarning ()<< APP_NAME + QObject::tr ( " is not supposed to be run as root" );
        exit(0);
    }
#endif
    // initiliaze the resource datas
    Q_INIT_RESOURCE( data );

    // only one session of simba
    QApplication a( argc, argv );

    // check tray exist
    if ( !QSystemTrayIcon::isSystemTrayAvailable ())
        qWarning ()<< QObject::tr ( "I couldn't detect any system tray on this system." );

    // install qt translator
    QTranslator qtTranslator;
    qtTranslator.load( "qt_" + QLocale::system ().name (), QLibraryInfo::location ( QLibraryInfo::TranslationsPath ));
    a.installTranslator( &qtTranslator );

    // Icons
    IconLoader::Init ();

    // delivery the cli argument
    MainWindow w( QCoreApplication::arguments ());
    w.show ();
    return a.exec ();
}

<|endoftext|>