// $Header: /cvs/gled-1.2/GledCore/Stones/ZMIR.cxx,v 1.5 2005/03/11 17:50:16 matevz Exp $

// Copyright (C) 1999-2005, Matevz Tadel. All rights reserved.
// This file is part of GLED, released under GNU General Public License version 2.
// For the licensing terms see $GLEDSYS/LICENSE or http://www.gnu.org/.

//________________________________________________________________________
//
// ZMIR
//
// Covering structure for streaming/routing of MIRs.
// Message type defaults to MT_Flare.
// By calling SetRecipient the message type is transmuted to MT_Beam.
//
// Direction is used for determination of routing/exec action in the Saturn.
// SuppressFlareBroadcast can be set during MIR execution on the sun-saturn
// to prevent broadcasting of the MIR to moons.

#include "ZMIR.h"
#include <Glasses/SaturnInfo.h>
#include <Gled/GledNS.h>
#include <TMessage.h>


/**************************************************************************/
// ZMIR
/**************************************************************************/

ClassImp(ZMIR)

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

namespace {

  const Int_t ROOT_Header_Length = 2*sizeof(UInt_t); // len + type

  const Int_t Routing_Header_Min_Length = ROOT_Header_Length +
  sizeof(UChar_t) + sizeof(ID_t) + sizeof(ID_t); // MirBits, Caller, A

  const Int_t Fixed_Header_Length = ROOT_Header_Length +
    sizeof(UChar_t) + 4*sizeof(ID_t) +               // MirBits, Caller, A,B,G
    sizeof(LID_t) + sizeof(CID_t) + sizeof(MID_t);   // full method identity

  const Int_t MirBits_Length	= sizeof(UChar_t);
  const Int_t Caller_Length     = sizeof(ID_t);
  const Int_t Recipient_Length  = sizeof(ID_t);
  const Int_t ResultReq_Length  = sizeof(ID_t) + sizeof(UInt_t);
  const Int_t Max_Header_Length = Fixed_Header_Length + Recipient_Length + ResultReq_Length;

  const Int_t Caller_Offset    = ROOT_Header_Length + MirBits_Length;
  const Int_t Recipient_Offset = Caller_Offset      + Caller_Length;
  const Int_t ResultReq_Offset = Recipient_Offset   + Recipient_Length;
};

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

void ZMIR::_init() {
  // Set demangled info to null
  Caller = 0; Recipient = ResultRecipient = 0;
  Alpha = Beta = Gamma = 0;
}

/**************************************************************************/
 
ZMIR::ZMIR(ID_t a, ID_t b, ID_t g) :
  TMessage(GledNS::MT_Flare),
  Direction(D_Unknown), SuppressFlareBroadcast(false),
  MirBits(0), CallerID(0),
  RecipientID(0), ResultRecipientID(0), ResultReqHandle(0),
  AlphaID(a), BetaID(b), GammaID(g)
{
  _init();
  fTrueBuffer = 0;
  SetBufferOffset(Max_Header_Length);
}

ZMIR::ZMIR(ZGlass* a, ZGlass* b, ZGlass* g) :
  TMessage(GledNS::MT_Flare),
  Direction(D_Unknown), SuppressFlareBroadcast(false),
  MirBits(0), CallerID(0),
  RecipientID(0), ResultRecipientID(0), ResultReqHandle(0),
  Alpha(a), Beta(b), Gamma(g)
{
  AlphaID = a ? a->GetSaturnID() : 0;
  BetaID  = b ? b->GetSaturnID() : 0;
  GammaID = g ? g->GetSaturnID() : 0;
  fTrueBuffer = 0;
  SetBufferOffset(Max_Header_Length);
  Caller = 0; Recipient = ResultRecipient = 0;
}


ZMIR::ZMIR(TMessage*& m) :
  TMessage(m->Buffer(), m->BufferSize()),
  Direction(D_Unknown),
  SuppressFlareBroadcast(false), RequiresResult(false)
{
  m->DetachBuffer(); delete m; m = 0;
  _init();
  fTrueBuffer = 0;
}

ZMIR::~ZMIR() {
  if(fTrueBuffer) fBuffer = fTrueBuffer;
}

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

Int_t ZMIR::HeaderLength()
{
  Int_t r = Fixed_Header_Length;
  if(MirBits & MB_HasRecipient) r += sizeof(ID_t);
  if(MirBits & MB_HasResultReq) r += ResultReq_Length;
  return r;
}

Int_t ZMIR::RoutingHeaderLength()
{
  Int_t r = Routing_Header_Min_Length;
  if(MirBits & MB_HasRecipient) r += sizeof(ID_t);
  if(MirBits & MB_HasResultReq) r += ResultReq_Length;
  return r;
}

void ZMIR::WriteHeader()
{
  // Writes a complete MIR header, including the message type. If
  // Recipient and ResultReq fields are not used, the position of
  // fBuffer is displaced for the appropriate amount.
  // Also ... sets fBufSize to the current buffer position.
  // Do not add further data after this method has been called!

  if(IsWriting()) {
    if(MirBits & MB_HeaderWritten) return;
    MirBits |= MB_HeaderWritten;

    fTrueBuffer = fBuffer;
    fBuffer += Max_Header_Length - HeaderLength();

    fBufSize  = Length();
    SetBufferOffset(sizeof(UInt_t));

    TBuffer& b = *this;
    b << What() << MirBits << CallerID;
    if(MirBits & MB_HasRecipient) b << RecipientID;
    if(MirBits & MB_HasResultReq) b << ResultRecipientID << ResultReqHandle;
    b << AlphaID << BetaID << GammaID;
    b << Lid << Cid << Mid;

    SetBufferOffset(fBufSize);
  }
}

void ZMIR::ReadRoutingHeader()
{
  assert(IsReading()); // or sth ...
  TBuffer& b = *this;
  b >> MirBits >> CallerID;
  if(MirBits & MB_HasRecipient) b >> RecipientID;
  if(MirBits & MB_HasResultReq) b >> ResultRecipientID >> ResultReqHandle;
  b >> AlphaID;
}

void ZMIR::ReadExecHeader()
{
  assert(IsReading()); // or sth else ...
  //if(!IsReading()) { ZGlass* p=0; p->GetName(); }
  TBuffer& b = *this;
  b >> BetaID >> GammaID;
  b >> Lid >> Cid >> Mid;
}

void ZMIR::RewindToData()
{
  // Sets Read mode and position to just after the Context header.

  SetReadMode();
  SetBufferOffset(HeaderLength());
}

void ZMIR::RewindToExecHeader()
{
  // Sets Read mode and position to just after the Context header.

  SetReadMode();
  SetBufferOffset(RoutingHeaderLength());
}

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

namespace {
  const string demangle_eh("ZMIR::Demangle failed for ");
}

void ZMIR::Demangle(An_ID_Demangler* s) throw(string)
{
  Caller = dynamic_cast<ZMirEmittingEntity*>(s->DemangleID(CallerID));
  if(!Caller) throw(demangle_eh + GForm("Caller(id=%d)",CallerID));

  // Recipient & Result recipient separated. Called by Saturn when appropriate.

  Alpha = s->DemangleID(AlphaID);
  if(!Alpha) throw(demangle_eh + "Alpha");
  if(BetaID) {
    Beta = s->DemangleID(BetaID);
    if(!Beta) throw(demangle_eh + "Beta");
  }
  if(GammaID) {
    Gamma = s->DemangleID(GammaID);
    if(!Gamma) throw(demangle_eh + "Gamma");
  }
}

void ZMIR::DemangleRecipient(An_ID_Demangler* s) throw(string)
{
  if(MirBits & MB_HasRecipient) {
    Recipient = dynamic_cast<SaturnInfo*>(s->DemangleID(RecipientID));
    if(!Recipient) throw(demangle_eh + "Recipient");
  }
}

void ZMIR::DemangleResultRecipient(An_ID_Demangler* s) throw(string)
{
  if(MirBits & MB_HasResultReq) {
    ResultRecipient = dynamic_cast<SaturnInfo*>(s->DemangleID(ResultRecipientID));
    if(!ResultRecipient) throw(demangle_eh + "ResultRecipient");
  }
}

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

void ZMIR::SetCaller(ZMirEmittingEntity* caller)
{
  Caller = caller;
  if(IsWriting()) {
    CallerID = caller ? caller->GetSaturnID() : 0;
  } else {
    // Called by Saturn to set Caller identity for MIRs coming from
    // Eyes and being posted by threads.
    CallerID = caller ? caller->GetSaturnID() : 0;
    Int_t pos = Length();
    SetBufferOffset(Caller_Offset);
    *this << CallerID;
    SetBufferOffset(pos);
  }
  
}

void ZMIR::SetRecipient(SaturnInfo* recipient)
{
  // Can be called for MIR in write mode or for MIR in read mode
  // if it is already a Beam.

  RecipientID = recipient->GetSaturnID();
  if(IsReading()) {
    assert(MirBits | MB_HasRecipient);
    Recipient = recipient;
    Int_t pos = Length();
    SetBufferOffset(Recipient_Offset);
    *this << RecipientID;
    SetBufferOffset(pos);
  } else {
    MirBits |= MB_HasRecipient;
    SetWhat(GledNS::MT_Beam);
  }
}

void ZMIR::ClearRecipient()
{
  // Can only be called for MIRs in read mode. MIR is transmuted into Flare,
  // but the HasRecipient flag stays on.

  assert(IsReading() && (MirBits | MB_HasRecipient));
  RecipientID = 0;
  Recipient   = 0;

  SetWhat(GledNS::MT_Flare);
  Int_t pos = Length();
  SetBufferOffset(Recipient_Offset);
  *this << RecipientID;
  SetBufferOffset(pos);
}

void ZMIR::SetResultReq(SaturnInfo* r_recipient, UInt_t r_handle)
{
  // Sets result request information of the MIR.
  // Beam results can also carry arbitrary streamed information.

  assert(IsWriting());

  MirBits |= MB_HasResultReq;
  ResultRecipientID = r_recipient->GetSaturnID();
  ResultReqHandle   = r_handle;
}

void ZMIR::SetDetachedExe(bool multix)
{
    assert(IsWriting());

    MirBits |= (multix) ? MB_DetachedExe | MB_MultixDetachedExe :
                          MB_DetachedExe;
    
}

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

void ZMIR::CopyToBuffer(TBuffer& b)
{
  // Copies contents of Message from current position until end.

  b.WriteFastArray(fBufCur, fBufSize - Length());
}

void ZMIR::AppendBuffer(TBuffer& b)
{
  // Appends contents of b to the MIR.

  WriteFastArray(b.Buffer(), b.Length());
}

/**************************************************************************/
// ZMIR_Result_Report
/**************************************************************************/

//______________________________________________________________________
// ZMIR_Result_Report
//

ClassImp(ZMIR_Result_Report)

 const char* ZMIR_Result_Report::GenError(bool report_buffer)
{
  if(report_buffer) {
    int buflen = HasResult() ? BufferSize() : -1;
    return GForm("ZMIR_Result_Report(buflen=%d, exc="%s")", buflen, Exception.Data());
  } else {
    return GForm("ZMIR_Result_Report(exc="%s")", Exception.Data());
  }
}


ROOT page - Home page - Class index - Class Hierarchy - Top of the page

This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.