<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/
/* $Id$ */
/** @file    AliFMDRawReader.cxx
    @author  Christian Holm Christensen <cholm@nbi.dk>
    @date    Mon Mar 27 12:45:23 2006
    @brief   Class to read raw data
    @ingroup FMD_rec
*/
//____________________________________________________________________
//
// Class to read ADC values from a AliRawReader object.
//
// This class uses the AliFMDRawStreamer class to read the ALTRO
// formatted data.
//
//          +-------+
//          | TTask |
//          +-------+
//              ^
//              |
//      +-----------------+  <<references>>  +--------------+
//      | AliFMDRawReader |<>----------------| AliRawReader |
//      +-----------------+                  +--------------+
//              |                                  ^
//              | <<uses>>                         |
//              V                                  |
//      +-----------------+      <<uses>>          |
//      | AliFMDRawStream |------------------------+
//      +-----------------+
//              |
//              V
//      +----------------+
//      | AliAltroStream |
//      +----------------+
//
#include <AliLog.h>		// ALILOG_H
#include "AliFMDParameters.h"	// ALIFMDPARAMETERS_H
#include "AliFMDDigit.h"	// ALIFMDDIGIT_H
#include "AliFMDRawStream.h"	// ALIFMDRAWSTREAM_H
#include "AliRawReader.h"	// ALIRAWREADER_H
#include "AliFMDRawReader.h"	// ALIFMDRAWREADER_H
// #include "AliFMDAltroIO.h"	// ALIFMDALTROIO_H
// #include <TArrayI.h>		// ROOT_TArrayI
#include <TTree.h>		// ROOT_TTree
#include <TClonesArray.h>	// ROOT_TClonesArray
// #include <iostream>
// #include <iomanip>

//____________________________________________________________________
ClassImp(AliFMDRawReader)
#if 0
  ; // This is here to keep Emacs for indenting the next line
#endif

//____________________________________________________________________
AliFMDRawReader::AliFMDRawReader(AliRawReader* reader, TTree* tree)
  : TTask("FMDRawReader", "Reader of Raw ADC values from the FMD"),
    fTree(tree),
    fReader(reader),
    fSampleRate(1)
{
  // Default CTOR
}

//____________________________________________________________________
void
AliFMDRawReader::Exec(Option_t*)
{
  // Read the data
  TClonesArray* array = new TClonesArray("AliFMDDigit");
  if (!fTree) {
    AliError("No tree");
    return;
  }
  fTree->Branch("FMD", &array);
  ReadAdcs(array);
  Int_t nWrite = fTree->Fill();
  AliDebug(1, Form("Got a grand total of %d digits, wrote %d bytes to tree",
		   array->GetEntries(), nWrite));
}

#if 1
//____________________________________________________________________
Bool_t
AliFMDRawReader::ReadAdcs(TClonesArray* array)
{
  // Read raw data into the digits array, using AliFMDAltroReader.
  if (!array) {
    AliError("No TClonesArray passed");
    return kFALSE;
  }
  if (!fReader->ReadHeader()) {
    AliError("Couldn't read header");
    return kFALSE;
  }
  // Get sample rate
  AliFMDParameters* pars = AliFMDParameters::Instance();
  AliFMDRawStream input(fReader);

  UShort_t stripMin = 0;
  UShort_t stripMax = 127;
  UShort_t preSamp  = 0;

  UInt_t ddl    = 0;
  UInt_t rate   = 0;
  UInt_t last   = 0;
  UInt_t hwaddr = 0;
  // Data array is approx twice the size needed.
  UShort_t data[2048];
  while (input.ReadChannel(ddl, hwaddr, last, data)) {
    AliDebug(5, Form("Read channel 0x%x of size %d", hwaddr, last));
    UShort_t det, sec, str;
    Char_t   ring;
    if (!pars->Hardware2Detector(ddl, hwaddr, det, ring, sec, str)) {
      AliError(Form("Failed to get detector id from DDL %d "
		    "and hardware address 0x%x", ddl, hwaddr));
      continue;
    }
    rate     = pars->GetSampleRate(det, ring, sec, str);
    stripMin = pars->GetMinStrip(det, ring, sec, str);
    stripMax = pars->GetMaxStrip(det, ring, sec, str);
    AliDebug(5, Form("DDL 0x%04x, address 0x%03x maps to FMD%d%c[%2d,%3d]",
		       ddl, hwaddr, det, ring, sec, str));

    // Loop over the `timebins', and make the digits
    for (size_t i = 0; i < last; i++) {
      if (i < preSamp) continue;
      Int_t    n      = array->GetEntries();
      UShort_t curStr = str + stripMin + i / rate;
      if ((curStr-str) > stripMax) {
	AliError(Form("Current strip is %d but DB says max is %d",
		      curStr, stripMax));
      }
      AliDebug(5, Form("making digit for FMD%d%c[%2d,%3d] from sample %4d",
		       det, ring, sec, curStr, i));
      new ((*array)[n]) AliFMDDigit(det, ring, sec, curStr, data[i],
				    (rate >= 2 ? data[i+1] : 0),
				    (rate >= 3 ? data[i+2] : 0));
      if (rate >= 2) i++;
      if (rate >= 3) i++;
    }
  }
  return kTRUE;
}
#else
//____________________________________________________________________
Bool_t
AliFMDRawReader::ReadAdcs(TClonesArray* array)
{
  // Read raw data into the digits array, using AliFMDAltroReader.
  if (!array) {
    AliError("No TClonesArray passed");
    return kFALSE;
  }
  if (!fReader->ReadHeader()) {
    AliError("Couldn't read header");
    return kFALSE;
  }
  // Get sample rate
  AliFMDParameters* pars = AliFMDParameters::Instance();

  // Select FMD DDL's
  fReader->Select(AliFMDParameters::kBaseDDL>>8);

  UShort_t stripMin = 0;
  UShort_t stripMax = 127;
  UShort_t preSamp  = 0;

  do {
    UChar_t* cdata;
    if (!fReader->ReadNextData(cdata)) break;
    size_t   nchar = fReader->GetDataSize();
    UShort_t ddl   = AliFMDParameters::kBaseDDL + fReader->GetDDLID();
    UShort_t rate  = 0;
    AliDebug(1, Form("Reading %d bytes (%d 10bit words) from %d",
		     nchar, nchar * 8 / 10, ddl));
    // Make a stream to read from
    std::string str((char*)(cdata), nchar);
    std::istringstream s(str);
    // Prep the reader class.
    AliFMDAltroReader r(s);
    // Data array is approx twice the size needed.
    UShort_t data[2048], hwaddr, last;
    while (r.ReadChannel(hwaddr, last, data) > 0) {
      AliDebug(5, Form("Read channel 0x%x of size %d", hwaddr, last));
      UShort_t det, sec, str;
      Char_t   ring;
      if (!pars->Hardware2Detector(ddl, hwaddr, det, ring, sec, str)) {
	AliError(Form("Failed to detector id from DDL %d "
		      "and hardware address 0x%x", ddl, hwaddr));
	continue;
      }
      rate     = pars->GetSampleRate(det, ring, sec, str);
      stripMin = pars->GetMinStrip(det, ring, sec, str);
      stripMax = pars->GetMaxStrip(det, ring, sec, str);
      AliDebug(5, Form("DDL 0x%04x, address 0x%03x maps to FMD%d%c[%2d,%3d]",
		       ddl, hwaddr, det, ring, sec, str));

      // Loop over the `timebins', and make the digits
      for (size_t i = 0; i < last; i++) {
	if (i < preSamp) continue;
	Int_t    n      = array->GetEntries();
	UShort_t curStr = str + stripMin + i / rate;
	if ((curStr-str) > stripMax) {
	  AliError(Form("Current strip is %d but DB says max is %d",
			curStr, stripMax));
	}
	AliDebug(5, Form("making digit for FMD%d%c[%2d,%3d] from sample %4d",
			 det, ring, sec, curStr, i));
	new ((*array)[n]) AliFMDDigit(det, ring, sec, curStr, data[i],
				      (rate >= 2 ? data[i+1] : 0),
				      (rate >= 3 ? data[i+2] : 0));
	if (rate >= 2) i++;
	if (rate >= 3) i++;
	}
	if (r.IsBof()) break;
    }
  } while (true);
  return kTRUE;
}

// This is the old method, for comparison.   It's really ugly, and far
// too convoluted.
//____________________________________________________________________
void
AliFMDRawReader::Exec(Option_t*)
{
  // Read raw data into the digits array
  if (!fReader->ReadHeader()) {
    Error("ReadAdcs", "Couldn't read header");
    return;
  }

  Int_t n = 0;
  TClonesArray* array = new TClonesArray("AliFMDDigit");
  fTree->Branch("FMD", &array);

  // Get sample rate
  AliFMDParameters* pars = AliFMDParameters::Instance();
  fSampleRate = pars->GetSampleRate(AliFMDParameters::kBaseDDL);

  // Use AliAltroRawStream to read the ALTRO format.  No need to
  // reinvent the wheel :-)
  AliFMDRawStream input(fReader, fSampleRate);
  // Select FMD DDL's
  fReader->Select(AliFMDParameters::kBaseDDL);

  Int_t    oldDDL      = -1;
  Int_t    count       = 0;
  UShort_t detector    = 1; // Must be one here
  UShort_t oldDetector = 0;
  Bool_t   next        = kTRUE;

  // local Cache
  TArrayI counts(10);
  counts.Reset(-1);

  // Loop over data in file
  while (next) {
    next = input.Next();

    count++;
    Int_t ddl = fReader->GetDDLID();
    AliDebug(10, Form("Current DDL is %d", ddl));
    if (ddl != oldDDL || input.IsNewStrip() || !next) {
      // Make a new digit, if we have some data (oldDetector == 0,
      // means that we haven't really read anything yet - that is,
      // it's the first time we get here).
      if (oldDetector > 0) {
	// Got a new strip.
	AliDebug(10, Form("Add a new strip: FMD%d%c[%2d,%3d] "
			  "(current: FMD%d%c[%2d,%3d])",
			  oldDetector, input.PrevRing(),
			  input.PrevSector() , input.PrevStrip(),
			  detector , input.Ring(), input.Sector(),
			  input.Strip()));
	new ((*array)[n]) AliFMDDigit(oldDetector,
				      input.PrevRing(),
				      input.PrevSector(),
				      input.PrevStrip(),
				      counts[0], counts[1], counts[2]);
	n++;
#if 0
	AliFMDDigit* digit =
	  static_cast<AliFMDDigit*>(fFMD->Digits()->
				    UncheckedAt(fFMD->GetNdigits()-1));
#endif
      }

      if (!next) {
	AliDebug(10, Form("Read %d channels for FMD%d",
			  count + 1, detector));
	break;
      }

      // If we got a new DDL, it means we have a new detector.
      if (ddl != oldDDL) {
	if (detector != 0)
	  AliDebug(10, Form("Read %d channels for FMD%d", count + 1, detector));
	// Reset counts, and update the DDL cache
	count       = 0;
	oldDDL      = ddl;
	// Check that we're processing a FMD detector
	Int_t detId = fReader->GetDetectorID();
	if (detId != (AliFMDParameters::kBaseDDL >> 8)) {
	  AliError(Form("Detector ID %d != %d",
			detId, (AliFMDParameters::kBaseDDL >> 8)));
	  break;
	}
	// Figure out what detector we're deling with
	oldDetector = detector;
	switch (ddl) {
	case 0: detector = 1; break;
	case 1: detector = 2; break;
	case 2: detector = 3; break;
	default:
	  AliError(Form("Unknown DDL 0x%x for FMD", ddl));
	  return;
	}
	AliDebug(10, Form("Reading ADCs for 0x%x  - That is FMD%d",
			  fReader->GetEquipmentId(), detector));
      }
      counts.Reset(-1);
    }

    counts[input.Sample()] = input.Count();

    AliDebug(10, Form("ADC of FMD%d%c[%2d,%3d] += %d",
		      detector, input.Ring(), input.Sector(),
		      input.Strip(), input.Count()));
    oldDetector = detector;
  }
  fTree->Fill();
  return;

}
#endif

//____________________________________________________________________
//
// EOF
//
<commit_msg>Illegal calls to ReadHeader method of the raw reader. The raw reader was not reset afterward and therefore the pointer to the raw data payload was broken (C.Cheshkov)<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/
/* $Id$ */
/** @file    AliFMDRawReader.cxx
    @author  Christian Holm Christensen <cholm@nbi.dk>
    @date    Mon Mar 27 12:45:23 2006
    @brief   Class to read raw data
    @ingroup FMD_rec
*/
//____________________________________________________________________
//
// Class to read ADC values from a AliRawReader object.
//
// This class uses the AliFMDRawStreamer class to read the ALTRO
// formatted data.
//
//          +-------+
//          | TTask |
//          +-------+
//              ^
//              |
//      +-----------------+  <<references>>  +--------------+
//      | AliFMDRawReader |<>----------------| AliRawReader |
//      +-----------------+                  +--------------+
//              |                                  ^
//              | <<uses>>                         |
//              V                                  |
//      +-----------------+      <<uses>>          |
//      | AliFMDRawStream |------------------------+
//      +-----------------+
//              |
//              V
//      +----------------+
//      | AliAltroStream |
//      +----------------+
//
#include <AliLog.h>		// ALILOG_H
#include "AliFMDParameters.h"	// ALIFMDPARAMETERS_H
#include "AliFMDDigit.h"	// ALIFMDDIGIT_H
#include "AliFMDRawStream.h"	// ALIFMDRAWSTREAM_H
#include "AliRawReader.h"	// ALIRAWREADER_H
#include "AliFMDRawReader.h"	// ALIFMDRAWREADER_H
// #include "AliFMDAltroIO.h"	// ALIFMDALTROIO_H
// #include <TArrayI.h>		// ROOT_TArrayI
#include <TTree.h>		// ROOT_TTree
#include <TClonesArray.h>	// ROOT_TClonesArray
// #include <iostream>
// #include <iomanip>

//____________________________________________________________________
ClassImp(AliFMDRawReader)
#if 0
  ; // This is here to keep Emacs for indenting the next line
#endif

//____________________________________________________________________
AliFMDRawReader::AliFMDRawReader(AliRawReader* reader, TTree* tree)
  : TTask("FMDRawReader", "Reader of Raw ADC values from the FMD"),
    fTree(tree),
    fReader(reader),
    fSampleRate(1)
{
  // Default CTOR
}

//____________________________________________________________________
void
AliFMDRawReader::Exec(Option_t*)
{
  // Read the data
  TClonesArray* array = new TClonesArray("AliFMDDigit");
  if (!fTree) {
    AliError("No tree");
    return;
  }
  fTree->Branch("FMD", &array);
  ReadAdcs(array);
  Int_t nWrite = fTree->Fill();
  AliDebug(1, Form("Got a grand total of %d digits, wrote %d bytes to tree",
		   array->GetEntries(), nWrite));
}

#if 1
//____________________________________________________________________
Bool_t
AliFMDRawReader::ReadAdcs(TClonesArray* array)
{
  // Read raw data into the digits array, using AliFMDAltroReader.
  if (!array) {
    AliError("No TClonesArray passed");
    return kFALSE;
  }
  //  if (!fReader->ReadHeader()) {
  //    AliError("Couldn't read header");
  //    return kFALSE;
  //  }
  // Get sample rate
  AliFMDParameters* pars = AliFMDParameters::Instance();
  AliFMDRawStream input(fReader);

  UShort_t stripMin = 0;
  UShort_t stripMax = 127;
  UShort_t preSamp  = 0;

  UInt_t ddl    = 0;
  UInt_t rate   = 0;
  UInt_t last   = 0;
  UInt_t hwaddr = 0;
  // Data array is approx twice the size needed.
  UShort_t data[2048];
  while (input.ReadChannel(ddl, hwaddr, last, data)) {
    AliDebug(5, Form("Read channel 0x%x of size %d", hwaddr, last));
    UShort_t det, sec, str;
    Char_t   ring;
    if (!pars->Hardware2Detector(ddl, hwaddr, det, ring, sec, str)) {
      AliError(Form("Failed to get detector id from DDL %d "
		    "and hardware address 0x%x", ddl, hwaddr));
      continue;
    }
    rate     = pars->GetSampleRate(det, ring, sec, str);
    stripMin = pars->GetMinStrip(det, ring, sec, str);
    stripMax = pars->GetMaxStrip(det, ring, sec, str);
    AliDebug(5, Form("DDL 0x%04x, address 0x%03x maps to FMD%d%c[%2d,%3d]",
		       ddl, hwaddr, det, ring, sec, str));

    // Loop over the `timebins', and make the digits
    for (size_t i = 0; i < last; i++) {
      if (i < preSamp) continue;
      Int_t    n      = array->GetEntries();
      UShort_t curStr = str + stripMin + i / rate;
      if ((curStr-str) > stripMax) {
	AliError(Form("Current strip is %d but DB says max is %d",
		      curStr, stripMax));
      }
      AliDebug(5, Form("making digit for FMD%d%c[%2d,%3d] from sample %4d",
		       det, ring, sec, curStr, i));
      new ((*array)[n]) AliFMDDigit(det, ring, sec, curStr, data[i],
				    (rate >= 2 ? data[i+1] : 0),
				    (rate >= 3 ? data[i+2] : 0));
      if (rate >= 2) i++;
      if (rate >= 3) i++;
    }
  }
  return kTRUE;
}
#else
//____________________________________________________________________
Bool_t
AliFMDRawReader::ReadAdcs(TClonesArray* array)
{
  // Read raw data into the digits array, using AliFMDAltroReader.
  if (!array) {
    AliError("No TClonesArray passed");
    return kFALSE;
  }
  //  if (!fReader->ReadHeader()) {
  //    AliError("Couldn't read header");
  //    return kFALSE;
  //  }
  // Get sample rate
  AliFMDParameters* pars = AliFMDParameters::Instance();

  // Select FMD DDL's
  fReader->Select(AliFMDParameters::kBaseDDL>>8);

  UShort_t stripMin = 0;
  UShort_t stripMax = 127;
  UShort_t preSamp  = 0;

  do {
    UChar_t* cdata;
    if (!fReader->ReadNextData(cdata)) break;
    size_t   nchar = fReader->GetDataSize();
    UShort_t ddl   = AliFMDParameters::kBaseDDL + fReader->GetDDLID();
    UShort_t rate  = 0;
    AliDebug(1, Form("Reading %d bytes (%d 10bit words) from %d",
		     nchar, nchar * 8 / 10, ddl));
    // Make a stream to read from
    std::string str((char*)(cdata), nchar);
    std::istringstream s(str);
    // Prep the reader class.
    AliFMDAltroReader r(s);
    // Data array is approx twice the size needed.
    UShort_t data[2048], hwaddr, last;
    while (r.ReadChannel(hwaddr, last, data) > 0) {
      AliDebug(5, Form("Read channel 0x%x of size %d", hwaddr, last));
      UShort_t det, sec, str;
      Char_t   ring;
      if (!pars->Hardware2Detector(ddl, hwaddr, det, ring, sec, str)) {
	AliError(Form("Failed to detector id from DDL %d "
		      "and hardware address 0x%x", ddl, hwaddr));
	continue;
      }
      rate     = pars->GetSampleRate(det, ring, sec, str);
      stripMin = pars->GetMinStrip(det, ring, sec, str);
      stripMax = pars->GetMaxStrip(det, ring, sec, str);
      AliDebug(5, Form("DDL 0x%04x, address 0x%03x maps to FMD%d%c[%2d,%3d]",
		       ddl, hwaddr, det, ring, sec, str));

      // Loop over the `timebins', and make the digits
      for (size_t i = 0; i < last; i++) {
	if (i < preSamp) continue;
	Int_t    n      = array->GetEntries();
	UShort_t curStr = str + stripMin + i / rate;
	if ((curStr-str) > stripMax) {
	  AliError(Form("Current strip is %d but DB says max is %d",
			curStr, stripMax));
	}
	AliDebug(5, Form("making digit for FMD%d%c[%2d,%3d] from sample %4d",
			 det, ring, sec, curStr, i));
	new ((*array)[n]) AliFMDDigit(det, ring, sec, curStr, data[i],
				      (rate >= 2 ? data[i+1] : 0),
				      (rate >= 3 ? data[i+2] : 0));
	if (rate >= 2) i++;
	if (rate >= 3) i++;
	}
	if (r.IsBof()) break;
    }
  } while (true);
  return kTRUE;
}

// This is the old method, for comparison.   It's really ugly, and far
// too convoluted.
//____________________________________________________________________
void
AliFMDRawReader::Exec(Option_t*)
{
  // Read raw data into the digits array
  //  if (!fReader->ReadHeader()) {
  //    Error("ReadAdcs", "Couldn't read header");
  //    return;
  //  }

  Int_t n = 0;
  TClonesArray* array = new TClonesArray("AliFMDDigit");
  fTree->Branch("FMD", &array);

  // Get sample rate
  AliFMDParameters* pars = AliFMDParameters::Instance();
  fSampleRate = pars->GetSampleRate(AliFMDParameters::kBaseDDL);

  // Use AliAltroRawStream to read the ALTRO format.  No need to
  // reinvent the wheel :-)
  AliFMDRawStream input(fReader, fSampleRate);
  // Select FMD DDL's
  fReader->Select(AliFMDParameters::kBaseDDL);

  Int_t    oldDDL      = -1;
  Int_t    count       = 0;
  UShort_t detector    = 1; // Must be one here
  UShort_t oldDetector = 0;
  Bool_t   next        = kTRUE;

  // local Cache
  TArrayI counts(10);
  counts.Reset(-1);

  // Loop over data in file
  while (next) {
    next = input.Next();

    count++;
    Int_t ddl = fReader->GetDDLID();
    AliDebug(10, Form("Current DDL is %d", ddl));
    if (ddl != oldDDL || input.IsNewStrip() || !next) {
      // Make a new digit, if we have some data (oldDetector == 0,
      // means that we haven't really read anything yet - that is,
      // it's the first time we get here).
      if (oldDetector > 0) {
	// Got a new strip.
	AliDebug(10, Form("Add a new strip: FMD%d%c[%2d,%3d] "
			  "(current: FMD%d%c[%2d,%3d])",
			  oldDetector, input.PrevRing(),
			  input.PrevSector() , input.PrevStrip(),
			  detector , input.Ring(), input.Sector(),
			  input.Strip()));
	new ((*array)[n]) AliFMDDigit(oldDetector,
				      input.PrevRing(),
				      input.PrevSector(),
				      input.PrevStrip(),
				      counts[0], counts[1], counts[2]);
	n++;
#if 0
	AliFMDDigit* digit =
	  static_cast<AliFMDDigit*>(fFMD->Digits()->
				    UncheckedAt(fFMD->GetNdigits()-1));
#endif
      }

      if (!next) {
	AliDebug(10, Form("Read %d channels for FMD%d",
			  count + 1, detector));
	break;
      }

      // If we got a new DDL, it means we have a new detector.
      if (ddl != oldDDL) {
	if (detector != 0)
	  AliDebug(10, Form("Read %d channels for FMD%d", count + 1, detector));
	// Reset counts, and update the DDL cache
	count       = 0;
	oldDDL      = ddl;
	// Check that we're processing a FMD detector
	Int_t detId = fReader->GetDetectorID();
	if (detId != (AliFMDParameters::kBaseDDL >> 8)) {
	  AliError(Form("Detector ID %d != %d",
			detId, (AliFMDParameters::kBaseDDL >> 8)));
	  break;
	}
	// Figure out what detector we're deling with
	oldDetector = detector;
	switch (ddl) {
	case 0: detector = 1; break;
	case 1: detector = 2; break;
	case 2: detector = 3; break;
	default:
	  AliError(Form("Unknown DDL 0x%x for FMD", ddl));
	  return;
	}
	AliDebug(10, Form("Reading ADCs for 0x%x  - That is FMD%d",
			  fReader->GetEquipmentId(), detector));
      }
      counts.Reset(-1);
    }

    counts[input.Sample()] = input.Count();

    AliDebug(10, Form("ADC of FMD%d%c[%2d,%3d] += %d",
		      detector, input.Ring(), input.Sector(),
		      input.Strip(), input.Count()));
    oldDetector = detector;
  }
  fTree->Fill();
  return;

}
#endif

//____________________________________________________________________
//
// EOF
//
<|endoftext|>


<commit_before>// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/app_list/views/search_result_actions_view.h"

#include "ui/app_list/views/search_result_actions_view_delegate.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/views/border.h"
#include "ui/views/controls/button/blue_button.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/views/layout/box_layout.h"

namespace app_list {

SearchResultActionsView::SearchResultActionsView(
    SearchResultActionsViewDelegate* delegate)
    : delegate_(delegate) {
  SetLayoutManager(
      new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 10, 0));
}

SearchResultActionsView::~SearchResultActionsView() {}

void SearchResultActionsView::SetActions(const SearchResult::Actions& actions) {
  RemoveAllChildViews(true);

  for (size_t i = 0; i < actions.size(); ++i) {
    const SearchResult::Action& action = actions.at(i);
    if (action.label_text.empty())
      CreateImageButton(action);
    else
      CreateBlueButton(action);
  }

  PreferredSizeChanged();
}

void SearchResultActionsView::CreateImageButton(
    const SearchResult::Action& action) {
  views::ImageButton* button = new views::ImageButton(this);
  button->set_border(views::Border::CreateEmptyBorder(0, 4, 0, 4));
  button->SetImageAlignment(views::ImageButton::ALIGN_CENTER,
                            views::ImageButton::ALIGN_MIDDLE);
  button->SetImage(views::CustomButton::STATE_NORMAL, &action.base_image);
  button->SetImage(views::CustomButton::STATE_HOVERED, &action.hover_image);
  button->SetImage(views::CustomButton::STATE_PRESSED, &action.pressed_image);
  button->SetTooltipText(action.tooltip_text);
  AddChildView(button);
}

void SearchResultActionsView::CreateBlueButton(
    const SearchResult::Action& action) {
  views::BlueButton* button = new views::BlueButton(this, action.label_text);
  button->SetTooltipText(action.tooltip_text);
  button->SetFont(ui::ResourceBundle::GetSharedInstance().GetFont(
      ui::ResourceBundle::SmallBoldFont));
  AddChildView(button);
}

void SearchResultActionsView::ButtonPressed(views::Button* sender,
                                            const ui::Event& event) {
  if (!delegate_)
    return;

  const int index = GetIndexOf(sender);
  DCHECK_NE(-1, index);
  delegate_->OnSearchResultActionActivated(index, event.flags());
}

}  // namespace app_list
<commit_msg>app_list: Blue button in result actions should not get focus.<commit_after>// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/app_list/views/search_result_actions_view.h"

#include "ui/app_list/views/search_result_actions_view_delegate.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/views/border.h"
#include "ui/views/controls/button/blue_button.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/views/layout/box_layout.h"

namespace app_list {

SearchResultActionsView::SearchResultActionsView(
    SearchResultActionsViewDelegate* delegate)
    : delegate_(delegate) {
  SetLayoutManager(
      new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 10, 0));
}

SearchResultActionsView::~SearchResultActionsView() {}

void SearchResultActionsView::SetActions(const SearchResult::Actions& actions) {
  RemoveAllChildViews(true);

  for (size_t i = 0; i < actions.size(); ++i) {
    const SearchResult::Action& action = actions.at(i);
    if (action.label_text.empty())
      CreateImageButton(action);
    else
      CreateBlueButton(action);
  }

  PreferredSizeChanged();
}

void SearchResultActionsView::CreateImageButton(
    const SearchResult::Action& action) {
  views::ImageButton* button = new views::ImageButton(this);
  button->set_border(views::Border::CreateEmptyBorder(0, 4, 0, 4));
  button->SetImageAlignment(views::ImageButton::ALIGN_CENTER,
                            views::ImageButton::ALIGN_MIDDLE);
  button->SetImage(views::CustomButton::STATE_NORMAL, &action.base_image);
  button->SetImage(views::CustomButton::STATE_HOVERED, &action.hover_image);
  button->SetImage(views::CustomButton::STATE_PRESSED, &action.pressed_image);
  button->SetTooltipText(action.tooltip_text);
  AddChildView(button);
}

void SearchResultActionsView::CreateBlueButton(
    const SearchResult::Action& action) {
  views::BlueButton* button = new views::BlueButton(this, action.label_text);
  button->SetTooltipText(action.tooltip_text);
  button->SetFont(ui::ResourceBundle::GetSharedInstance().GetFont(
      ui::ResourceBundle::SmallBoldFont));
  button->set_focusable(false);
  AddChildView(button);
}

void SearchResultActionsView::ButtonPressed(views::Button* sender,
                                            const ui::Event& event) {
  if (!delegate_)
    return;

  const int index = GetIndexOf(sender);
  DCHECK_NE(-1, index);
  delegate_->OnSearchResultActionActivated(index, event.flags());
}

}  // namespace app_list
<|endoftext|>


<commit_before>#include "notendaui.h"
#include <iostream>
#include <string>
#include <utility>
#include <algorithm>

using namespace std;

NotendaUI::NotendaUI()
{

}

bool check = true;

void NotendaUI::keyra()
{
    //TEMP
    vector<tolvufolk> data = _service.getTolvufolk();

    string nName;
    string gGender;
    int bYear;
    int dYear;

    skrifaUt();

    do
        {
        check = true;
        string skipun;
        cin >> skipun;

        if (skipun == "list" || skipun == "l")
        {
            skrifaUt();
            printList(data);
            continueUI();
        }
        else if (skipun == "sort"|| skipun == "so")
        {
            skrifaUt();
            sortOptions(data);
            continueUI();
        }
        else if (skipun == "add" || skipun == "a")
        {
            skrifaUt();
            cout << "Enter name: ";
            cin.ignore();
            getline(cin,nName);

            cout << "Enter gender(kk/kvk) [lowercase]: ";
            cin >> gGender;

            while (gGender != "kk" && gGender != "kvk")
            {
                cerr << "Input not valid, try again: ";
                cin >> gGender;
            }

            cout << "Enter year of birth: ";
            cin >> bYear;

            while (0 > bYear)
            {
                cerr << "Input not valid, try again: ";
                cin >> bYear;
            }

            cout << "Enter year of death(-1 if still alive): ";
            cin >> dYear;

            while (-1 > dYear)
            {
                cerr << "Input not valid, try again: ";
                cin >> dYear;
                cout << endl;
            }

            tolvufolk Tempr(nName, gGender, bYear, dYear);
            data.push_back(Tempr);
            _service.addTolvufolk(Tempr);
            printList(data);
            continueUI();

        }
        else if (skipun == "delete" || skipun == "d")
        {
            skrifaUt();
            printList(data);
            continueUI();

        }

        else if (skipun == "update" || skipun == "u")
        {

            skrifaUt();
            updatePerson(data);
            continueUI();
        }

        else if (skipun == "search" || skipun == "s")
        {
            skrifaUt();
            searchName(data);
            continueUI();
        }

        else if (skipun == "purge" || skipun == "p")
        {
            skrifaUt();
            cout << "By the Emperor, are you sure? (Y/N): ";
            cin >> skipun;

            if (skipun == "Y" || skipun == "y")
            {
                cout << "Are you really sure? This will EXTERMINATE ALL ENTRIES. (Y/N): ";
                cin >> skipun;

                if (skipun == "Y" || skipun == "y")
                {
                    cout << "Acknowledged, by your will, all ENTRIES will be EXTERMINATED.";
                    // TODO; Erase everything
                    continueUI();

                }
                else
                {
                    cout << "Purge canceled." << endl;
                    continueUI();
                }

            }
            else
            {
                cout << "Purge canceled." << endl;
                continueUI();
            }

        }

        else if (skipun == "quit" || skipun == "q")
        {
            check = true;
        }

        else
        {
            skrifaUt();
            cerr << "Input not valid, try again: ";
            check = false;
        }
    } while (check == false);
}

void NotendaUI::skrifaUt()
{
    system("cls");

    cout << "*==================================================================*" << endl;
    cout << "*||Please enter one the following commands                       ||*" << endl;
    cout << "*==================================================================*" << endl;
    cout << "*||list - Shows a list of all known entries in the database.     ||*" << endl;
    cout << "*||add - Add a new entry into the database.                      ||*" << endl;
    cout << "*||delete - Removes an entry from the database.                  ||*" << endl;
    cout << "*||update - Updates an entry from the database.                  ||*" << endl;
    cout << "*||search - Search for an entry from the database.               ||*" << endl;
    cout << "*||purge - Removes every entry from the database.                ||*" << endl;
    cout << "*||quit - Exits/quits the program                                ||*" << endl;
    cout << "*==================================================================*" << endl;
}
void NotendaUI::updatePerson(vector<tolvufolk>& data)
{
    int persNR;
    string skipunin;
    cout << "Number of Scientist: ";
    cin >> persNR;
    persNR --;

    cout << "*==============================================================*" << endl;
    cout << "*||Please enter one the following command*                   ||*" << endl;
    cout << "*==============================================================*" << endl;
    cout << "*||name - update name                                        ||*" << endl;
    cout << "*||gender - update gender                                    ||*" << endl;
    cout << "*||birth - update year of birth                              ||*" << endl;
    cout << "*||death - update year of death                              ||*" << endl;
    cout << "*==============================================================*" << endl;
    cin >> skipunin;

    if (skipunin == "name" || skipunin == "n")
    {
        string nafn;
        cout << "Enter updated name for " << data[persNR].getNafn() << ": ";
        cin.ignore();
        getline(cin,nafn);
        data[persNR].updNafn(nafn);
    }

    else if (skipunin == "gender" || skipunin == "g")
    {
        string newgend;
        cout << "Enter updated gender for " << data[persNR].getNafn() << ": ";
        cin >> newgend;
        while (newgend != "kk" && newgend != "kvk")
        {
            cerr << "Input not valid, try again: ";
            cin >> newgend;
        }
        data[persNR].updGender(newgend);
    }

    else if (skipunin == "birth" || skipunin == "b")
    {
        int nytt;
        cout << "Enter updated year of birth for " << data[persNR].getNafn() << ": ";
        cin >> nytt;
        data[persNR].updFaedingarar(nytt);
    }

    else if (skipunin == "death" || skipunin == "d")
    {
        int nytt;
        cout << "Enter updated year of death for " << data[persNR].getNafn() << ": ";
        cin >> nytt;
        data[persNR].updDanarar(nytt);
    }
}
void NotendaUI::searchOptions()
{
    system("cls");
    cout << "*==================================================================*" << endl;
    cout << "*||Please enter one the following command                        ||*" << endl;
    cout << "*==================================================================*" << endl;
    cout << "*||name  - Search by name, please write 'name'                   ||*" << endl;
    cout << "*||age   - Search by age, please write 'age'                     ||*" << endl;
    cout << "*||birth - Search by year of birth, please write 'birth'         ||*" << endl;
    cout << "*||death - Search by year of death, please write 'death'         ||*" << endl;
    cout << "*==================================================================*" << endl;
}

void NotendaUI::printList(const vector<tolvufolk>& data)
{
    for (size_t i = 0; i < data.size(); i++)
    {
        cout << "Scientist number: " << i + 1 << endl;
        cout << data[i] << endl;
    }
}

void NotendaUI::searchName(const vector<tolvufolk>& data)
{
    searchOptions();
    string skipunin;
    cin >> skipunin;

    if (skipunin == "name" || skipunin == "n")
    {
        searchOptions();
        string nafn;
        cout << "Name to search: ";
        cin.ignore();
        getline(cin,nafn);
        cout << endl;
        for(size_t i = 0; i < data.size(); i++)
        {
            if (nafn == data[i].getNafn() )
            {
                cout << data[i];
            }
        }
        cout << endl;
    }

    else if (skipunin == "age" || skipunin == "a")
    {
        searchOptions();
        int age;
        cout << "Age to search: ";
        cin >> age;
        cout << endl;
        for(size_t i = 0; i < data.size(); i++)
        {
            if (age == (data[i].getDanarar() - data[i].getFaedingarar() ) )
            {
                cout << data[i];
            }
        }
        cout << endl;
    }

    else if (skipunin == "birth" || skipunin == "b")
    {
        searchOptions();
        int birth;
        cout << "Year of birth to search: ";
        cin >> birth;
        cout << endl;
        for(size_t i = 0; i < data.size(); i++)
        {
            if (birth == data[i].getFaedingarar() )
            {
                cout << data[i];
            }
        }
        cout << endl;
    }

    else if (skipunin == "death" || skipunin == "d")
    {
        searchOptions();
        int death;
        cout << "Year of birth to search: ";
        cin >> death;
        cout << endl;
        for(size_t i = 0; i < data.size(); i++)
        {
            if (death == data[i].getDanarar() )
            {
                cout << data[i];
            }
        }
        cout << endl;
    }

}

void NotendaUI::sortOptions(vector<tolvufolk>& data)
{
    system("cls");
    cout << "*==============================================================*" << endl;
    cout << "*||Please enter one the following command                    ||*" << endl;
    cout << "*==============================================================*" << endl;
    cout << "*||name - Sort by name                                     ||*" << endl;
    cout << "*||age - Sort by age                                       ||*" << endl;
    cout << "*||birth - Sort by year of birth                           ||*" << endl;
    cout << "*||death - Sort by year of death                           ||*" << endl;
    cout << "*==============================================================*" << endl;

    string skipunin;
    cin >> skipunin;

    if (skipunin == "name" || skipunin == "n")
    {
    system("cls");
    cout << "*==============================================================*" << endl;
    cout << "*||Please enter one the following command                    ||*" << endl;
    cout << "*==============================================================*" << endl;
    cout << "*||ascending - Sort names by ascending order                 ||*" << endl;
    cout << "*||descending - Sort names by descending order               ||*" << endl;

        string skipunin;
        cin >> skipunin;

        if(skipunin == "ascending" || skipunin == "a")
        {
            //vector<tolvufolk> result;
            //result = _service.sortByName(data);
        }
    }
}

void NotendaUI::continueUI()
{
    string answer;
    cout << "Continue? (Y/N): ";
    cin >> answer;
    if (answer == "Y" || answer == "y")
    {
        skrifaUt();
        check = false;
    }
    else
    {
        check = true;
    }

}
<commit_msg>cosmic changes<commit_after>#include "notendaui.h"
#include <iostream>
#include <string>
#include <utility>
#include <algorithm>

using namespace std;

NotendaUI::NotendaUI()
{

}

bool check = true;

void NotendaUI::keyra()
{
    //TEMP
    vector<tolvufolk> data = _service.getTolvufolk();

    string nName;
    string gGender;
    int bYear;
    int dYear;

    skrifaUt();

    do
        {
        check = true;
        string skipun;
        cin >> skipun;

        if (skipun == "list" || skipun == "l")
        {
            skrifaUt();
            printList(data);
            continueUI();
        }
        else if (skipun == "sort"|| skipun == "so")
        {
            skrifaUt();
            sortOptions(data);
            continueUI();
        }
        else if (skipun == "add" || skipun == "a")
        {
            skrifaUt();
            cout << "Enter name: ";
            cin.ignore();
            getline(cin,nName);

            cout << "Enter gender(kk/kvk) [lowercase]: ";
            cin >> gGender;

            while (gGender != "kk" && gGender != "kvk")
            {
                cerr << "Input not valid, try again: ";
                cin >> gGender;
            }

            cout << "Enter year of birth: ";
            cin >> bYear;

            while (0 > bYear)
            {
                cerr << "Input not valid, try again: ";
                cin >> bYear;
            }

            cout << "Enter year of death(-1 if still alive): ";
            cin >> dYear;

            while (-1 > dYear)
            {
                cerr << "Input not valid, try again: ";
                cin >> dYear;
                cout << endl;
            }

            tolvufolk Tempr(nName, gGender, bYear, dYear);
            data.push_back(Tempr);
            _service.addTolvufolk(Tempr);
            printList(data);
            continueUI();

        }
        else if (skipun == "delete" || skipun == "d")
        {
            skrifaUt();
            printList(data);
            continueUI();

        }

        else if (skipun == "update" || skipun == "u")
        {

            skrifaUt();
            updatePerson(data);
            continueUI();
        }

        else if (skipun == "search" || skipun == "s")
        {
            skrifaUt();
            searchName(data);
            continueUI();
        }

        else if (skipun == "purge" || skipun == "p")
        {
            skrifaUt();
            cout << "By the Emperor, are you sure? (Y/N): ";
            cin >> skipun;

            if (skipun == "Y" || skipun == "y")
            {
                cout << "Are you really sure? This will EXTERMINATE ALL ENTRIES. (Y/N): ";
                cin >> skipun;

                if (skipun == "Y" || skipun == "y")
                {
                    cout << "Acknowledged, by your will, all ENTRIES will be EXTERMINATED.";
                    // TODO; Erase everything
                    continueUI();

                }
                else
                {
                    cout << "Purge canceled." << endl;
                    continueUI();
                }

            }
            else
            {
                cout << "Purge canceled." << endl;
                continueUI();
            }

        }

        else if (skipun == "quit" || skipun == "q")
        {
            check = true;
        }

        else
        {
            skrifaUt();
            cerr << "Input not valid, try again: ";
            check = false;
        }
    } while (check == false);
}

void NotendaUI::skrifaUt()
{
    system("cls");

    cout << "*==================================================================*" << endl;
    cout << "*||Please enter one the following commands                       ||*" << endl;
    cout << "*==================================================================*" << endl;
    cout << "*||list - Shows a list of all known entries in the database.     ||*" << endl;
    cout << "*||add - Add a new entry into the database.                      ||*" << endl;
    cout << "*||delete - Removes an entry from the database.                  ||*" << endl;
    cout << "*||update - Updates an entry from the database.                  ||*" << endl;
    cout << "*||search - Search for an entry from the database.               ||*" << endl;
    cout << "*||purge - Removes every entry from the database.                ||*" << endl;
    cout << "*||quit - Exits/quits the program                                ||*" << endl;
    cout << "*==================================================================*" << endl;
}
void NotendaUI::updatePerson(vector<tolvufolk>& data)
{
    int persNR;
    string skipunin;
    cout << "Number of Scientist: ";
    cin >> persNR;
    persNR --;

    cout << "*==================================================================*" << endl;
    cout << "*||Please enter one the following command*                       ||*" << endl;
    cout << "*==============================================================*" << endl;
    cout << "*||name - update name, please write 'name'                       ||*" << endl;
    cout << "*||gender - update gender, please write 'gender'                 ||*" << endl;
    cout << "*||birth - update year of birth, please write 'birth'            ||*" << endl;
    cout << "*||death - update year of death, please write 'deat'             ||*" << endl;
    cout << "*==================================================================*" << endl;
    cin >> skipunin;

    if (skipunin == "name" || skipunin == "n")
    {
        string nafn;
        cout << "Enter updated name for " << data[persNR].getNafn() << ": ";
        cin.ignore();
        getline(cin,nafn);
        data[persNR].updNafn(nafn);
    }

    else if (skipunin == "gender" || skipunin == "g")
    {
        string newgend;
        cout << "Enter updated gender for " << data[persNR].getNafn() << ": ";
        cin >> newgend;
        while (newgend != "kk" && newgend != "kvk")
        {
            cerr << "Input not valid, try again: ";
            cin >> newgend;
        }
        data[persNR].updGender(newgend);
    }

    else if (skipunin == "birth" || skipunin == "b")
    {
        int nytt;
        cout << "Enter updated year of birth for " << data[persNR].getNafn() << ": ";
        cin >> nytt;
        data[persNR].updFaedingarar(nytt);
    }

    else if (skipunin == "death" || skipunin == "d")
    {
        int nytt;
        cout << "Enter updated year of death for " << data[persNR].getNafn() << ": ";
        cin >> nytt;
        data[persNR].updDanarar(nytt);
    }
}
void NotendaUI::searchOptions()
{
    system("cls");
    cout << "*==================================================================*" << endl;
    cout << "*||Please enter one the following command                        ||*" << endl;
    cout << "*==================================================================*" << endl;
    cout << "*||name  - Search by name, please write 'name'                   ||*" << endl;
    cout << "*||age   - Search by age, please write 'age'                     ||*" << endl;
    cout << "*||birth - Search by year of birth, please write 'birth'         ||*" << endl;
    cout << "*||death - Search by year of death, please write 'death'         ||*" << endl;
    cout << "*==================================================================*" << endl;
}

void NotendaUI::printList(const vector<tolvufolk>& data)
{
    for (size_t i = 0; i < data.size(); i++)
    {
        cout << "Scientist number: " << i + 1 << endl;
        cout << data[i] << endl;
    }
}

void NotendaUI::searchName(const vector<tolvufolk>& data)
{
    searchOptions();
    string skipunin;
    cin >> skipunin;

    if (skipunin == "name" || skipunin == "n")
    {
        searchOptions();
        string nafn;
        cout << "Name to search: ";
        cin.ignore();
        getline(cin,nafn);
        cout << endl;
        for(size_t i = 0; i < data.size(); i++)
        {
            if (nafn == data[i].getNafn() )
            {
                cout << data[i];
            }
        }
        cout << endl;
    }

    else if (skipunin == "age" || skipunin == "a")
    {
        searchOptions();
        int age;
        cout << "Age to search: ";
        cin >> age;
        cout << endl;
        for(size_t i = 0; i < data.size(); i++)
        {
            if (age == (data[i].getDanarar() - data[i].getFaedingarar() ) )
            {
                cout << data[i];
            }
        }
        cout << endl;
    }

    else if (skipunin == "birth" || skipunin == "b")
    {
        searchOptions();
        int birth;
        cout << "Year of birth to search: ";
        cin >> birth;
        cout << endl;
        for(size_t i = 0; i < data.size(); i++)
        {
            if (birth == data[i].getFaedingarar() )
            {
                cout << data[i];
            }
        }
        cout << endl;
    }

    else if (skipunin == "death" || skipunin == "d")
    {
        searchOptions();
        int death;
        cout << "Year of birth to search: ";
        cin >> death;
        cout << endl;
        for(size_t i = 0; i < data.size(); i++)
        {
            if (death == data[i].getDanarar() )
            {
                cout << data[i];
            }
        }
        cout << endl;
    }

}

void NotendaUI::sortOptions(vector<tolvufolk>& data)
{
    system("cls");
    cout << "*==================================================================*" << endl;
    cout << "*||Please enter one the following command                        ||*" << endl;
    cout << "*==================================================================*" << endl;
    cout << "*||name - Sort by name, please write 'name'                      ||*" << endl;
    cout << "*||age - Sort by age, please write 'age'                         ||*" << endl;
    cout << "*||birth - Sort by year of birth, please write 'birth'           ||*" << endl;
    cout << "*||death - Sort by year of death, please write 'death'           ||*" << endl;
    cout << "*==================================================================*" << endl;

    string skipunin;
    cin >> skipunin;

    if (skipunin == "name" || skipunin == "n")
    {
    system("cls");
    cout << "*==================================================================*" << endl;
    cout << "*||Please enter one the following command                        ||*" << endl;
    cout << "*==================================================================*" << endl;
    cout << "*||ascending - Sort names by ascending order                     ||*" << endl;
    cout << "*||descending - Sort names by descending order                   ||*" << endl;
    cout << "*==================================================================*" << endl;

        string skipunin;
        cin >> skipunin;

        if(skipunin == "ascending" || skipunin == "a")
        {
            //vector<tolvufolk> result;
            //result = _service.sortByName(data);
        }
    }
}

void NotendaUI::continueUI()
{
    string answer;
    cout << "Continue? (Y/N): ";
    cin >> answer;
    if (answer == "Y" || answer == "y")
    {
        skrifaUt();
        check = false;
    }
    else
    {
        check = true;
    }

}
<|endoftext|>


<commit_before>#ifndef JOINT_DEVKIT_UTIL_INTRUSIVEREFCOUNTER_HPP
#define JOINT_DEVKIT_UTIL_INTRUSIVEREFCOUNTER_HPP

#include <joint/devkit/Config.hpp>
#include <joint/util/Assert.h>

#include <atomic>

namespace joint {
namespace devkit
{

	template < typename Derived_ >
	class IntrusiveRefCounter
	{
	private:
		std::atomic<int>   _refCount{1};

	public:
		IntrusiveRefCounter() = default;

		IntrusiveRefCounter(const IntrusiveRefCounter&) = delete;
		IntrusiveRefCounter& operator = (const IntrusiveRefCounter&) = delete;

		void AddRef() JOINT_DEVKIT_NOEXCEPT
		{
			int newVal = ++_refCount;
			JOINT_CORE_ASSERT(newVal > 1);
		}

		void Release() JOINT_DEVKIT_NOEXCEPT
		{
			int newVal = --_refCount;
			JOINT_CORE_ASSERT(newVal >= 0);
			if (newVal == 0)
				delete DerivedPtr();
		}

	protected:
		virtual ~IntrusiveRefCounter() = default;

	private:
		Derived_* DerivedPtr() JOINT_DEVKIT_NOEXCEPT
		{ return static_cast<Derived_*>(this); }
	};

}}

#endif
<commit_msg>Fix gcc-4.8 build<commit_after>#ifndef JOINT_DEVKIT_UTIL_INTRUSIVEREFCOUNTER_HPP
#define JOINT_DEVKIT_UTIL_INTRUSIVEREFCOUNTER_HPP

#include <joint/devkit/Config.hpp>
#include <joint/util/Assert.h>

#include <atomic>

namespace joint {
namespace devkit
{

	template < typename Derived_ >
	class IntrusiveRefCounter
	{
	private:
		std::atomic<int>   _refCount;

	public:
		IntrusiveRefCounter()
			: _refCount(1)
		{ }

		IntrusiveRefCounter(const IntrusiveRefCounter&) = delete;
		IntrusiveRefCounter& operator = (const IntrusiveRefCounter&) = delete;

		void AddRef() JOINT_DEVKIT_NOEXCEPT
		{
			int newVal = ++_refCount;
			JOINT_CORE_ASSERT(newVal > 1);
		}

		void Release() JOINT_DEVKIT_NOEXCEPT
		{
			int newVal = --_refCount;
			JOINT_CORE_ASSERT(newVal >= 0);
			if (newVal == 0)
				delete DerivedPtr();
		}

	protected:
		virtual ~IntrusiveRefCounter() = default;

	private:
		Derived_* DerivedPtr() JOINT_DEVKIT_NOEXCEPT
		{ return static_cast<Derived_*>(this); }
	};

}}

#endif
<|endoftext|>


<commit_before>/** \file    augment_mohr_titles_with_dois
 *  \brief   Augment title data of printed works with dois if no
 *           electronic version exists in IxTheo data
 *  \author  Johannes Riedl
 */

/*
    Copyright (C) 2021 Library of the University of Tübingen

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <iostream>
#include <unordered_map>
#include <vector>
#include "MARC.h"
#include "StringUtil.h"
#include "util.h"

namespace {

[[noreturn]] void Usage() {
    ::Usage("marc_input mohr_book_data marc_output");
}

void CreatePPNToISBNMappings(MARC::Reader * const marc_reader,
                          std::unordered_multimap<std::string, std::string> * const print_ppn_to_isbn_map,
                          std::unordered_multimap<std::string, std::string> * const electronic_ppn_to_isbn_map)
{
    while (MARC::Record record = marc_reader->read()) {

        if (record.isMonograph()) {
            const auto &isbns(record.getISBNs());
            if (record.isElectronicResource()) {
                for (const auto &isbn : isbns)
                     electronic_ppn_to_isbn_map->emplace(record.getControlNumber(), isbn);
            } else {
                for (const auto &isbn : isbns)
                     print_ppn_to_isbn_map->emplace(record.getControlNumber(), isbn);
            }
       }
    }
}

void CreateMohrISBNToDOIMapping(MARC::Reader * const marc_reader,
                               std::unordered_map<std::string, std::string> * const mohr_isbn_to_doi_map)
{
   while (MARC::Record record = marc_reader->read()) {
          const auto dois(record.getDOIs());
          if (dois.size() != 1)
              LOG_ERROR("No unique DOI for \"" + record.getControlNumber() + '"');

          // Get "native" ISBNs
          for (const auto &native_isbn : record.getISBNs())
               mohr_isbn_to_doi_map->emplace(native_isbn, *(dois.begin()));

          // Get "alternative" print ISBN
          for (const auto &alternative_isbn : record.getSubfieldValues("776", 'z'))
               mohr_isbn_to_doi_map->emplace(alternative_isbn, *(dois.begin()));
   }
}

void ProcessRecords(MARC::Reader * const marc_reader,
                    MARC::Writer * const marc_writer,
                    const std::unordered_multimap<std::string, std::string> &print_ppn_to_isbn_map,
                    const std::unordered_multimap<std::string, std::string> &electronic_ppn_to_isbn_map,
                    const std::unordered_map<std::string, std::string> &mohr_isbn_to_doi_map)
{
    unsigned count(0), new_electronic_dois(0), new_print_dois(0);
    while (MARC::Record record = marc_reader->read()) {
        ++count;
        const std::string ppn(record.getControlNumber());
        if (electronic_ppn_to_isbn_map.contains(ppn)) {
            const auto electronic_isbns(electronic_ppn_to_isbn_map.equal_range(ppn));
            for (auto ppn_and_isbn(electronic_isbns.first); ppn_and_isbn != electronic_isbns.second; ++ppn_and_isbn) {
                 const auto isbn(ppn_and_isbn->second);
                 if (mohr_isbn_to_doi_map.find(isbn) != mohr_isbn_to_doi_map.end()) {
                     const auto &record_dois(record.getDOIs());
                     const auto doi_for_isbn(mohr_isbn_to_doi_map.find(isbn)->second);
                     // Insert doi if not present
                     if (std::find(record_dois.begin(), record_dois.end(), doi_for_isbn) == record_dois.end()) {
                         LOG_INFO("Inserting previously not existing DOI \"" + doi_for_isbn + "\" for electronic record " +
                                  "\"" + record.getControlNumber());
                         record.insertField("024", { { 'a', doi_for_isbn }, { '2', "doi" } });
                         ++new_electronic_dois;
                     }
                     break;
                 }
             }
        } else if (print_ppn_to_isbn_map.contains(ppn)) {
            const auto print_isbns(print_ppn_to_isbn_map.equal_range(ppn));
            for (auto ppn_and_isbn(print_isbns.first); ppn_and_isbn != print_isbns.second; ++ppn_and_isbn) {
                 const auto isbn(ppn_and_isbn->second);
                 if (mohr_isbn_to_doi_map.find(isbn) != mohr_isbn_to_doi_map.end()) {
                     const auto &record_dois(record.getDOIs());
                     const auto doi_for_isbn(mohr_isbn_to_doi_map.find(isbn)->second);
                     // Insert doi if not present
                     if (std::find(record_dois.begin(), record_dois.end(), doi_for_isbn) == record_dois.end()) {
                         LOG_INFO("Inserting previously not existing DOI \"" + doi_for_isbn + "\" for print record " +
                                  "\"" + record.getControlNumber());
                         record.insertField("024", { { 'a', doi_for_isbn }, { '2', "doi" } });
                         ++new_print_dois;
                     }
                     break;
                 }
            }
        }
        marc_writer->write(record);
    }
    LOG_INFO("Inserted " + std::to_string(new_electronic_dois) + " new electronic DOIs and " +
             std::to_string(new_print_dois) + " print DOIs of " + std::to_string(count) + " records altogether");
}

} // unnamed namespace

int Main(int argc, char **argv) {
    if (argc != 4)
        Usage();

    const std::string marc_input_filename(argv[1]);
    const std::string mohr_book_data(argv[2]);
    const std::string marc_output_filename(argv[3]);
    if (unlikely(marc_input_filename == marc_output_filename))
        LOG_ERROR("Title data input file name equals output file name!");
    if (unlikely(mohr_book_data == marc_output_filename))
        LOG_ERROR("Mohr marc data input file name equals output file name!");

    std::unique_ptr<MARC::Reader> marc_reader(MARC::Reader::Factory(marc_input_filename));
    std::unique_ptr<MARC::Reader> mohr_book_reader(MARC::Reader::Factory(mohr_book_data));
    std::unique_ptr<MARC::Writer> marc_writer(MARC::Writer::Factory(marc_output_filename));

    std::unordered_multimap<std::string, std::string> print_ppn_to_isbn_map;
    std::unordered_multimap<std::string, std::string> electronic_ppn_to_isbn_map;
    std::unordered_map<std::string, std::string> mohr_isbn_to_doi_map;
    LOG_INFO("Create ISBN to DOI map from Mohr data");
    CreateMohrISBNToDOIMapping(mohr_book_reader.get(), &mohr_isbn_to_doi_map);
    LOG_INFO("We extracted " + std::to_string(mohr_isbn_to_doi_map.size())  + " ISBN to DOI mappings");
    LOG_INFO("Create PPN to ISBN Mappings");
    CreatePPNToISBNMappings(marc_reader.get(), &print_ppn_to_isbn_map, &electronic_ppn_to_isbn_map);
    LOG_INFO("We extracted " + std::to_string(print_ppn_to_isbn_map.size()) + " print PPN to ISBN mappings");
    LOG_INFO("We extracted " + std::to_string(electronic_ppn_to_isbn_map.size()) + " electronic PPN to ISBN mappings");
    LOG_INFO("Augmenting records");
    marc_reader->rewind();
    ProcessRecords(marc_reader.get(), marc_writer.get(),
                   print_ppn_to_isbn_map, electronic_ppn_to_isbn_map, mohr_isbn_to_doi_map);

    return EXIT_SUCCESS;
}

<commit_msg>Two more lines<commit_after>/** \file    augment_mohr_titles_with_dois
 *  \brief   Augment title data of printed works with dois if no
 *           electronic version exists in IxTheo data
 *  \author  Johannes Riedl
 */

/*
    Copyright (C) 2021 Library of the University of Tübingen

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <iostream>
#include <unordered_map>
#include <vector>
#include "MARC.h"
#include "StringUtil.h"
#include "util.h"

namespace {

[[noreturn]] void Usage() {
    ::Usage("marc_input mohr_book_data marc_output");
}

void CreatePPNToISBNMappings(MARC::Reader * const marc_reader,
                          std::unordered_multimap<std::string, std::string> * const print_ppn_to_isbn_map,
                          std::unordered_multimap<std::string, std::string> * const electronic_ppn_to_isbn_map)
{
    while (MARC::Record record = marc_reader->read()) {

        if (record.isMonograph()) {
            const auto &isbns(record.getISBNs());
            if (record.isElectronicResource()) {
                for (const auto &isbn : isbns)
                     electronic_ppn_to_isbn_map->emplace(record.getControlNumber(), isbn);
            } else {
                for (const auto &isbn : isbns)
                     print_ppn_to_isbn_map->emplace(record.getControlNumber(), isbn);
            }
       }
    }
}

void CreateMohrISBNToDOIMapping(MARC::Reader * const marc_reader,
                               std::unordered_map<std::string, std::string> * const mohr_isbn_to_doi_map)
{
   while (MARC::Record record = marc_reader->read()) {
          const auto dois(record.getDOIs());
          if (dois.size() != 1)
              LOG_ERROR("No unique DOI for \"" + record.getControlNumber() + '"');

          // Get "native" ISBNs
          for (const auto &native_isbn : record.getISBNs())
               mohr_isbn_to_doi_map->emplace(native_isbn, *(dois.begin()));

          // Get "alternative" print ISBN
          for (const auto &alternative_isbn : record.getSubfieldValues("776", 'z'))
               mohr_isbn_to_doi_map->emplace(alternative_isbn, *(dois.begin()));
   }
}

void ProcessRecords(MARC::Reader * const marc_reader,
                    MARC::Writer * const marc_writer,
                    const std::unordered_multimap<std::string, std::string> &print_ppn_to_isbn_map,
                    const std::unordered_multimap<std::string, std::string> &electronic_ppn_to_isbn_map,
                    const std::unordered_map<std::string, std::string> &mohr_isbn_to_doi_map)
{
    unsigned count(0), new_electronic_dois(0), new_print_dois(0);
    while (MARC::Record record = marc_reader->read()) {
        ++count;
        const std::string ppn(record.getControlNumber());
        if (electronic_ppn_to_isbn_map.find(ppn) != electronic_ppn_to_isbn_map.end()) {
            const auto electronic_isbns(electronic_ppn_to_isbn_map.equal_range(ppn));
            for (auto ppn_and_isbn(electronic_isbns.first); ppn_and_isbn != electronic_isbns.second; ++ppn_and_isbn) {
                 const auto isbn(ppn_and_isbn->second);
                 if (mohr_isbn_to_doi_map.find(isbn) != mohr_isbn_to_doi_map.end()) {
                     const auto &record_dois(record.getDOIs());
                     const auto doi_for_isbn(mohr_isbn_to_doi_map.find(isbn)->second);
                     // Insert doi if not present
                     if (std::find(record_dois.begin(), record_dois.end(), doi_for_isbn) == record_dois.end()) {
                         LOG_INFO("Inserting previously not existing DOI \"" + doi_for_isbn + "\" for electronic record " +
                                  "\"" + record.getControlNumber());
                         record.insertField("024", { { 'a', doi_for_isbn }, { '2', "doi" } });
                         ++new_electronic_dois;
                     }
                     break;
                 }
             }
        } else if (print_ppn_to_isbn_map.find(ppn) != print_ppn_to_isbn_map.end()) {
            const auto print_isbns(print_ppn_to_isbn_map.equal_range(ppn));
            for (auto ppn_and_isbn(print_isbns.first); ppn_and_isbn != print_isbns.second; ++ppn_and_isbn) {
                 const auto isbn(ppn_and_isbn->second);
                 if (mohr_isbn_to_doi_map.find(isbn) != mohr_isbn_to_doi_map.end()) {
                     const auto &record_dois(record.getDOIs());
                     const auto doi_for_isbn(mohr_isbn_to_doi_map.find(isbn)->second);
                     // Insert doi if not present
                     if (std::find(record_dois.begin(), record_dois.end(), doi_for_isbn) == record_dois.end()) {
                         LOG_INFO("Inserting previously not existing DOI \"" + doi_for_isbn + "\" for print record " +
                                  "\"" + record.getControlNumber());
                         record.insertField("024", { { 'a', doi_for_isbn }, { '2', "doi" } });
                         ++new_print_dois;
                     }
                     break;
                 }
            }
        }
        marc_writer->write(record);
    }
    LOG_INFO("Inserted " + std::to_string(new_electronic_dois) + " new electronic DOIs and " +
             std::to_string(new_print_dois) + " print DOIs of " + std::to_string(count) + " records altogether");
}

} // unnamed namespace

int Main(int argc, char **argv) {
    if (argc != 4)
        Usage();

    const std::string marc_input_filename(argv[1]);
    const std::string mohr_book_data(argv[2]);
    const std::string marc_output_filename(argv[3]);
    if (unlikely(marc_input_filename == marc_output_filename))
        LOG_ERROR("Title data input file name equals output file name!");
    if (unlikely(mohr_book_data == marc_output_filename))
        LOG_ERROR("Mohr marc data input file name equals output file name!");

    std::unique_ptr<MARC::Reader> marc_reader(MARC::Reader::Factory(marc_input_filename));
    std::unique_ptr<MARC::Reader> mohr_book_reader(MARC::Reader::Factory(mohr_book_data));
    std::unique_ptr<MARC::Writer> marc_writer(MARC::Writer::Factory(marc_output_filename));

    std::unordered_multimap<std::string, std::string> print_ppn_to_isbn_map;
    std::unordered_multimap<std::string, std::string> electronic_ppn_to_isbn_map;
    std::unordered_map<std::string, std::string> mohr_isbn_to_doi_map;
    LOG_INFO("Create ISBN to DOI map from Mohr data");
    CreateMohrISBNToDOIMapping(mohr_book_reader.get(), &mohr_isbn_to_doi_map);
    LOG_INFO("We extracted " + std::to_string(mohr_isbn_to_doi_map.size())  + " ISBN to DOI mappings");
    LOG_INFO("Create PPN to ISBN Mappings");
    CreatePPNToISBNMappings(marc_reader.get(), &print_ppn_to_isbn_map, &electronic_ppn_to_isbn_map);
    LOG_INFO("We extracted " + std::to_string(print_ppn_to_isbn_map.size()) + " print PPN to ISBN mappings");
    LOG_INFO("We extracted " + std::to_string(electronic_ppn_to_isbn_map.size()) + " electronic PPN to ISBN mappings");
    LOG_INFO("Augmenting records");
    marc_reader->rewind();
    ProcessRecords(marc_reader.get(), marc_writer.get(),
                   print_ppn_to_isbn_map, electronic_ppn_to_isbn_map, mohr_isbn_to_doi_map);

    return EXIT_SUCCESS;
}

<|endoftext|>


<commit_before>#include "udpwrapper.h"

#include <iostream>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <cstring> // memset

using namespace std;

UdpWrapper *UdpWrapper::instance = nullptr;

UdpWrapper::UdpWrapper(const NodeInfo &mSender) : dataReceived(false)
{
    // Openning the socket

    mSocket = socket(AF_INET, SOCK_DGRAM, 0);
    if (mSocket < 0)
    {
        cout << "Error: cannot open a socket." << endl;
        exit(-1);
    }

    struct sockaddr_in mSrcAddr;

    // Setting the src address and port

    memset(&mSrcAddr, 0, sizeof(mSrcAddr));
    mSrcAddr.sin_family = AF_INET;
    mSrcAddr.sin_addr.s_addr = inet_addr(mSender.getAddress().c_str());
    mSrcAddr.sin_port = htons(mSender.getPort());

    if (::bind(mSocket, (struct sockaddr*) &mSrcAddr, sizeof(mSrcAddr)) < 0)
    {
        cout << "Error: bind " << mSender.toString() << endl;
    }

    tv.tv_sec = 0;
    tv.tv_usec = 100000;
    FD_ZERO(&rset);
}

UdpWrapper::~UdpWrapper()
{
    // Close the socket
    close(mSocket);
}

UdpWrapper *UdpWrapper::initialize(const NodeInfo &sender)
{
    if(instance == nullptr)
    {
        instance = new UdpWrapper(sender);
    }
    return instance;
}

void UdpWrapper::main()
{
    FD_SET(mSocket, &rset);
    if(select(mSocket+1, &rset, NULL, NULL, &tv) < 0)
    {
        if (errno == EINTR)
            cout << "What's happened here ?" << endl;
        else
            cout << "Error: Select" << endl;
    }

    if(FD_ISSET(mSocket, &rset))
    {
        dataReceived = true;
        receiveOnce();
    }
    else
    {
        dataReceived = false;
    }
}

void UdpWrapper::sendOnce(const NodeInfo &receiver, const std::string &message)
{
    struct sockaddr_in dstAddr;

    memset(&dstAddr, 0, sizeof(dstAddr));
    dstAddr.sin_family = AF_INET;
    dstAddr.sin_addr.s_addr = inet_addr(receiver.getAddress().c_str());
    dstAddr.sin_port = htons(receiver.getPort());

    cout << "Sending packet : " << message << endl;

    if (sendto(mSocket,
               message.c_str(), message.size()+1, // +1 for the null character
               0,
               (struct sockaddr *)&dstAddr, sizeof(dstAddr))
            < 0)
    {
        cout << "Error: sending to " << receiver.toString() << endl;
    }
}

std::string UdpWrapper::receiveOnce()
{
    if(dataReceived)
    {
        struct sockaddr_in emitterAdress;
        socklen_t emitterAdressLength = sizeof(emitterAdress);

        const int MAX_SIZE_BUFFER = 30;
        char buffer[MAX_SIZE_BUFFER];

        if (recvfrom(mSocket,
                     buffer, MAX_SIZE_BUFFER, 0,
                     (struct sockaddr *) &emitterAdress, &emitterAdressLength) < 0)
        {
            cout << "Error receving data" << endl;
            exit(-1);
        }
        cout << "Received from " << inet_ntoa(emitterAdress.sin_addr) << "(" << ntohs(emitterAdress.sin_port) << "): " << buffer << endl;
        cout << endl;
    }
    return "";
}
<commit_msg>Fix typo receving<commit_after>#include "udpwrapper.h"

#include <iostream>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <cstring> // memset

using namespace std;

UdpWrapper *UdpWrapper::instance = nullptr;

UdpWrapper::UdpWrapper(const NodeInfo &mSender) : dataReceived(false)
{
    // Openning the socket

    mSocket = socket(AF_INET, SOCK_DGRAM, 0);
    if (mSocket < 0)
    {
        cout << "Error: cannot open a socket." << endl;
        exit(-1);
    }

    struct sockaddr_in mSrcAddr;

    // Setting the src address and port

    memset(&mSrcAddr, 0, sizeof(mSrcAddr));
    mSrcAddr.sin_family = AF_INET;
    mSrcAddr.sin_addr.s_addr = inet_addr(mSender.getAddress().c_str());
    mSrcAddr.sin_port = htons(mSender.getPort());

    if (::bind(mSocket, (struct sockaddr*) &mSrcAddr, sizeof(mSrcAddr)) < 0)
    {
        cout << "Error: bind " << mSender.toString() << endl;
    }

    tv.tv_sec = 0;
    tv.tv_usec = 100000;
    FD_ZERO(&rset);
}

UdpWrapper::~UdpWrapper()
{
    // Close the socket
    close(mSocket);
}

UdpWrapper *UdpWrapper::initialize(const NodeInfo &sender)
{
    if(instance == nullptr)
    {
        instance = new UdpWrapper(sender);
    }
    return instance;
}

void UdpWrapper::main()
{
    FD_SET(mSocket, &rset);
    if(select(mSocket+1, &rset, NULL, NULL, &tv) < 0)
    {
        if (errno == EINTR)
            cout << "What's happened here ?" << endl;
        else
            cout << "Error: Select" << endl;
    }

    if(FD_ISSET(mSocket, &rset))
    {
        dataReceived = true;
        receiveOnce();
    }
    else
    {
        dataReceived = false;
    }
}

void UdpWrapper::sendOnce(const NodeInfo &receiver, const std::string &message)
{
    struct sockaddr_in dstAddr;

    memset(&dstAddr, 0, sizeof(dstAddr));
    dstAddr.sin_family = AF_INET;
    dstAddr.sin_addr.s_addr = inet_addr(receiver.getAddress().c_str());
    dstAddr.sin_port = htons(receiver.getPort());

    cout << "Sending packet : " << message << endl;

    if (sendto(mSocket,
               message.c_str(), message.size()+1, // +1 for the null character
               0,
               (struct sockaddr *)&dstAddr, sizeof(dstAddr))
            < 0)
    {
        cout << "Error: sending to " << receiver.toString() << endl;
    }
}

std::string UdpWrapper::receiveOnce()
{
    if(dataReceived)
    {
        struct sockaddr_in emitterAdress;
        socklen_t emitterAdressLength = sizeof(emitterAdress);

        const int MAX_SIZE_BUFFER = 30;
        char buffer[MAX_SIZE_BUFFER];

        if (recvfrom(mSocket,
                     buffer, MAX_SIZE_BUFFER, 0,
                     (struct sockaddr *) &emitterAdress, &emitterAdressLength) < 0)
        {
            cout << "Error receiving data" << endl;
            exit(-1);
        }
        cout << "Received from " << inet_ntoa(emitterAdress.sin_addr) << "(" << ntohs(emitterAdress.sin_port) << "): " << buffer << endl;
        cout << endl;
    }
    return "";
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2009-2010, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

#include <libport/cstdlib>
#include <iostream>

#include <libport/bind.hh>
#include <boost/lambda/lambda.hpp>
#include <boost/mem_fn.hpp>

#include <libport/compiler.hh>     // For LIBPORT_DEBUG
#include <libport/containers.hh>
#include <libport/debug.hh>
#include <libport/foreach.hh>
#include <libport/indent.hh>
#include <libport/separate.hh>

#include <sched/job.hh>

GD_ADD_CATEGORY(sched);

namespace sched
{
  StopException::StopException(unsigned depth, boost::any payload)
    : depth_(depth)
    , payload_(payload)
  {
  }

  /*-----------------.
  | Job::Collector.  |
  `-----------------*/

  Job::Collector::~Collector()
  {
    foreach (rJob& child, *this)
      parent_->terminate_child(child);
  }

  void
  Job::Collector::collect()
  {
    for (iterator i = begin(); i != end(); /* nothing. */)
      if ((*i)->terminated())
        {
          parent_->terminate_child(*i);
          i = erase(i);
        }
      else
        ++i;
  }

  std::ostream&
  Job::Collector::dump(std::ostream& o) const
  {
    return o << "{" << libport::incendl
             // Explicit parameters required by MSWC 2005.
             << libport::separate<const Collector,
                                  std::ostream&(*)(std::ostream&)>
                                  (*this, libport::iendl)
             << libport::decendl << "}";
  }

  std::ostream&
  operator<< (std::ostream& o, const Job::Collector& c)
  {
    return c.dump(o);
  }

  /*------.
  | Job.  |
  `------*/

  unsigned int Job::alive_jobs_ = 0;

  std::ostream&
  Job::dump(std::ostream& o) const
  {
    o << "Job(" << name_ << ")"
      << " "
      << (child_job() ? "child job" : "root job")
      << " state: " << state_;
    if (!children_.empty())
      o << " Children:" << libport::incendl
        << "{" << libport::incendl
        << children_ << libport::decendl
        << "}" << libport::decindent;
    return o;
  }

  void
  Job::run()
  {
    // This function never terminates properly: it yields and is never
    // called back. So perform RAII in a subblock to ensure that GD_CATEGORY
    // releases its memory.
    {
      GD_CATEGORY(sched);
      aver(state_ == to_start);
      LIBPORT_DEBUG("In Job::run for " << this);

      // We may get interrupted during our first run, in which case
      // we better not be in the to_start state while we are executing
      // or we would get removed abruptly from the scheduler pending_
      // list.
      state_ = running;
      try {
        if (has_pending_exception() &&
            dynamic_cast<SchedulerException*>(pending_exception_.get()))
	check_for_pending_exception();
        work();
      }
      catch (TerminateException&)
      {
      // Normal termination requested.
      }
      catch (StopException&)
      {
        // Termination through "stop" or "block" on a top-level tag,
        // that is a tag inherited at the job creation time.
      }
      catch (const exception& e)
      {
        // Rethrow the exception into the parent job if it exists.
        if (parent_)
          parent_->async_throw(ChildException(e.clone()));
      }
      catch (const std::exception& e)
      {
        GD_FERROR("job %s: Exception `%s' caught, losing it", this,
                  e.what());
      }
      catch (...)
      {
        // Exception is lost and cannot be propagated properly.
        GD_FERROR("job %s: Unknown exception caught, losing it", this);
      }
    }

    terminate_cleanup();

    // We should never go there as the scheduler will have terminated us.
    pabort("scheduler did not terminate us");
  }

  void
  Job::terminate_now()
  {
    // We have to terminate our children as well.
    terminate_jobs(children_);
    terminate_asap();
  }

  void
  Job::terminate_asap()
  {
    if (!terminated())
      async_throw(TerminateException());
  }

  void
  Job::terminate_child(const rJob& child)
  {
    child->terminate_now();
    libport::erase_if(children_, boost::lambda::_1 == child);
  }

  void
  Job::terminate_cleanup()
  {
    // Wake-up waiting jobs.
    foreach (const rJob& job, to_wake_up_)
      if (!job->terminated())
	job->state_set(running);
    to_wake_up_.clear();
    state_ = zombie;
    scheduler_.resume_scheduler(this);
  }

  void
  Job::register_child(const rJob& child, Collector& children)
  {
    aver(!child->parent_);
    child->parent_ = this;
    children.push_back(child);
    children_.push_back(child);
  }

  static bool
  job_compare(rJob lhs, rJob rhs)
  {
    return lhs == rhs;
  }

  void
  Job::yield_until_terminated(Job& other)
  {
    if (non_interruptible_ && this != &other)
      scheduling_error
	("dependency on other task in non-interruptible code");

    if (!other.terminated())
    {
      // We allow enqueuing on ourselves, but without doing it for real.
      if (&other != this)
	other.to_wake_up_.push_back(this);
      state_ = joining;
      try
      {
	scheduler_.resume_scheduler(this);
      }
      catch (...)
      {
	// We have been awoken by an exception; in this case,
	// dequeue ourselves from the other thread queue if
	// we are still enqueued there.
	libport::erase_if(other.to_wake_up_,
                          boost::bind(job_compare, this, _1));
	throw;
      }
    }
  }

  void
  Job::yield_until_terminated(const jobs_type& jobs)
  {
    foreach (const rJob& job, jobs)
      yield_until_terminated(*job);
  }

  void
  Job::yield_until_things_changed()
  {
    if (non_interruptible_ && !frozen())
      scheduling_error
	("attempt to wait for condition changes in non-interruptible code");

    state_ = waiting;
    scheduler_.resume_scheduler(this);
  }

  void
  Job::async_throw(const exception& e)
  {
    // A job which has received an exception is no longer side effect
    // free or non-interruptible.
    side_effect_free_ = false;
    non_interruptible_ = false;
    // If this is the current job we are talking about, the exception
    // is synchronous.
    if (scheduler_.is_current_job(this))
      e.rethrow();

    // Store the exception for later use.
    pending_exception_ = e.clone();

    // Now that we acquired an exception to raise, we are active again,
    // even if we were previously sleeping or waiting for something.
    if (state_ != to_start && state_ != zombie)
      state_ = running;
  }

  void
  Job::register_stopped_tag(const Tag& tag, const boost::any& payload)
  {
    size_t max_tag_check = (size_t)-1;
    if (has_pending_exception())
    {
      // If we are going to terminate, do nothing
      if (dynamic_cast<TerminateException*>(pending_exception_.get()))
	return;
      // If we already have a StopException stored, do not go any
      // further.
      StopException* exc =
	dynamic_cast<StopException*>(pending_exception_.get());
      if (exc)
	max_tag_check = exc->depth_get();
    }

    // Check if we are affected by this tag, up-to max_tag_check from
    // the beginning of the tag list.
    if (size_t pos = has_tag(tag, max_tag_check))
      async_throw(StopException(pos - 1, payload));
  }

  void
  Job::check_for_pending_exception()
  {
    // If an exception has been stored for further rethrow, now is
    // a good time to do so.
    if (has_pending_exception())
    {
      // Reset pending_exception_ by copying it into a local variable
      // first. This ensures that the exception will be destroyed
      // properly after having been rethrown.
      exception_ptr e = pending_exception_;
      e->rethrow();
    }
  }

  unsigned int
  Job::alive_jobs()
  {
    return alive_jobs_;
  }

  /*------------.
  | jobs_type.  |
  `------------*/

  void
  terminate_jobs(jobs_type& jobs)
  {
    foreach (rJob& job, jobs)
      job->terminate_now();
    jobs.clear();
  }

  std::ostream&
  operator<< (std::ostream& o, const jobs_type& js)
  {
    // Explicit parameters required by MSWC 2005.
    return o << libport::separate<const jobs_type,
                                  std::ostream&(*)(std::ostream&)>
                                 (js, libport::iendl);
  }

} // namespace sched
<commit_msg>Comment changes.<commit_after>/*
 * Copyright (C) 2009-2010, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

#include <libport/cstdlib>
#include <iostream>

#include <libport/bind.hh>
#include <boost/lambda/lambda.hpp>
#include <boost/mem_fn.hpp>

#include <libport/compiler.hh>     // For LIBPORT_DEBUG
#include <libport/containers.hh>
#include <libport/debug.hh>
#include <libport/foreach.hh>
#include <libport/indent.hh>
#include <libport/separate.hh>

#include <sched/job.hh>

GD_ADD_CATEGORY(sched);

namespace sched
{
  StopException::StopException(unsigned depth, boost::any payload)
    : depth_(depth)
    , payload_(payload)
  {
  }

  /*-----------------.
  | Job::Collector.  |
  `-----------------*/

  Job::Collector::~Collector()
  {
    foreach (rJob& child, *this)
      parent_->terminate_child(child);
  }

  void
  Job::Collector::collect()
  {
    for (iterator i = begin(); i != end(); /* nothing. */)
      if ((*i)->terminated())
        {
          parent_->terminate_child(*i);
          i = erase(i);
        }
      else
        ++i;
  }

  std::ostream&
  Job::Collector::dump(std::ostream& o) const
  {
    return o << "{" << libport::incendl
             // Explicit parameters required by MSVC 2005.
             << libport::separate<const Collector,
                                  std::ostream&(*)(std::ostream&)>
                                  (*this, libport::iendl)
             << libport::decendl << "}";
  }

  std::ostream&
  operator<< (std::ostream& o, const Job::Collector& c)
  {
    return c.dump(o);
  }

  /*------.
  | Job.  |
  `------*/

  unsigned int Job::alive_jobs_ = 0;

  std::ostream&
  Job::dump(std::ostream& o) const
  {
    o << "Job(" << name_ << ")"
      << " "
      << (child_job() ? "child job" : "root job")
      << " state: " << state_;
    if (!children_.empty())
      o << " Children:" << libport::incendl
        << "{" << libport::incendl
        << children_ << libport::decendl
        << "}" << libport::decindent;
    return o;
  }

  void
  Job::run()
  {
    // This function never terminates properly: it yields and is never
    // called back. So perform RAII in a subblock to ensure that GD_CATEGORY
    // releases its memory.
    {
      GD_CATEGORY(sched);
      aver(state_ == to_start);
      LIBPORT_DEBUG("In Job::run for " << this);

      // We may get interrupted during our first run, in which case
      // we better not be in the to_start state while we are executing
      // or we would get removed abruptly from the scheduler pending_
      // list.
      state_ = running;
      try {
        if (has_pending_exception() &&
            dynamic_cast<SchedulerException*>(pending_exception_.get()))
	check_for_pending_exception();
        work();
      }
      catch (TerminateException&)
      {
      // Normal termination requested.
      }
      catch (StopException&)
      {
        // Termination through "stop" or "block" on a top-level tag,
        // that is a tag inherited at the job creation time.
      }
      catch (const exception& e)
      {
        // Rethrow the exception into the parent job if it exists.
        if (parent_)
          parent_->async_throw(ChildException(e.clone()));
      }
      catch (const std::exception& e)
      {
        GD_FERROR("job %s: Exception `%s' caught, losing it", this,
                  e.what());
      }
      catch (...)
      {
        // Exception is lost and cannot be propagated properly.
        GD_FERROR("job %s: Unknown exception caught, losing it", this);
      }
    }

    terminate_cleanup();

    // We should never go there as the scheduler will have terminated us.
    pabort("scheduler did not terminate us");
  }

  void
  Job::terminate_now()
  {
    // We have to terminate our children as well.
    terminate_jobs(children_);
    terminate_asap();
  }

  void
  Job::terminate_asap()
  {
    if (!terminated())
      async_throw(TerminateException());
  }

  void
  Job::terminate_child(const rJob& child)
  {
    child->terminate_now();
    libport::erase_if(children_, boost::lambda::_1 == child);
  }

  void
  Job::terminate_cleanup()
  {
    // Wake-up waiting jobs.
    foreach (const rJob& job, to_wake_up_)
      if (!job->terminated())
	job->state_set(running);
    to_wake_up_.clear();
    state_ = zombie;
    scheduler_.resume_scheduler(this);
  }

  void
  Job::register_child(const rJob& child, Collector& children)
  {
    aver(!child->parent_);
    child->parent_ = this;
    children.push_back(child);
    children_.push_back(child);
  }

  static bool
  job_compare(rJob lhs, rJob rhs)
  {
    return lhs == rhs;
  }

  void
  Job::yield_until_terminated(Job& other)
  {
    if (non_interruptible_ && this != &other)
      scheduling_error
	("dependency on other task in non-interruptible code");

    if (!other.terminated())
    {
      // We allow enqueuing on ourselves, but without doing it for real.
      if (&other != this)
	other.to_wake_up_.push_back(this);
      state_ = joining;
      try
      {
	scheduler_.resume_scheduler(this);
      }
      catch (...)
      {
	// We have been awoken by an exception; in this case,
	// dequeue ourselves from the other thread queue if
	// we are still enqueued there.
	libport::erase_if(other.to_wake_up_,
                          boost::bind(job_compare, this, _1));
	throw;
      }
    }
  }

  void
  Job::yield_until_terminated(const jobs_type& jobs)
  {
    foreach (const rJob& job, jobs)
      yield_until_terminated(*job);
  }

  void
  Job::yield_until_things_changed()
  {
    if (non_interruptible_ && !frozen())
      scheduling_error
	("attempt to wait for condition changes in non-interruptible code");

    state_ = waiting;
    scheduler_.resume_scheduler(this);
  }

  void
  Job::async_throw(const exception& e)
  {
    // A job which has received an exception is no longer side effect
    // free or non-interruptible.
    side_effect_free_ = false;
    non_interruptible_ = false;
    // If this is the current job we are talking about, the exception
    // is synchronous.
    if (scheduler_.is_current_job(this))
      e.rethrow();

    // Store the exception for later use.
    pending_exception_ = e.clone();

    // Now that we acquired an exception to raise, we are active again,
    // even if we were previously sleeping or waiting for something.
    if (state_ != to_start && state_ != zombie)
      state_ = running;
  }

  void
  Job::register_stopped_tag(const Tag& tag, const boost::any& payload)
  {
    size_t max_tag_check = (size_t)-1;
    if (has_pending_exception())
    {
      // If we are going to terminate, do nothing
      if (dynamic_cast<TerminateException*>(pending_exception_.get()))
	return;
      // If we already have a StopException stored, do not go any
      // further.
      StopException* exc =
	dynamic_cast<StopException*>(pending_exception_.get());
      if (exc)
	max_tag_check = exc->depth_get();
    }

    // Check if we are affected by this tag, up-to max_tag_check from
    // the beginning of the tag list.
    if (size_t pos = has_tag(tag, max_tag_check))
      async_throw(StopException(pos - 1, payload));
  }

  void
  Job::check_for_pending_exception()
  {
    // If an exception has been stored for further rethrow, now is
    // a good time to do so.
    if (has_pending_exception())
    {
      // Reset pending_exception_ by copying it into a local variable
      // first. This ensures that the exception will be destroyed
      // properly after having been rethrown.
      exception_ptr e = pending_exception_;
      e->rethrow();
    }
  }

  unsigned int
  Job::alive_jobs()
  {
    return alive_jobs_;
  }

  /*------------.
  | jobs_type.  |
  `------------*/

  void
  terminate_jobs(jobs_type& jobs)
  {
    foreach (rJob& job, jobs)
      job->terminate_now();
    jobs.clear();
  }

  std::ostream&
  operator<< (std::ostream& o, const jobs_type& js)
  {
    // Explicit parameters required by MSWC 2005.
    return o << libport::separate<const jobs_type,
                                  std::ostream&(*)(std::ostream&)>
                                 (js, libport::iendl);
  }

} // namespace sched
<|endoftext|>