ROOT logo
// $Id: ZKing.cxx 2456 2010-10-17 18:31:40Z matevz $

// Copyright (C) 1999-2008, 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/.

//________________________________________________________________________
// ZKing
//
// A King controls top level chunks of ID space. A sun-space of each Saturn
// is ruled over by a King.
// King creates a dummy queen (set to mQueen) for proper ref-counting.
// Fire-space of each Saturn is ruled by a ZFireKing.
//
// BlessMIR() method is much less restrictive than the Queen version
// as Kings provide services for managing dependencies and mirroring
// of queens. Visibility of arguments is the sole concern of this
// method. Further checking is (and should be) provided in each
// respective method.
//________________________________________________________________________

#include "ZKing.h"
#include <Glasses/ZQueen.h>
#include "ZKing.c7"
#include <Glasses/ZEunuch.h>
#include <Glasses/SaturnInfo.h>
#include <Stones/ZComet.h>

ClassImp(ZKing);

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

void ZKing::_init()
{
  mSaturnInfo = 0;
  mLightType = LT_Undef;
  mMapNoneTo = ZMirFilter::R_Allow;
}

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

ZKing::~ZKing()
{
  delete mQueen;
}

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

void ZKing::AdEnlightenment()
{
  PARENT_GLASS::AdEnlightenment();
  // Create a dummy queen for reference counting and emitting Rays.
  mQueen = new ZQueen(GForm("Concubine of %s", GetName()));
  mQueen->mSaturn = mSaturn;
  mQueen->mZeroRCPolicy = ZQueen::ZRCP_Ignore;
  mQueen->mKing = this;
}

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

void ZKing::BlessMIR(ZMIR& mir)
{
  // Performs dependenciy check of context arguments and access
  // authorization.

  static TString _eh("ZKing::BlessMIR ");

  // Dependency check
  // Mild version ... just assert args in moon or sun space.
  // Further could restrict args to queens + lenses of mandatory queens.
  if(mir.fBeta) {
    if(mir.fBetaID > mMaxID) {
      throw(_eh + GForm("beta '%s', id=%d: dependency check failed.",
			mir.fBeta->GetName(), mir.fBetaID));
    }
  }
  if(mir.fGamma) {
    if(mir.fGammaID > mMaxID) {
      throw(_eh + GForm("gamma '%s', id=%d: dependency check failed.",
			    mir.fGamma->GetName(), mir.fGammaID));
    }
  }

  // Authorization

  // Allow everything if UseAuth is false
  if(mSaturn->GetSaturnInfo()->GetUseAuth() == false) {
    return;
  }

  // Always allow SunAbsolute access
  if(mir.fCaller->HasIdentity(mSaturn->mSunInfo->GetPrimaryIdentity())) {
    return;
  }

  UChar_t result = (mGuard != 0) ? mGuard->FilterMIR(mir) : ZMirFilter::R_None;
  if( result == ZMirFilter::R_Deny ||
      (result == ZMirFilter::R_None && mMapNoneTo == ZMirFilter::R_Deny))
    {
      throw(_eh + "access denied");
    }
}

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

void ZKing::Enthrone(ZQueen* queen)
{
  ID_t id_span = queen->GetIDSpan();
  if(mMaxID==mMaxUsedID || mMaxID - mMaxUsedID < id_span) {
    assert(0);
  }
  queen->mKing   = this;
  queen->mSaturn = mSaturn;
  queen->mMinID = mMaxUsedID + 1;
  mMaxUsedID += id_span;
  queen->mMaxID = mMaxUsedID;
  queen->bootstrap();
  Add(queen);

  // !!!! should broadcast to all moons
}

void ZKing::StarToQueen(ZComet* comet, ID_t span)
{
  // In principle, loading of queen with wider id-span than needed.
  // Perhaps could be even useful.
}

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

ZComet* ZKing::MakeComet()
{
  // Produces Comet of type ST_King.
  // Contains the King, all its Queens and their Dependencies.
  // Used for producing snapshot of a King-space to be sent to a Moon.

  ZComet* comet = new ZComet(GetName(), GForm("Comet[King] of %s", GetName()));
  comet->mType = ZComet::CT_King;
  comet->mKing = this;

  ReadLock();
  comet->AddGlass(this);
  lpZGlass_t queens; CopyList(queens);
  for(lpZGlass_i i=queens.begin(); i!=queens.end(); ++i) {
    ZQueen* q = dynamic_cast<ZQueen*>(*i);
    assert(q!=0);
    comet->AddGlass(q);
    comet->AddGlass(q->GetDeps());
  }
  ReadUnlock();

  return comet;
}

/**************************************************************************/
// Mirroring of Queens
/**************************************************************************/

void ZKing::reflect_queen(ZQueen* queen_to_mirror, SaturnInfo* moon)
{
  // Actual activation of a queen.
  // If moon == mSaturn->GetSaturnInfo() and queen is not activated,
  //    check deps, send beams, mark the queens.
  // If moon in my moons, then:
  //   if(have the queen active) push it along
  //   else forward the request and mark thingies (queen and the new reflector).

  static TString _eh("ZKing::reflect_queen() ");

  assert_MIR_presence(_eh);

  if(moon == mSaturn->GetSaturnInfo()) {
    // Request came from self ... must beam it upwards, if necessary.

    if(queen_to_mirror->GetRuling()) {
      throw(_eh + "queen is already ruling");
    }
    if(queen_to_mirror->GetAwaitingSceptre()) {
      throw(_eh + "queen is awaiting sceptre");
    }

    // Here should check dependencies etc.
    // or perhaps later prior to streaming

    mSaturn->RefQueenLoadCnd().Lock();
    mSaturn->SetQueenLoadNum(mSaturn->GetQueenLoadNum() + 1);
    mSaturn->RefQueenLoadCnd().Broadcast();
    mSaturn->RefQueenLoadCnd().Unlock();


    queen_to_mirror->SetAwaitingSceptre(true);
    // Request_mirror
    auto_ptr<ZMIR> mir(S_reflect_queen(queen_to_mirror, moon));
    mir->SetCaller(mSaturn->GetSaturnInfo());
    mir->SetRecipient(moon->GetMaster());
    mSaturn->PostMIR(mir);

  } else {
    // Request should be coming from direct moon.
    // Must serve it or forward it.

    if(!mSaturn->IsMoon(moon)) {
      throw(_eh + "moon neither this Saturn nor its direct Moon");
    }

    if(queen_to_mirror->GetRuling()) {

      queen_to_mirror->WriteLock();
      auto_ptr<ZMIR> mir(this->S_activate_queen(queen_to_mirror));
      mir->SetCaller(mSaturn->GetSaturnInfo());
      mir->SetRecipient(moon);
      queen_to_mirror->CreateReflection(*mir);
      queen_to_mirror->add_reflector(moon);
      queen_to_mirror->WriteUnlock();
      ISdebug(0, GForm("%s Sending queen '%s' to moon '%s'; length=%d",
		       _eh.Data(), queen_to_mirror->GetName(),
		       moon->GetName(), mir->Length()));
      mSaturn->PostMIR(mir);
      moon->hQueens.insert(queen_to_mirror);

    } else if(queen_to_mirror->GetAwaitingSceptre()) {

      queen_to_mirror->add_reflector(moon);

    } else {

      // Here should check dependencies etc.
      queen_to_mirror->SetAwaitingSceptre(true);
      queen_to_mirror->add_reflector(moon);
      // Request_mirror
      auto_ptr<ZMIR> mir(S_reflect_queen(queen_to_mirror,
					 mSaturn->GetSaturnInfo()));
      mir->SetCaller(mSaturn->GetSaturnInfo());
      mir->SetRecipient(mSaturn->GetSaturnInfo()->GetMaster());
      mSaturn->PostMIR(mir);

    }

  }
}

void ZKing::activate_queen(ZQueen* queen)
{
  // A response from upper Saturn, containing whatever was attached
  // by ZQueen::CreateReflection().

  // assert queen awaiting sceptre.
  // Invoke it upon reflection.
  // Check, if the queen has any aspiring reflectors ... forward the beam to them

  static TString _eh("ZKing::activate_queen() ");

  ZMIR* mir = assert_MIR_presence(_eh);

  if(!queen->GetAwaitingSceptre()) {
    throw(_eh + "queen " + queen->GetName() + " is NOT awaiting sceptre");
  }

  queen->InvokeReflection(*mir);
  queen->SetAwaitingSceptre(false);

  ISmess(GForm("%s queen '%s' arrived for king '%s'",
	       _eh.Data(), queen->GetName(), GetName()));

  mSaturn->RefQueenLoadCnd().Lock();
  mSaturn->SetQueenLoadNum(mSaturn->GetQueenLoadNum() - 1);
  mSaturn->RefQueenLoadCnd().Broadcast();
  mSaturn->RefQueenLoadCnd().Unlock();

  // Broadcast beams
  if(!queen->mReflectors.empty()) {
    mSaturn->BroadcastBeamMIR(*mir, queen->mReflectors);
    for(ZQueen::lpSaturnInfo_i r=queen->mReflectors.begin(); r!=queen->mReflectors.end(); ++r) {
      (*r)->hQueens.insert(queen);
    }
  }
}

void ZKing::unreflect_queen(ZQueen* queen_to_leave, SaturnInfo* moon)
{
  // Ignore gloriously. Deps first.
}

void ZKing::receive_eunuch()
{
  // Receives an eunuch.

  static TString _eh("ZKing::receive_eunuch ");
  ZMIR* mir = assert_MIR_presence(_eh, ZGlass::MC_IsBeam);

  ZEunuch* e = GledNS::StreamLensByGlass<ZEunuch*>(*mir);
  if(e == 0)
    throw(_eh + "MIR not followed by an eunuch.");


}


/**************************************************************************/
 ZKing.cxx:1
 ZKing.cxx:2
 ZKing.cxx:3
 ZKing.cxx:4
 ZKing.cxx:5
 ZKing.cxx:6
 ZKing.cxx:7
 ZKing.cxx:8
 ZKing.cxx:9
 ZKing.cxx:10
 ZKing.cxx:11
 ZKing.cxx:12
 ZKing.cxx:13
 ZKing.cxx:14
 ZKing.cxx:15
 ZKing.cxx:16
 ZKing.cxx:17
 ZKing.cxx:18
 ZKing.cxx:19
 ZKing.cxx:20
 ZKing.cxx:21
 ZKing.cxx:22
 ZKing.cxx:23
 ZKing.cxx:24
 ZKing.cxx:25
 ZKing.cxx:26
 ZKing.cxx:27
 ZKing.cxx:28
 ZKing.cxx:29
 ZKing.cxx:30
 ZKing.cxx:31
 ZKing.cxx:32
 ZKing.cxx:33
 ZKing.cxx:34
 ZKing.cxx:35
 ZKing.cxx:36
 ZKing.cxx:37
 ZKing.cxx:38
 ZKing.cxx:39
 ZKing.cxx:40
 ZKing.cxx:41
 ZKing.cxx:42
 ZKing.cxx:43
 ZKing.cxx:44
 ZKing.cxx:45
 ZKing.cxx:46
 ZKing.cxx:47
 ZKing.cxx:48
 ZKing.cxx:49
 ZKing.cxx:50
 ZKing.cxx:51
 ZKing.cxx:52
 ZKing.cxx:53
 ZKing.cxx:54
 ZKing.cxx:55
 ZKing.cxx:56
 ZKing.cxx:57
 ZKing.cxx:58
 ZKing.cxx:59
 ZKing.cxx:60
 ZKing.cxx:61
 ZKing.cxx:62
 ZKing.cxx:63
 ZKing.cxx:64
 ZKing.cxx:65
 ZKing.cxx:66
 ZKing.cxx:67
 ZKing.cxx:68
 ZKing.cxx:69
 ZKing.cxx:70
 ZKing.cxx:71
 ZKing.cxx:72
 ZKing.cxx:73
 ZKing.cxx:74
 ZKing.cxx:75
 ZKing.cxx:76
 ZKing.cxx:77
 ZKing.cxx:78
 ZKing.cxx:79
 ZKing.cxx:80
 ZKing.cxx:81
 ZKing.cxx:82
 ZKing.cxx:83
 ZKing.cxx:84
 ZKing.cxx:85
 ZKing.cxx:86
 ZKing.cxx:87
 ZKing.cxx:88
 ZKing.cxx:89
 ZKing.cxx:90
 ZKing.cxx:91
 ZKing.cxx:92
 ZKing.cxx:93
 ZKing.cxx:94
 ZKing.cxx:95
 ZKing.cxx:96
 ZKing.cxx:97
 ZKing.cxx:98
 ZKing.cxx:99
 ZKing.cxx:100
 ZKing.cxx:101
 ZKing.cxx:102
 ZKing.cxx:103
 ZKing.cxx:104
 ZKing.cxx:105
 ZKing.cxx:106
 ZKing.cxx:107
 ZKing.cxx:108
 ZKing.cxx:109
 ZKing.cxx:110
 ZKing.cxx:111
 ZKing.cxx:112
 ZKing.cxx:113
 ZKing.cxx:114
 ZKing.cxx:115
 ZKing.cxx:116
 ZKing.cxx:117
 ZKing.cxx:118
 ZKing.cxx:119
 ZKing.cxx:120
 ZKing.cxx:121
 ZKing.cxx:122
 ZKing.cxx:123
 ZKing.cxx:124
 ZKing.cxx:125
 ZKing.cxx:126
 ZKing.cxx:127
 ZKing.cxx:128
 ZKing.cxx:129
 ZKing.cxx:130
 ZKing.cxx:131
 ZKing.cxx:132
 ZKing.cxx:133
 ZKing.cxx:134
 ZKing.cxx:135
 ZKing.cxx:136
 ZKing.cxx:137
 ZKing.cxx:138
 ZKing.cxx:139
 ZKing.cxx:140
 ZKing.cxx:141
 ZKing.cxx:142
 ZKing.cxx:143
 ZKing.cxx:144
 ZKing.cxx:145
 ZKing.cxx:146
 ZKing.cxx:147
 ZKing.cxx:148
 ZKing.cxx:149
 ZKing.cxx:150
 ZKing.cxx:151
 ZKing.cxx:152
 ZKing.cxx:153
 ZKing.cxx:154
 ZKing.cxx:155
 ZKing.cxx:156
 ZKing.cxx:157
 ZKing.cxx:158
 ZKing.cxx:159
 ZKing.cxx:160
 ZKing.cxx:161
 ZKing.cxx:162
 ZKing.cxx:163
 ZKing.cxx:164
 ZKing.cxx:165
 ZKing.cxx:166
 ZKing.cxx:167
 ZKing.cxx:168
 ZKing.cxx:169
 ZKing.cxx:170
 ZKing.cxx:171
 ZKing.cxx:172
 ZKing.cxx:173
 ZKing.cxx:174
 ZKing.cxx:175
 ZKing.cxx:176
 ZKing.cxx:177
 ZKing.cxx:178
 ZKing.cxx:179
 ZKing.cxx:180
 ZKing.cxx:181
 ZKing.cxx:182
 ZKing.cxx:183
 ZKing.cxx:184
 ZKing.cxx:185
 ZKing.cxx:186
 ZKing.cxx:187
 ZKing.cxx:188
 ZKing.cxx:189
 ZKing.cxx:190
 ZKing.cxx:191
 ZKing.cxx:192
 ZKing.cxx:193
 ZKing.cxx:194
 ZKing.cxx:195
 ZKing.cxx:196
 ZKing.cxx:197
 ZKing.cxx:198
 ZKing.cxx:199
 ZKing.cxx:200
 ZKing.cxx:201
 ZKing.cxx:202
 ZKing.cxx:203
 ZKing.cxx:204
 ZKing.cxx:205
 ZKing.cxx:206
 ZKing.cxx:207
 ZKing.cxx:208
 ZKing.cxx:209
 ZKing.cxx:210
 ZKing.cxx:211
 ZKing.cxx:212
 ZKing.cxx:213
 ZKing.cxx:214
 ZKing.cxx:215
 ZKing.cxx:216
 ZKing.cxx:217
 ZKing.cxx:218
 ZKing.cxx:219
 ZKing.cxx:220
 ZKing.cxx:221
 ZKing.cxx:222
 ZKing.cxx:223
 ZKing.cxx:224
 ZKing.cxx:225
 ZKing.cxx:226
 ZKing.cxx:227
 ZKing.cxx:228
 ZKing.cxx:229
 ZKing.cxx:230
 ZKing.cxx:231
 ZKing.cxx:232
 ZKing.cxx:233
 ZKing.cxx:234
 ZKing.cxx:235
 ZKing.cxx:236
 ZKing.cxx:237
 ZKing.cxx:238
 ZKing.cxx:239
 ZKing.cxx:240
 ZKing.cxx:241
 ZKing.cxx:242
 ZKing.cxx:243
 ZKing.cxx:244
 ZKing.cxx:245
 ZKing.cxx:246
 ZKing.cxx:247
 ZKing.cxx:248
 ZKing.cxx:249
 ZKing.cxx:250
 ZKing.cxx:251
 ZKing.cxx:252
 ZKing.cxx:253
 ZKing.cxx:254
 ZKing.cxx:255
 ZKing.cxx:256
 ZKing.cxx:257
 ZKing.cxx:258
 ZKing.cxx:259
 ZKing.cxx:260
 ZKing.cxx:261
 ZKing.cxx:262
 ZKing.cxx:263
 ZKing.cxx:264
 ZKing.cxx:265
 ZKing.cxx:266
 ZKing.cxx:267
 ZKing.cxx:268
 ZKing.cxx:269
 ZKing.cxx:270
 ZKing.cxx:271
 ZKing.cxx:272
 ZKing.cxx:273
 ZKing.cxx:274
 ZKing.cxx:275
 ZKing.cxx:276
 ZKing.cxx:277
 ZKing.cxx:278
 ZKing.cxx:279
 ZKing.cxx:280
 ZKing.cxx:281
 ZKing.cxx:282
 ZKing.cxx:283
 ZKing.cxx:284
 ZKing.cxx:285
 ZKing.cxx:286
 ZKing.cxx:287
 ZKing.cxx:288
 ZKing.cxx:289
 ZKing.cxx:290
 ZKing.cxx:291
 ZKing.cxx:292
 ZKing.cxx:293
 ZKing.cxx:294
 ZKing.cxx:295
 ZKing.cxx:296
 ZKing.cxx:297
 ZKing.cxx:298
 ZKing.cxx:299