<commit_before>/*
Copyright (C) 2007 <SWGEmu>

This File is part of Core3.

This program is free software; you can redistribute
it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software
Foundation; either version 2 of the License,
or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for
more details.

You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write to
the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

Linking Engine3 statically or dynamically with other modules
is making a combined work based on Engine3.
Thus, the terms and conditions of the GNU Lesser General Public License
cover the whole combination.

In addition, as a special exception, the copyright holders of Engine3
give you permission to combine Engine3 program with free software
programs or libraries that are released under the GNU LGPL and with
code included in the standard release of Core3 under the GNU LGPL
license (or modified versions of such code, with unchanged license).
You may copy and distribute such a system following the terms of the
GNU LGPL for Engine3 and the licenses of the other code concerned,
provided that you include the source code of that other code when
and as the GNU LGPL requires distribution of source code.

Note that people who make modified versions of Engine3 are not obligated
to grant this special exception for their modified versions;
it is their choice whether to do so. The GNU Lesser General Public License
gives permission to release a modified version without this exception;
this exception also makes it possible to release a modified version
which carries forward this exception.
*/

#include "CommandQueueAction.h"

#include "../../objects/creature/skills/Skill.h"

#include "../../objects/player/Player.h"

#include "../../objects/creature/CreatureObject.h"
#include "../../objects/tangible/weapons/Weapon.h"
#include "../../objects/attackable/AttackableObject.h"

CommandQueueAction::CommandQueueAction(CreatureObject* cr, uint64 targid, uint32 acrc, uint32 acntr, const String& amod) {
	actionCRC = acrc;
	actionCounter = acntr;

	targetID = targid;

	actionModifier = amod;

	creature = cr;
	if (creature->isPlayer())
		player = (Player*)cr;
	else
		player = NULL;

	target = NULL;
	skill = NULL;
	weapon = NULL;
}

bool CommandQueueAction::check() {
	if (creature->isIncapacitated() || creature->isDead()) {
		clearError(1, 19);
		return false;
	}

	if (creature->isMounted()) {
		clearError(1, 16);
		return false;
	}

	if (skill->isTargetSkill()) {
		if (creature->isKnockedDown()) {
			clearError(1, 18);
			return false;
		}

		target = player->getTarget();

		if (target == NULL)
			target = creature;

		if (!(target->isNonPlayerCreature() || target->isPlayer() || target->isAttackableObject())) {
			clearError(3);
			return false;
		}

		return true;
	}

	return true;
}

bool CommandQueueAction::validate() {
	if (creature->hasAttackDelay()) {
		clearError(0);
		return false;
	}

	if (creature->isIncapacitated() || creature->isDead()) {
		clearError(1, 19);
		return false;
	}

	if (creature->isMounted()) {
		clearError(1, 16);
		return false;
	}

	if (creature->isKnockedDown()) {
		clearError(1, 18);
		return false;
	}

	if (skill->isTargetSkill()) {
		if (target != creature) {
			if (skill->isAttackSkill()) {

				if (!checkWeapon())
					return false;

				try {
					target->wlock(creature);

					Weapon* weapon = creature->getWeapon();

					int range;

					if (skill->getRange() != 0)
						range = (int)skill->getRange();
					else if (weapon != NULL)
						range = weapon->getMaxRange();
					else
						range = 5;

					if (!creature->isInRange(target->getPositionX(), target->getPositionY(), range)) {
						target->unlock();
						clearError(4);
						return false;
					}

					SceneObject* sco = target;

					if (sco->isPlayer()) {
						Player* targetPlayer = (Player*) sco;

						if (targetPlayer->isInBuilding() && target->getParent() != creature->getParent()) {
								clearError(0);
								creature->sendSystemMessage("cbt_spam", "los_recycle"); // You cannot see your target

								target->unlock();
								return false;
						}

					} else {
						if (target->getParent() != creature->getParent()) {
							clearError(0);
							creature->sendSystemMessage("cbt_spam", "los_recycle"); // You cannot see your target

							target->unlock();
							return false;
						}
					}

					if (!target->isAttackableObject()) {
						CreatureObject* targetCreature = (CreatureObject*) target.get();

						if (targetCreature->isIncapacitated() || targetCreature->isDead()) {
							clearError(3);
							target->unlock();
							return false;
						}
					} else {
						AttackableObject* targetObject = (AttackableObject*) target.get();

						if (targetObject->isDestroyed()) {
							clearError(3);
							target->unlock();
							return false;
						}
					}

					if (target->isPlayer()) {
						Player* targetPlayer = (Player*) target.get();

						// TODO:  Needs fixing for BH missions
						if (!player->isInDuelWith(targetPlayer, false)) {
							if (!player->isOvert() || !targetPlayer->isOvert()) {
								clearError(3);
								target->unlock();
								return false;
							} else if (player->getFaction() == targetPlayer->getFaction()) {
								clearError(3);
								target->unlock();
								return false;
							}
						}
					} else {
						if (!target->isAttackableBy(creature)) {
							clearError(3);
							target->unlock();
							return false;
						}
					}

					target->unlock();
				} catch (...) {
					System::out << "Unreported Exception in CommandQueueAction::validate()\n";
					target->unlock();
				}
			} else if (skill->isHealSkill()) {
				return checkHealSkill();
			}
		} else { // target == creature
			if (skill->isAttackSkill()) {
				clearError(3);
				return false;
			}
		}
	}

	return true;
}

bool CommandQueueAction::checkHealSkill() {

	if (target->isAttackableObject()) {
		clearError(3);
		return false;
	}

	CreatureObject* targetObject = (CreatureObject*) target.get();
	if (targetObject != creature) {
		try {
			targetObject->wlock(creature);

			if (target->isPlayer()) {
				Player* targetPlayer = (Player*) target.get();

				if (player->isInDuelWith(targetPlayer, false))
					target = creature;
				else if (player->isOvert() && targetPlayer->isOvert()
						&& player->getFaction() != targetPlayer->getFaction())
					target = creature;
				else if (!player->isOvert() && targetPlayer->isOvert())
					target = creature;
			} else if (target->isNonPlayerCreature() && !skill->isDiagnoseSkill() && !skill->isDragSkill())
				target = creature;

			if (!creature->isInRange(target->getPositionX(), target->getPositionY(), skill->getRange())) {
				targetObject->unlock();
				clearError(4);
				return false;
			}

			if (targetObject->isDead() && !skill->isReviveSkill() && !skill->isDragSkill()) {
				clearError(3);
				targetObject->unlock();
				return false;
			}

			targetObject->unlock();
		} catch (...) {
			targetObject->unlock();
		}
	}

	return true;
}

bool CommandQueueAction::checkWeapon() {
	int requiredWeapon = skill->getRequiredWeaponType();

	if (requiredWeapon != 0xFF) {
		weapon = creature->getWeapon();

		if (weapon != NULL) {
			if (requiredWeapon == 0x10 || requiredWeapon == 0x20 ||
					requiredWeapon == 0x30) {
				if (weapon->getCategory() != requiredWeapon) {
					clearError(0);
					if (player != NULL)
						player->sendSystemMessage("cbt_spam", "no_attack_wrong_weapon"); // Can't be done with this weapon
					return false;
				}
			} else if (weapon->getType() != requiredWeapon) {
				clearError(0);
				if (player != NULL)
					player->sendSystemMessage("cbt_spam", "no_attack_wrong_weapon"); // Can't be done with this weapon
				return false;
			}
		} else if (requiredWeapon != 0) {
			clearError(0);
			if (player != NULL)
				player->sendSystemMessage("cbt_spam", "no_attack_wrong_weapon"); // Can't be done with this weapon
			return false;
		}
	}

	if (creature->isKneeling()) {
		if (requiredWeapon < 4 || requiredWeapon == 0x10) {
			clearError(1,4);
			return false;
		}
	}

	if (creature->isProne()) {
		if (requiredWeapon < 4 || requiredWeapon > 6 || requiredWeapon == 0x10 || requiredWeapon == 0x30) {
			clearError(1,7);
			return false;
		}
	}

	return true;
}

void CommandQueueAction::clear(float timer, uint32 tab1, uint32 tab2) {
	if (player != NULL)
		player->clearQueueAction(actionCounter, timer, tab1, tab2);
}
<commit_msg>[Fixed] Players with healing abilities will now Heal themselves instead of receiving an "Invalid Target" msg when a Dead NPC, Ticket Collector etc is targeted. *Does not apply to Heal Mind*<commit_after>/*
Copyright (C) 2007 <SWGEmu>

This File is part of Core3.

This program is free software; you can redistribute
it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software
Foundation; either version 2 of the License,
or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for
more details.

You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write to
the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

Linking Engine3 statically or dynamically with other modules
is making a combined work based on Engine3.
Thus, the terms and conditions of the GNU Lesser General Public License
cover the whole combination.

In addition, as a special exception, the copyright holders of Engine3
give you permission to combine Engine3 program with free software
programs or libraries that are released under the GNU LGPL and with
code included in the standard release of Core3 under the GNU LGPL
license (or modified versions of such code, with unchanged license).
You may copy and distribute such a system following the terms of the
GNU LGPL for Engine3 and the licenses of the other code concerned,
provided that you include the source code of that other code when
and as the GNU LGPL requires distribution of source code.

Note that people who make modified versions of Engine3 are not obligated
to grant this special exception for their modified versions;
it is their choice whether to do so. The GNU Lesser General Public License
gives permission to release a modified version without this exception;
this exception also makes it possible to release a modified version
which carries forward this exception.
*/

#include "CommandQueueAction.h"

#include "../../objects/creature/skills/Skill.h"

#include "../../objects/player/Player.h"

#include "../../objects/creature/CreatureObject.h"
#include "../../objects/tangible/weapons/Weapon.h"
#include "../../objects/attackable/AttackableObject.h"

CommandQueueAction::CommandQueueAction(CreatureObject* cr, uint64 targid, uint32 acrc, uint32 acntr, const String& amod) {
	actionCRC = acrc;
	actionCounter = acntr;

	targetID = targid;

	actionModifier = amod;

	creature = cr;
	if (creature->isPlayer())
		player = (Player*)cr;
	else
		player = NULL;

	target = NULL;
	skill = NULL;
	weapon = NULL;
}

bool CommandQueueAction::check() {
	if (creature->isIncapacitated() || creature->isDead()) {
		clearError(1, 19);
		return false;
	}

	if (creature->isMounted()) {
		clearError(1, 16);
		return false;
	}

	if (skill->isTargetSkill()) {
		if (creature->isKnockedDown()) {
			clearError(1, 18);
			return false;
		}

		target = player->getTarget();

		if (target == NULL)
			target = creature;

		if (!(target->isNonPlayerCreature() || target->isPlayer() || target->isAttackableObject()))
			target = creature;

		if (target->isNonPlayerCreature() && !target->isAttackableObject() && skill->isHealSkill())
			target = creature;

		return true;
	}

	return true;
}

bool CommandQueueAction::validate() {
	if (creature->hasAttackDelay()) {
		clearError(0);
		return false;
	}

	if (creature->isIncapacitated() || creature->isDead()) {
		clearError(1, 19);
		return false;
	}

	if (creature->isMounted()) {
		clearError(1, 16);
		return false;
	}

	if (creature->isKnockedDown()) {
		clearError(1, 18);
		return false;
	}

	if (skill->isTargetSkill()) {
		if (target != creature) {
			if (skill->isAttackSkill()) {

				if (!checkWeapon())
					return false;

				try {
					target->wlock(creature);

					Weapon* weapon = creature->getWeapon();

					int range;

					if (skill->getRange() != 0)
						range = (int)skill->getRange();
					else if (weapon != NULL)
						range = weapon->getMaxRange();
					else
						range = 5;

					if (!creature->isInRange(target->getPositionX(), target->getPositionY(), range)) {
						target->unlock();
						clearError(4);
						return false;
					}

					SceneObject* sco = target;

					if (sco->isPlayer()) {
						Player* targetPlayer = (Player*) sco;

						if (targetPlayer->isInBuilding() && target->getParent() != creature->getParent()) {
								clearError(0);
								creature->sendSystemMessage("cbt_spam", "los_recycle"); // You cannot see your target

								target->unlock();
								return false;
						}

					} else {
						if (target->getParent() != creature->getParent()) {
							clearError(0);
							creature->sendSystemMessage("cbt_spam", "los_recycle"); // You cannot see your target

							target->unlock();
							return false;
						}
					}

					if (!target->isAttackableObject()) {
						CreatureObject* targetCreature = (CreatureObject*) target.get();

						if (targetCreature->isIncapacitated() || targetCreature->isDead()) {
							clearError(3);
							target->unlock();
							return false;
						}
					} else {
						AttackableObject* targetObject = (AttackableObject*) target.get();

						if (targetObject->isDestroyed()) {
							clearError(3);
							target->unlock();
							return false;
						}
					}

					if (target->isPlayer()) {
						Player* targetPlayer = (Player*) target.get();

						// TODO:  Needs fixing for BH missions
						if (!player->isInDuelWith(targetPlayer, false)) {
							if (!player->isOvert() || !targetPlayer->isOvert()) {
								clearError(3);
								target->unlock();
								return false;
							} else if (player->getFaction() == targetPlayer->getFaction()) {
								clearError(3);
								target->unlock();
								return false;
							}
						}
					} else {
						if (!target->isAttackableBy(creature)) {
							clearError(3);
							target->unlock();
							return false;
						}
					}

					target->unlock();
				} catch (...) {
					System::out << "Unreported Exception in CommandQueueAction::validate()\n";
					target->unlock();
				}
			} else if (skill->isHealSkill()) {
				return checkHealSkill();
			}
		} else { // target == creature
			if (skill->isAttackSkill()) {
				clearError(3);
				return false;
			}
		}
	}

	return true;
}

bool CommandQueueAction::checkHealSkill() {

	if (target->isAttackableObject()) {
		clearError(3);
		return false;
	}

	CreatureObject* targetObject = (CreatureObject*) target.get();
	if (targetObject != creature) {
		try {
			targetObject->wlock(creature);

			if (target->isPlayer()) {
				Player* targetPlayer = (Player*) target.get();

				if (player->isInDuelWith(targetPlayer, false))
					target = creature;
				else if (player->isOvert() && targetPlayer->isOvert()
						&& player->getFaction() != targetPlayer->getFaction())
					target = creature;
				else if (!player->isOvert() && targetPlayer->isOvert())
					target = creature;
			} else if (target->isNonPlayerCreature() && !skill->isDiagnoseSkill() && !skill->isDragSkill())
				target = creature;

			if (!creature->isInRange(target->getPositionX(), target->getPositionY(), skill->getRange())) {
				targetObject->unlock();
				clearError(4);
				return false;
			}

			if (targetObject->isDead() && !skill->isReviveSkill() && !skill->isDragSkill()) {
				clearError(3);
				targetObject->unlock();
				return false;
			}

			targetObject->unlock();
		} catch (...) {
			targetObject->unlock();
		}
	}

	return true;
}

bool CommandQueueAction::checkWeapon() {
	int requiredWeapon = skill->getRequiredWeaponType();

	if (requiredWeapon != 0xFF) {
		weapon = creature->getWeapon();

		if (weapon != NULL) {
			if (requiredWeapon == 0x10 || requiredWeapon == 0x20 ||
					requiredWeapon == 0x30) {
				if (weapon->getCategory() != requiredWeapon) {
					clearError(0);
					if (player != NULL)
						player->sendSystemMessage("cbt_spam", "no_attack_wrong_weapon"); // Can't be done with this weapon
					return false;
				}
			} else if (weapon->getType() != requiredWeapon) {
				clearError(0);
				if (player != NULL)
					player->sendSystemMessage("cbt_spam", "no_attack_wrong_weapon"); // Can't be done with this weapon
				return false;
			}
		} else if (requiredWeapon != 0) {
			clearError(0);
			if (player != NULL)
				player->sendSystemMessage("cbt_spam", "no_attack_wrong_weapon"); // Can't be done with this weapon
			return false;
		}
	}

	if (creature->isKneeling()) {
		if (requiredWeapon < 4 || requiredWeapon == 0x10) {
			clearError(1,4);
			return false;
		}
	}

	if (creature->isProne()) {
		if (requiredWeapon < 4 || requiredWeapon > 6 || requiredWeapon == 0x10 || requiredWeapon == 0x30) {
			clearError(1,7);
			return false;
		}
	}

	return true;
}

void CommandQueueAction::clear(float timer, uint32 tab1, uint32 tab2) {
	if (player != NULL)
		player->clearQueueAction(actionCounter, timer, tab1, tab2);
}
<|endoftext|>


<commit_before>/************************************************************************************
 * Copyright (C) 2017, Copyright Holders of the ALICE Collaboration                 *
 * All rights reserved.                                                             *
 *                                                                                *
 * Redistribution and use in source and binary forms, with or without               *
 * modification, are permitted provided that the following conditions are met:      *
 *     * Redistributions of source code must retain the above copyright             *
 *       notice, this list of conditions and the following disclaimer.              *
 *     * Redistributions in binary form must reproduce the above copyright          *
 *       notice, this list of conditions and the following disclaimer in the        *
 *       documentation and/or other materials provided with the distribution.       *
 *     * Neither the name of the <organization> nor the                             *
 *       names of its contributors may be used to endorse or promote products       *
 *       derived from this software without specific prior written permission.      *
 *                                                                                *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND  *
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED    *
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE           *
 * DISCLAIMED. IN NO EVENT SHALL ALICE COLLABORATION BE LIABLE FOR ANY              *
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES       *
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;     *
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND      *
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT       *
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS    *
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                     *
 ************************************************************************************/
#include <algorithm>
#include <array>
#include <string>
#include <sstream>
#include <vector>
#include <THistManager.h>
#include <TCustomBinning.h>
#include <TLinearBinning.h>

#include "AliAODInputHandler.h"
#include "AliAnalysisManager.h"
#include "AliAnalysisTaskEmcalJetEnergyScale.h"
#include "AliEmcalTriggerDecisionContainer.h"
#include "AliEmcalAnalysisFactory.h"
#include "AliLog.h"
#include "AliVEventHandler.h"

ClassImp(EmcalTriggerJets::AliAnalysisTaskEmcalJetEnergyScale)

using namespace EmcalTriggerJets;

AliAnalysisTaskEmcalJetEnergyScale::AliAnalysisTaskEmcalJetEnergyScale():
  AliAnalysisTaskEmcalJet(),
  fHistos(nullptr),
  fNameDetectorJets(),
  fNameParticleJets(),
  fTriggerSelectionString(),
  fNameTriggerDecisionContainer("EmcalTriggerDecision")
{
}

AliAnalysisTaskEmcalJetEnergyScale::AliAnalysisTaskEmcalJetEnergyScale(const char *name):
  AliAnalysisTaskEmcalJet(name, true),
  fHistos(nullptr),
  fNameDetectorJets(),
  fNameParticleJets(),
  fTriggerSelectionString(),
  fNameTriggerDecisionContainer("EmcalTriggerDecision")
{
  SetUseAliAnaUtils(true);
  DefineOutput(1, TList::Class());
}

AliAnalysisTaskEmcalJetEnergyScale::~AliAnalysisTaskEmcalJetEnergyScale() {
  if(fHistos) delete fHistos;
}

void AliAnalysisTaskEmcalJetEnergyScale::UserCreateOutputObjects(){
  AliAnalysisTaskEmcal::UserCreateOutputObjects();

  TLinearBinning jetPtBinning(300, 0., 300.), nefbinning(100, 0., 1.), ptdiffbinning(200, -1., 1.), jetEtaBinning(100, -0.9, 0.9), jetPhiBinning(100, 0., TMath::TwoPi());

  const TBinning *diffbinning[3] = {&jetPtBinning, &nefbinning, &ptdiffbinning},
                 *corrbinning[3] = {&jetPtBinning, &jetPtBinning, &nefbinning},
                 *effbinning[3] = {&jetPtBinning, &jetEtaBinning, &jetPhiBinning};

  fHistos = new THistManager("energyScaleHistos");
  fHistos->CreateTH1("hEventCounter", "Event counter", 1, 0.5, 1.5);
  fHistos->CreateTHnSparse("hPtDiff", "pt diff det/part", 3., diffbinning, "s");
  fHistos->CreateTHnSparse("hPtCorr", "Correlation det pt / part pt", 3., corrbinning, "s");
  fHistos->CreateTHnSparse("hPartJetsAccepted", "Accepted particle level jets", 3, effbinning, "s");
  fHistos->CreateTHnSparse("hPartJetsReconstructed", "Accepted and reconstructed particle level jets", 3, effbinning, "s");
  for(auto h : *(fHistos->GetListOfHistograms())) fOutput->Add(h);

  PostData(1, fOutput);
}

Bool_t AliAnalysisTaskEmcalJetEnergyScale::Run(){
  AliDebugStream(1) << "Next event" << std::endl;
  if(!(fInputHandler->IsEventSelected() & AliVEvent::kINT7)) return false;
  if(IsSelectEmcalTriggers(fTriggerSelectionString.Data())){
    auto mctrigger = static_cast<PWG::EMCAL::AliEmcalTriggerDecisionContainer *>(fInputEvent->FindListObject(fNameTriggerDecisionContainer));
    AliDebugStream(1) << "Found trigger decision object: " << (mctrigger ? "yes" : "no") << std::endl;
    if(!mctrigger){
      AliErrorStream() <<  "Trigger decision container with name " << fNameTriggerDecisionContainer << " not found in event - not possible to select EMCAL triggers" << std::endl;
      return false;
    }
    if(!mctrigger->IsEventSelected(fTriggerSelectionString)) return false;
  }
  AliDebugStream(1) << "event selected" << std::endl;
  fHistos->FillTH1("hEventCounter", 1);

  auto detjets = GetJetContainer(fNameDetectorJets),
       partjets = GetJetContainer(fNameParticleJets);
  if(!detjets || !partjets) {
    AliErrorStream() << "At least one jet container missing, exiting ..." << std::endl;
    return false;
  }
  AliDebugStream(1) << "Have both jet containers: part(" << partjets->GetNAcceptedJets() << "|" << partjets->GetNJets() << "), det(" << detjets->GetNAcceptedJets() << "|" << detjets->GetNJets() << ")" << std::endl;

  std::vector<AliEmcalJet *> taggedjets;
  for(auto detjet : detjets->accepted()){
    AliDebugStream(2) << "Next jet" << std::endl;
    auto partjet = detjet->ClosestJet();
    if(!partjet) {
      AliDebugStream(2) << "No tagged jet" << std::endl;
      continue;
    }
    taggedjets.emplace_back(partjet);
    double pointCorr[3] = {partjet->Pt(), detjet->Pt(), detjet->NEF()},
           pointDiff[3] = {partjet->Pt(), detjet->NEF(), (detjet->Pt()-partjet->Pt())/partjet->Pt()};
    fHistos->FillTHnSparse("hPtDiff", pointDiff);
    fHistos->FillTHnSparse("hPtCorr", pointCorr);
  }

  // efficiency x acceptance: Add histos for all accepted and reconstucted accepted jets
  for(auto partjet : partjets->accepted()){
    double pvect[3] = {partjet->Pt(), partjet->Eta(), partjet->Phi()};
    if(pvect[2] < 0) pvect[2] += TMath::TwoPi();
    fHistos->FillTHnSparse("hPartJetsAccepted", pvect);
    if(std::find(taggedjets.begin(), taggedjets.end(), partjet) != taggedjets.end()) fHistos->FillTHnSparse("hPartJetsReconstructed", pvect);
  }
  return true;
}

bool AliAnalysisTaskEmcalJetEnergyScale::IsSelectEmcalTriggers(const TString &triggerstring) const {
  const std::array<TString, 8> kEMCALTriggers = {
    "EJ1", "EJ2", "DJ1", "DJ2", "EG1", "EG2", "DG1", "DG2"
  };
  bool isEMCAL = false;
  for(auto emcaltrg : kEMCALTriggers) {
    if(triggerstring.Contains(emcaltrg)) {
      isEMCAL = true;
      break;
    }
  }
  return isEMCAL;
}

AliAnalysisTaskEmcalJetEnergyScale *AliAnalysisTaskEmcalJetEnergyScale::AddTaskJetEnergyScale(AliJetContainer::EJetType_t jettype, Double_t jetradius, Bool_t useDCAL, const char *trigger) {
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if(!mgr){
    ::Error("EmcalTriggerJets::AliAnalysisTaskEmcalJetEnergyScale::AddTaskJetEnergyScale", "No analysis manager available");
    return nullptr;
  }

  auto inputhandler = mgr->GetInputEventHandler();
  auto isAOD = inputhandler->IsA() == AliAODInputHandler::Class();

  std::string jettypename;
  AliJetContainer::JetAcceptanceType acceptance(AliJetContainer::kTPCfid);
  bool addClusterContainer(false), addTrackContainer(false);
  switch(jettype){
    case AliJetContainer::kFullJet:
        jettypename = "FullJet";
        acceptance = useDCAL ? AliJetContainer::kDCALfid : AliJetContainer::kEMCALfid;
        addClusterContainer = addTrackContainer = true;
        break;
    case AliJetContainer::kChargedJet:
        jettypename = "ChargedJet";
        acceptance = AliJetContainer::kTPCfid;
        addTrackContainer = true;
        break;
    case AliJetContainer::kNeutralJet:
        jettypename = "NeutralJet";
        acceptance = useDCAL ? AliJetContainer::kDCALfid : AliJetContainer::kEMCALfid;
        addClusterContainer = true;
        break;
  };

  std::stringstream taskname, tag;
  tag << jettypename << "_R" << std::setw(2) << std::setfill('0') << int(jetradius * 10.) << "_" << trigger;
  taskname << "EnergyScaleTask_" << tag.str();
  AliAnalysisTaskEmcalJetEnergyScale *energyscaletask = new AliAnalysisTaskEmcalJetEnergyScale(taskname.str().data());
  mgr->AddTask(energyscaletask);
  energyscaletask->SetTriggerName(trigger);

  auto partcont = energyscaletask->AddMCParticleContainer("mcparticles");
  partcont->SetMinPt(0.);

  AliClusterContainer *clusters(nullptr);
  if(addClusterContainer) {
    clusters = energyscaletask->AddClusterContainer(EMCalTriggerPtAnalysis::AliEmcalAnalysisFactory::ClusterContainerNameFactory(isAOD));
    switch(jettype){
      case AliJetContainer::kChargedJet: break;     // Silence compiler
      case AliJetContainer::kFullJet:
        clusters->SetDefaultClusterEnergy(AliVCluster::kHadCorr);
        clusters->SetClusHadCorrEnergyCut(0.3);
        break;
      case AliJetContainer::kNeutralJet:
        clusters->SetDefaultClusterEnergy(AliVCluster::kNonLinCorr);
        clusters->SetClusNonLinCorrEnergyCut(0.3);
        break;
    };
  }
  AliTrackContainer *tracks(nullptr);
  if(addTrackContainer) {
    tracks = energyscaletask->AddTrackContainer(EMCalTriggerPtAnalysis::AliEmcalAnalysisFactory::TrackContainerNameFactory(isAOD));
  }

  auto contpartjet = energyscaletask->AddJetContainer(jettype, AliJetContainer::antikt_algorithm, AliJetContainer::E_scheme, jetradius,
                                                      AliJetContainer::kTPCfid, partcont, nullptr);
  contpartjet->SetName("particleLevelJets");
  energyscaletask->SetNamePartJetContainer("particleLevelJets");
  std::cout << "Adding particle-level jet container with underling array: " << contpartjet->GetArrayName() << std::endl;

  auto contdetjet = energyscaletask->AddJetContainer(jettype, AliJetContainer::antikt_algorithm, AliJetContainer::E_scheme, jetradius,
                                                     acceptance, tracks, clusters);
  contdetjet->SetName("detectorLevelJets");
  energyscaletask->SetNameDetJetContainer("detectorLevelJets");
  std::cout << "Adding detector-level jet container with underling array: " << contdetjet->GetArrayName() << std::endl;

  std::stringstream outnamebuilder, listnamebuilder;
  listnamebuilder << "EnergyScaleHists_" << tag.str();
  outnamebuilder << mgr->GetCommonFileName() << ":EnergyScaleResults_" << tag.str();

  mgr->ConnectInput(energyscaletask, 0, mgr->GetCommonInputContainer());
  mgr->ConnectOutput(energyscaletask, 1, mgr->CreateContainer(listnamebuilder.str().data(), TList::Class(), AliAnalysisManager::kOutputContainer, outnamebuilder.str().data()));
  return energyscaletask;
} <commit_msg>Increase jet pt range at particle level<commit_after>/************************************************************************************
 * Copyright (C) 2017, Copyright Holders of the ALICE Collaboration                 *
 * All rights reserved.                                                             *
 *                                                                                *
 * Redistribution and use in source and binary forms, with or without               *
 * modification, are permitted provided that the following conditions are met:      *
 *     * Redistributions of source code must retain the above copyright             *
 *       notice, this list of conditions and the following disclaimer.              *
 *     * Redistributions in binary form must reproduce the above copyright          *
 *       notice, this list of conditions and the following disclaimer in the        *
 *       documentation and/or other materials provided with the distribution.       *
 *     * Neither the name of the <organization> nor the                             *
 *       names of its contributors may be used to endorse or promote products       *
 *       derived from this software without specific prior written permission.      *
 *                                                                                *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND  *
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED    *
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE           *
 * DISCLAIMED. IN NO EVENT SHALL ALICE COLLABORATION BE LIABLE FOR ANY              *
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES       *
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;     *
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND      *
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT       *
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS    *
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                     *
 ************************************************************************************/
#include <algorithm>
#include <array>
#include <string>
#include <sstream>
#include <vector>
#include <THistManager.h>
#include <TCustomBinning.h>
#include <TLinearBinning.h>

#include "AliAODInputHandler.h"
#include "AliAnalysisManager.h"
#include "AliAnalysisTaskEmcalJetEnergyScale.h"
#include "AliEmcalTriggerDecisionContainer.h"
#include "AliEmcalAnalysisFactory.h"
#include "AliLog.h"
#include "AliVEventHandler.h"

ClassImp(EmcalTriggerJets::AliAnalysisTaskEmcalJetEnergyScale)

using namespace EmcalTriggerJets;

AliAnalysisTaskEmcalJetEnergyScale::AliAnalysisTaskEmcalJetEnergyScale():
  AliAnalysisTaskEmcalJet(),
  fHistos(nullptr),
  fNameDetectorJets(),
  fNameParticleJets(),
  fTriggerSelectionString(),
  fNameTriggerDecisionContainer("EmcalTriggerDecision")
{
}

AliAnalysisTaskEmcalJetEnergyScale::AliAnalysisTaskEmcalJetEnergyScale(const char *name):
  AliAnalysisTaskEmcalJet(name, true),
  fHistos(nullptr),
  fNameDetectorJets(),
  fNameParticleJets(),
  fTriggerSelectionString(),
  fNameTriggerDecisionContainer("EmcalTriggerDecision")
{
  SetUseAliAnaUtils(true);
  DefineOutput(1, TList::Class());
}

AliAnalysisTaskEmcalJetEnergyScale::~AliAnalysisTaskEmcalJetEnergyScale() {
  if(fHistos) delete fHistos;
}

void AliAnalysisTaskEmcalJetEnergyScale::UserCreateOutputObjects(){
  AliAnalysisTaskEmcal::UserCreateOutputObjects();

  TLinearBinning jetPtBinningDet(300, 0., 300.), jetPtBinningPart(500, 0., 500), nefbinning(100, 0., 1.), ptdiffbinning(200, -1., 1.), jetEtaBinning(100, -0.9, 0.9), jetPhiBinning(100, 0., TMath::TwoPi());

  const TBinning *diffbinning[3] = {&jetPtBinningPart, &nefbinning, &ptdiffbinning},
                 *corrbinning[3] = {&jetPtBinningPart, &jetPtBinningDet, &nefbinning},
                 *effbinning[3] = {&jetPtBinningPart, &jetEtaBinning, &jetPhiBinning};

  fHistos = new THistManager("energyScaleHistos");
  fHistos->CreateTH1("hEventCounter", "Event counter", 1, 0.5, 1.5);
  fHistos->CreateTHnSparse("hPtDiff", "pt diff det/part", 3., diffbinning, "s");
  fHistos->CreateTHnSparse("hPtCorr", "Correlation det pt / part pt", 3., corrbinning, "s");
  fHistos->CreateTHnSparse("hPartJetsAccepted", "Accepted particle level jets", 3, effbinning, "s");
  fHistos->CreateTHnSparse("hPartJetsReconstructed", "Accepted and reconstructed particle level jets", 3, effbinning, "s");
  for(auto h : *(fHistos->GetListOfHistograms())) fOutput->Add(h);

  PostData(1, fOutput);
}

Bool_t AliAnalysisTaskEmcalJetEnergyScale::Run(){
  AliDebugStream(1) << "Next event" << std::endl;
  if(!(fInputHandler->IsEventSelected() & AliVEvent::kINT7)) return false;
  if(IsSelectEmcalTriggers(fTriggerSelectionString.Data())){
    auto mctrigger = static_cast<PWG::EMCAL::AliEmcalTriggerDecisionContainer *>(fInputEvent->FindListObject(fNameTriggerDecisionContainer));
    AliDebugStream(1) << "Found trigger decision object: " << (mctrigger ? "yes" : "no") << std::endl;
    if(!mctrigger){
      AliErrorStream() <<  "Trigger decision container with name " << fNameTriggerDecisionContainer << " not found in event - not possible to select EMCAL triggers" << std::endl;
      return false;
    }
    if(!mctrigger->IsEventSelected(fTriggerSelectionString)) return false;
  }
  AliDebugStream(1) << "event selected" << std::endl;
  fHistos->FillTH1("hEventCounter", 1);

  auto detjets = GetJetContainer(fNameDetectorJets),
       partjets = GetJetContainer(fNameParticleJets);
  if(!detjets || !partjets) {
    AliErrorStream() << "At least one jet container missing, exiting ..." << std::endl;
    return false;
  }
  AliDebugStream(1) << "Have both jet containers: part(" << partjets->GetNAcceptedJets() << "|" << partjets->GetNJets() << "), det(" << detjets->GetNAcceptedJets() << "|" << detjets->GetNJets() << ")" << std::endl;

  std::vector<AliEmcalJet *> taggedjets;
  for(auto detjet : detjets->accepted()){
    AliDebugStream(2) << "Next jet" << std::endl;
    auto partjet = detjet->ClosestJet();
    if(!partjet) {
      AliDebugStream(2) << "No tagged jet" << std::endl;
      continue;
    }
    taggedjets.emplace_back(partjet);
    double pointCorr[3] = {partjet->Pt(), detjet->Pt(), detjet->NEF()},
           pointDiff[3] = {partjet->Pt(), detjet->NEF(), (detjet->Pt()-partjet->Pt())/partjet->Pt()};
    fHistos->FillTHnSparse("hPtDiff", pointDiff);
    fHistos->FillTHnSparse("hPtCorr", pointCorr);
  }

  // efficiency x acceptance: Add histos for all accepted and reconstucted accepted jets
  for(auto partjet : partjets->accepted()){
    double pvect[3] = {partjet->Pt(), partjet->Eta(), partjet->Phi()};
    if(pvect[2] < 0) pvect[2] += TMath::TwoPi();
    fHistos->FillTHnSparse("hPartJetsAccepted", pvect);
    if(std::find(taggedjets.begin(), taggedjets.end(), partjet) != taggedjets.end()) fHistos->FillTHnSparse("hPartJetsReconstructed", pvect);
  }
  return true;
}

bool AliAnalysisTaskEmcalJetEnergyScale::IsSelectEmcalTriggers(const TString &triggerstring) const {
  const std::array<TString, 8> kEMCALTriggers = {
    "EJ1", "EJ2", "DJ1", "DJ2", "EG1", "EG2", "DG1", "DG2"
  };
  bool isEMCAL = false;
  for(auto emcaltrg : kEMCALTriggers) {
    if(triggerstring.Contains(emcaltrg)) {
      isEMCAL = true;
      break;
    }
  }
  return isEMCAL;
}

AliAnalysisTaskEmcalJetEnergyScale *AliAnalysisTaskEmcalJetEnergyScale::AddTaskJetEnergyScale(AliJetContainer::EJetType_t jettype, Double_t jetradius, Bool_t useDCAL, const char *trigger) {
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if(!mgr){
    ::Error("EmcalTriggerJets::AliAnalysisTaskEmcalJetEnergyScale::AddTaskJetEnergyScale", "No analysis manager available");
    return nullptr;
  }

  auto inputhandler = mgr->GetInputEventHandler();
  auto isAOD = inputhandler->IsA() == AliAODInputHandler::Class();

  std::string jettypename;
  AliJetContainer::JetAcceptanceType acceptance(AliJetContainer::kTPCfid);
  bool addClusterContainer(false), addTrackContainer(false);
  switch(jettype){
    case AliJetContainer::kFullJet:
        jettypename = "FullJet";
        acceptance = useDCAL ? AliJetContainer::kDCALfid : AliJetContainer::kEMCALfid;
        addClusterContainer = addTrackContainer = true;
        break;
    case AliJetContainer::kChargedJet:
        jettypename = "ChargedJet";
        acceptance = AliJetContainer::kTPCfid;
        addTrackContainer = true;
        break;
    case AliJetContainer::kNeutralJet:
        jettypename = "NeutralJet";
        acceptance = useDCAL ? AliJetContainer::kDCALfid : AliJetContainer::kEMCALfid;
        addClusterContainer = true;
        break;
  };

  std::stringstream taskname, tag;
  tag << jettypename << "_R" << std::setw(2) << std::setfill('0') << int(jetradius * 10.) << "_" << trigger;
  taskname << "EnergyScaleTask_" << tag.str();
  AliAnalysisTaskEmcalJetEnergyScale *energyscaletask = new AliAnalysisTaskEmcalJetEnergyScale(taskname.str().data());
  mgr->AddTask(energyscaletask);
  energyscaletask->SetTriggerName(trigger);

  auto partcont = energyscaletask->AddMCParticleContainer("mcparticles");
  partcont->SetMinPt(0.);

  AliClusterContainer *clusters(nullptr);
  if(addClusterContainer) {
    clusters = energyscaletask->AddClusterContainer(EMCalTriggerPtAnalysis::AliEmcalAnalysisFactory::ClusterContainerNameFactory(isAOD));
    switch(jettype){
      case AliJetContainer::kChargedJet: break;     // Silence compiler
      case AliJetContainer::kFullJet:
        clusters->SetDefaultClusterEnergy(AliVCluster::kHadCorr);
        clusters->SetClusHadCorrEnergyCut(0.3);
        break;
      case AliJetContainer::kNeutralJet:
        clusters->SetDefaultClusterEnergy(AliVCluster::kNonLinCorr);
        clusters->SetClusNonLinCorrEnergyCut(0.3);
        break;
    };
  }
  AliTrackContainer *tracks(nullptr);
  if(addTrackContainer) {
    tracks = energyscaletask->AddTrackContainer(EMCalTriggerPtAnalysis::AliEmcalAnalysisFactory::TrackContainerNameFactory(isAOD));
  }

  auto contpartjet = energyscaletask->AddJetContainer(jettype, AliJetContainer::antikt_algorithm, AliJetContainer::E_scheme, jetradius,
                                                      AliJetContainer::kTPCfid, partcont, nullptr);
  contpartjet->SetName("particleLevelJets");
  energyscaletask->SetNamePartJetContainer("particleLevelJets");
  std::cout << "Adding particle-level jet container with underling array: " << contpartjet->GetArrayName() << std::endl;

  auto contdetjet = energyscaletask->AddJetContainer(jettype, AliJetContainer::antikt_algorithm, AliJetContainer::E_scheme, jetradius,
                                                     acceptance, tracks, clusters);
  contdetjet->SetName("detectorLevelJets");
  energyscaletask->SetNameDetJetContainer("detectorLevelJets");
  std::cout << "Adding detector-level jet container with underling array: " << contdetjet->GetArrayName() << std::endl;

  std::stringstream outnamebuilder, listnamebuilder;
  listnamebuilder << "EnergyScaleHists_" << tag.str();
  outnamebuilder << mgr->GetCommonFileName() << ":EnergyScaleResults_" << tag.str();

  mgr->ConnectInput(energyscaletask, 0, mgr->GetCommonInputContainer());
  mgr->ConnectOutput(energyscaletask, 1, mgr->CreateContainer(listnamebuilder.str().data(), TList::Class(), AliAnalysisManager::kOutputContainer, outnamebuilder.str().data()));
  return energyscaletask;
} <|endoftext|>


<commit_before>#include "engine/resource_manager_base.h"
#include "engine/log.h"
#include "engine/lumix.h"
#include "engine/path.h"
#include "engine/resource.h"
#include "engine/resource_manager.h"

namespace Lumix
{

void ResourceManagerBase::LoadHook::continueLoad(Resource& resource)
{
	ASSERT(resource.isEmpty());
	resource.remRef(); // release from hook
	resource.m_desired_state = Resource::State::EMPTY;
	resource.doLoad();
}

void ResourceManagerBase::create(ResourceType type, ResourceManager& owner)
{
	owner.add(type, this);
	m_owner = &owner;
}

void ResourceManagerBase::destroy()
{
	for (auto iter = m_resources.begin(), end = m_resources.end(); iter != end; ++iter)
	{
		Resource* resource = iter.value();
		if (!resource->isEmpty())
		{
			g_log_error.log("Engine") << "Leaking resource " << resource->getPath().c_str() << "\n";
		}
		destroyResource(*resource);
	}
	m_resources.clear();
}

Resource* ResourceManagerBase::get(const Path& path)
{
	ResourceTable::iterator it = m_resources.find(path.getHash());

	if(m_resources.end() != it)
	{
		return *it;
	}

	return nullptr;
}

Resource* ResourceManagerBase::load(const Path& path)
{
	if (!path.isValid()) return nullptr;
	Resource* resource = get(path);

	if(nullptr == resource)
	{
		resource = createResource(path);
		m_resources.insert(path.getHash(), resource);
	}

	if(resource->isEmpty() && resource->m_desired_state == Resource::State::EMPTY)
	{
		if (m_load_hook && m_load_hook->onBeforeLoad(*resource))
		{
			resource->m_desired_state = Resource::State::READY;
			resource->addRef(); // for hook
			resource->addRef(); // for return value
			return resource;
		}
		resource->doLoad();
	}

	resource->addRef();
	return resource;
}

void ResourceManagerBase::removeUnreferenced()
{
	if (!m_is_unload_enabled) return;

	Array<Resource*> to_remove(m_allocator);
	for (auto* i : m_resources)
	{
		if (i->getRefCount() == 0) to_remove.push(i);
	}

	for (auto* i : to_remove)
	{
		m_resources.erase(i->getPath().getHash());
		destroyResource(*i);
	}
}

void ResourceManagerBase::load(Resource& resource)
{
	if(resource.isEmpty() && resource.m_desired_state == Resource::State::EMPTY)
	{
		if (m_load_hook && m_load_hook->onBeforeLoad(resource))
		{
			resource.addRef(); // for hook
			resource.addRef(); // for return value
			return;
		}
		resource.doLoad();
	}

	resource.addRef();
}

void ResourceManagerBase::unload(const Path& path)
{
	Resource* resource = get(path);
	if (resource) unload(*resource);
}

void ResourceManagerBase::unload(Resource& resource)
{
	int new_ref_count = resource.remRef();
	ASSERT(new_ref_count >= 0);
	if(new_ref_count == 0 && m_is_unload_enabled)
	{
		resource.doUnload();
	}
}

void ResourceManagerBase::reload(const Path& path)
{
	Resource* resource = get(path);
	if(resource) reload(*resource);
}

void ResourceManagerBase::reload(Resource& resource)
{
	resource.doUnload();
	resource.doLoad();
}

void ResourceManagerBase::enableUnload(bool enable)
{
	m_is_unload_enabled = enable;
	if (!enable) return;

	for (auto* resource : m_resources)
	{
		if (resource->getRefCount() == 0)
		{
			resource->doUnload();
		}
	}
}

void ResourceManagerBase::setLoadHook(LoadHook& load_hook)
{
	ASSERT(!m_load_hook);
	m_load_hook = &load_hook;
}

ResourceManagerBase::ResourceManagerBase(IAllocator& allocator)
	: m_resources(allocator)
	, m_allocator(allocator)
	, m_owner(nullptr)
	, m_is_unload_enabled(true)
	, m_load_hook(nullptr)
{ }

ResourceManagerBase::~ResourceManagerBase()
{
	ASSERT(m_resources.empty());
}

} // namespace Lumix
<commit_msg>fixed reference count<commit_after>#include "engine/resource_manager_base.h"
#include "engine/log.h"
#include "engine/lumix.h"
#include "engine/path.h"
#include "engine/resource.h"
#include "engine/resource_manager.h"

namespace Lumix
{

void ResourceManagerBase::LoadHook::continueLoad(Resource& resource)
{
	ASSERT(resource.isEmpty());
	resource.remRef(); // release from hook
	resource.m_desired_state = Resource::State::EMPTY;
	resource.doLoad();
}

void ResourceManagerBase::create(ResourceType type, ResourceManager& owner)
{
	owner.add(type, this);
	m_owner = &owner;
}

void ResourceManagerBase::destroy()
{
	for (auto iter = m_resources.begin(), end = m_resources.end(); iter != end; ++iter)
	{
		Resource* resource = iter.value();
		if (!resource->isEmpty())
		{
			g_log_error.log("Engine") << "Leaking resource " << resource->getPath().c_str() << "\n";
		}
		destroyResource(*resource);
	}
	m_resources.clear();
}

Resource* ResourceManagerBase::get(const Path& path)
{
	ResourceTable::iterator it = m_resources.find(path.getHash());

	if(m_resources.end() != it)
	{
		return *it;
	}

	return nullptr;
}

Resource* ResourceManagerBase::load(const Path& path)
{
	if (!path.isValid()) return nullptr;
	Resource* resource = get(path);

	if(nullptr == resource)
	{
		resource = createResource(path);
		m_resources.insert(path.getHash(), resource);
	}

	if(resource->isEmpty() && resource->m_desired_state == Resource::State::EMPTY)
	{
		if (m_load_hook && m_load_hook->onBeforeLoad(*resource))
		{
			resource->m_desired_state = Resource::State::READY;
			resource->addRef(); // for hook
			resource->addRef(); // for return value
			return resource;
		}
		resource->doLoad();
	}

	resource->addRef();
	return resource;
}

void ResourceManagerBase::removeUnreferenced()
{
	if (!m_is_unload_enabled) return;

	Array<Resource*> to_remove(m_allocator);
	for (auto* i : m_resources)
	{
		if (i->getRefCount() == 0) to_remove.push(i);
	}

	for (auto* i : to_remove)
	{
		m_resources.erase(i->getPath().getHash());
		destroyResource(*i);
	}
}

void ResourceManagerBase::load(Resource& resource)
{
	if(resource.isEmpty() && resource.m_desired_state == Resource::State::EMPTY)
	{
		if (m_load_hook && m_load_hook->onBeforeLoad(resource))
		{
			resource.addRef(); // for hook
			return;
		}
		resource.doLoad();
	}

	resource.addRef();
}

void ResourceManagerBase::unload(const Path& path)
{
	Resource* resource = get(path);
	if (resource) unload(*resource);
}

void ResourceManagerBase::unload(Resource& resource)
{
	int new_ref_count = resource.remRef();
	ASSERT(new_ref_count >= 0);
	if(new_ref_count == 0 && m_is_unload_enabled)
	{
		resource.doUnload();
	}
}

void ResourceManagerBase::reload(const Path& path)
{
	Resource* resource = get(path);
	if(resource) reload(*resource);
}

void ResourceManagerBase::reload(Resource& resource)
{
	resource.doUnload();
	resource.doLoad();
}

void ResourceManagerBase::enableUnload(bool enable)
{
	m_is_unload_enabled = enable;
	if (!enable) return;

	for (auto* resource : m_resources)
	{
		if (resource->getRefCount() == 0)
		{
			resource->doUnload();
		}
	}
}

void ResourceManagerBase::setLoadHook(LoadHook& load_hook)
{
	ASSERT(!m_load_hook);
	m_load_hook = &load_hook;
}

ResourceManagerBase::ResourceManagerBase(IAllocator& allocator)
	: m_resources(allocator)
	, m_allocator(allocator)
	, m_owner(nullptr)
	, m_is_unload_enabled(true)
	, m_load_hook(nullptr)
{ }

ResourceManagerBase::~ResourceManagerBase()
{
	ASSERT(m_resources.empty());
}

} // namespace Lumix
<|endoftext|>


<commit_before>/*****************************************************************\
           __
          / /
		 / /                     __  __
		/ /______    _______    / / / / ________   __       __
	   / ______  \  /_____  \  / / / / / _____  | / /      / /
	  / /      | / _______| / / / / / / /____/ / / /      / /
	 / /      / / / _____  / / / / / / _______/ / /      / /
	/ /      / / / /____/ / / / / / / |______  / |______/ /
   /_/      /_/ |________/ / / / /  \_______/  \_______  /
                          /_/ /_/                     / /
			                                         / /
		       High Level Game Framework            /_/

  ---------------------------------------------------------------

  Copyright (c) 2007-2011 - Rodrigo Braz Monteiro.
  This file is subject to the terms of halley_license.txt.

\*****************************************************************/

#include <halley/utils/utils.h>
#include "halley/text/encode.h"
#include "halley/support/assert.h"
#include "halley/support/exception.h"

using namespace Halley;

static const char* base64dict = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static Bytes base64reverse;

static void initBase64()
{
	static bool hasInit = false;
	if (!hasInit) {
		base64reverse.resize(256);
		for (size_t i=0; i<64; i++) {
			base64reverse[base64dict[i]] = char(i);
		}
		base64reverse['='] = 255;
		hasInit = true;
	}
}

typedef unsigned char uchar;

String Encode::encodeBase16(gsl::span<const Byte> in)
{
	const char characters[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

	String result;
	size_t size = size_t(in.size());
	result.cppStr().resize(size * 2, '0');
	for (size_t i = 0; i < size; ++i) {
		unsigned char c = in[i];
		result[i * 2] = characters[(c & 0xF0) >> 4];
		result[i * 2 + 1] = characters[c & 0x0F];
	}

	return result;
}

void Encode::decodeBase16(const String& in, gsl::span<Byte> bytes)
{
	auto charToVal = [&] (char character) -> uint32_t
	{
		if (character >= 0 && character <= 9) {
			return character - '0';
		} else if (character >= 'A' && character <= 'F') {
			return character - 'A' + 10;
		} else if (character >= 'a' && character <= 'f') {
			return character - 'a' + 10;
		} else {
			throw Exception("Invalid hex string \"" + in + "\".", HalleyExceptions::Utils);
		}
	};

	const size_t inSize = in.size();
	const size_t outSize = inSize / 2;
	Expects(inSize % 2 == 0);
	Expects(size_t(bytes.size()) > outSize);

	for (size_t i = 0; i < outSize; ++i) {
		const auto high = charToVal(in[i * 2]);
		const auto low = charToVal(in[i * 2 + 1]);
		bytes[i] = (high << 4) | low;
	}
}

String Encode::encodeBase16(const Bytes& in)
{
	return encodeBase16(gsl::span<const Byte>(in.data(), in.size()));
}

String Encode::encodeBase64(const Bytes& in)
{
	size_t sz = in.size();
	Bytes result(((sz+2) / 3) * 4);

	for (size_t i=0; i<sz; i+=3) {
		// Input bytes
		int available = std::min(int(sz-i), 3);
		assert (available >= 1);
		unsigned int inByte = (uchar(in[i]) << 16) | (available >= 2 ? uchar(in[i+1]) << 8 : 0u) | (available >= 3 ? uchar(in[i+2]) : 0u);

		// Output bytes
		unsigned int o0 = (inByte >> 18) & 0x3F;
		unsigned int o1 = (inByte >> 12) & 0x3F;
		unsigned int o2 = (inByte >> 6) & 0x3F;
		unsigned int o3 = (inByte >> 0) & 0x3F;

		size_t outPos = i / 3 * 4;
		result[outPos] = base64dict[o0];
		result[outPos+1] = base64dict[o1];
		result[outPos+2] = available >= 2 ? base64dict[o2] : '=';
		result[outPos+3] = available >= 3 ? base64dict[o3] : '=';
	}

	return String(reinterpret_cast<const char*>(result.data()), result.size());
}

Bytes Encode::decodeBase64(const String& in)
{
	initBase64();

	size_t sz = in.length();
	assert(sz % 4 == 0);
	size_t resLen = sz * 3 / 4;
	if (in[sz-2] == '=') resLen -= 2;
	else if (in[sz-1] == '=') resLen -= 1;
	Bytes result(resLen);

	for (size_t i=0; i<sz; i+=4) {
		int b0 = base64reverse[in[i]];
		int b1 = base64reverse[in[i+1]];
		int b2 = base64reverse[in[i+2]];
		int b3 = base64reverse[in[i+3]];

		int available = 3;
		if (b3 == 255) {
			available = 2;
			b3 = 0;
		}
		if (b2 == 255) {
			available = 1;
			b2 = 0;
		}

		unsigned int val = static_cast<unsigned int>((b0 << 18) | (b1 << 12) | (b2 << 6) | (b3));
		size_t outPos = i * 3 / 4;

		result[outPos] = (val >> 16) & 0xFF;
		if (available >= 2) result[outPos+1] = (val >> 8) & 0xFF;
		if (available == 3) result[outPos+2] = (val >> 0) & 0xFF;
	}

	return result;
}

static void flushTo(Vector<char>& toFlush, Vector<char>& dest)
{
	if (toFlush.size() > 0) {
		for (size_t i=0; i<toFlush.size(); i += 127) {
			int toWrite = std::min(int(toFlush.size() - i), 127);
			dest.push_back(char(toWrite));
			dest.insert(dest.end(), toFlush.begin()+i, toFlush.begin()+i+toWrite);
		}
	}
	toFlush.clear();
}

Vector<char> Encode::encodeRLE(const Vector<char>& in)
{
	Vector<char> result;
	Vector<char> toFlush;

	size_t totalLen = in.size();
	for (size_t i=0; i<totalLen; ) {
		// Compute run from here
		char byte = in[i];
		int len = 1;
		for (size_t j = i + 1; j < totalLen && in[j] == byte && len < 127; j++, len++);

		// Length of run, only write as RLE if it's at least 3 bytes long
		if (len >= 3) {
			// Flush any waiting to be flushed
			flushTo(toFlush, result);

			// Encode sequence
			result.push_back(char(0x80 | len));
			result.push_back(byte);

			i += len;
		} else {
			// Insert on list of stuff waiting to be flushed
			toFlush.insert(toFlush.end(), in.begin()+i, in.begin()+i+len);
			i++;
		}
	}
	flushTo(toFlush, result);

	return result;
}

Vector<char> Encode::decodeRLE(const Vector<char>& in)
{
	Vector<char> result;
	for (size_t i=0; i<in.size(); ) {
		int control = in[i];
		int len = control & 0x7F;
		if (control & 0x80) {
			// Sequence
			char byte = in[i+1];
			result.insert(result.end(), len, byte);
			i += 2;
		} else {
			// Bunch of stuff
			result.insert(result.end(), in.begin() + i + 1, in.begin() + i + 1 + len);
			i += len + 1;
		}
	}
	return result;
}
<commit_msg>Fix base16 decoding<commit_after>/*****************************************************************\
           __
          / /
		 / /                     __  __
		/ /______    _______    / / / / ________   __       __
	   / ______  \  /_____  \  / / / / / _____  | / /      / /
	  / /      | / _______| / / / / / / /____/ / / /      / /
	 / /      / / / _____  / / / / / / _______/ / /      / /
	/ /      / / / /____/ / / / / / / |______  / |______/ /
   /_/      /_/ |________/ / / / /  \_______/  \_______  /
                          /_/ /_/                     / /
			                                         / /
		       High Level Game Framework            /_/

  ---------------------------------------------------------------

  Copyright (c) 2007-2011 - Rodrigo Braz Monteiro.
  This file is subject to the terms of halley_license.txt.

\*****************************************************************/

#include <halley/utils/utils.h>
#include "halley/text/encode.h"
#include "halley/support/assert.h"
#include "halley/support/exception.h"

using namespace Halley;

static const char* base64dict = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static Bytes base64reverse;

static void initBase64()
{
	static bool hasInit = false;
	if (!hasInit) {
		base64reverse.resize(256);
		for (size_t i=0; i<64; i++) {
			base64reverse[base64dict[i]] = char(i);
		}
		base64reverse['='] = 255;
		hasInit = true;
	}
}

typedef unsigned char uchar;

String Encode::encodeBase16(gsl::span<const Byte> in)
{
	const char characters[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

	String result;
	size_t size = size_t(in.size());
	result.cppStr().resize(size * 2, '0');
	for (size_t i = 0; i < size; ++i) {
		unsigned char c = in[i];
		result[i * 2] = characters[(c & 0xF0) >> 4];
		result[i * 2 + 1] = characters[c & 0x0F];
	}

	return result;
}

void Encode::decodeBase16(const String& in, gsl::span<Byte> bytes)
{
	auto charToVal = [&] (char character) -> uint32_t
	{
		if (character >= '0' && character <= '9') {
			return character - '0';
		} else if (character >= 'A' && character <= 'F') {
			return character - 'A' + 10;
		} else if (character >= 'a' && character <= 'f') {
			return character - 'a' + 10;
		} else {
			throw Exception("Invalid hex string \"" + in + "\".", HalleyExceptions::Utils);
		}
	};

	const size_t inSize = in.size();
	const size_t outSize = inSize / 2;
	Expects(inSize % 2 == 0);
	Expects(size_t(bytes.size()) >= outSize);

	for (size_t i = 0; i < outSize; ++i) {
		const auto high = charToVal(in[i * 2]);
		const auto low = charToVal(in[i * 2 + 1]);
		bytes[i] = (high << 4) | low;
	}
}

String Encode::encodeBase16(const Bytes& in)
{
	return encodeBase16(gsl::span<const Byte>(in.data(), in.size()));
}

String Encode::encodeBase64(const Bytes& in)
{
	size_t sz = in.size();
	Bytes result(((sz+2) / 3) * 4);

	for (size_t i=0; i<sz; i+=3) {
		// Input bytes
		int available = std::min(int(sz-i), 3);
		assert (available >= 1);
		unsigned int inByte = (uchar(in[i]) << 16) | (available >= 2 ? uchar(in[i+1]) << 8 : 0u) | (available >= 3 ? uchar(in[i+2]) : 0u);

		// Output bytes
		unsigned int o0 = (inByte >> 18) & 0x3F;
		unsigned int o1 = (inByte >> 12) & 0x3F;
		unsigned int o2 = (inByte >> 6) & 0x3F;
		unsigned int o3 = (inByte >> 0) & 0x3F;

		size_t outPos = i / 3 * 4;
		result[outPos] = base64dict[o0];
		result[outPos+1] = base64dict[o1];
		result[outPos+2] = available >= 2 ? base64dict[o2] : '=';
		result[outPos+3] = available >= 3 ? base64dict[o3] : '=';
	}

	return String(reinterpret_cast<const char*>(result.data()), result.size());
}

Bytes Encode::decodeBase64(const String& in)
{
	initBase64();

	size_t sz = in.length();
	assert(sz % 4 == 0);
	size_t resLen = sz * 3 / 4;
	if (in[sz-2] == '=') resLen -= 2;
	else if (in[sz-1] == '=') resLen -= 1;
	Bytes result(resLen);

	for (size_t i=0; i<sz; i+=4) {
		int b0 = base64reverse[in[i]];
		int b1 = base64reverse[in[i+1]];
		int b2 = base64reverse[in[i+2]];
		int b3 = base64reverse[in[i+3]];

		int available = 3;
		if (b3 == 255) {
			available = 2;
			b3 = 0;
		}
		if (b2 == 255) {
			available = 1;
			b2 = 0;
		}

		unsigned int val = static_cast<unsigned int>((b0 << 18) | (b1 << 12) | (b2 << 6) | (b3));
		size_t outPos = i * 3 / 4;

		result[outPos] = (val >> 16) & 0xFF;
		if (available >= 2) result[outPos+1] = (val >> 8) & 0xFF;
		if (available == 3) result[outPos+2] = (val >> 0) & 0xFF;
	}

	return result;
}

static void flushTo(Vector<char>& toFlush, Vector<char>& dest)
{
	if (toFlush.size() > 0) {
		for (size_t i=0; i<toFlush.size(); i += 127) {
			int toWrite = std::min(int(toFlush.size() - i), 127);
			dest.push_back(char(toWrite));
			dest.insert(dest.end(), toFlush.begin()+i, toFlush.begin()+i+toWrite);
		}
	}
	toFlush.clear();
}

Vector<char> Encode::encodeRLE(const Vector<char>& in)
{
	Vector<char> result;
	Vector<char> toFlush;

	size_t totalLen = in.size();
	for (size_t i=0; i<totalLen; ) {
		// Compute run from here
		char byte = in[i];
		int len = 1;
		for (size_t j = i + 1; j < totalLen && in[j] == byte && len < 127; j++, len++);

		// Length of run, only write as RLE if it's at least 3 bytes long
		if (len >= 3) {
			// Flush any waiting to be flushed
			flushTo(toFlush, result);

			// Encode sequence
			result.push_back(char(0x80 | len));
			result.push_back(byte);

			i += len;
		} else {
			// Insert on list of stuff waiting to be flushed
			toFlush.insert(toFlush.end(), in.begin()+i, in.begin()+i+len);
			i++;
		}
	}
	flushTo(toFlush, result);

	return result;
}

Vector<char> Encode::decodeRLE(const Vector<char>& in)
{
	Vector<char> result;
	for (size_t i=0; i<in.size(); ) {
		int control = in[i];
		int len = control & 0x7F;
		if (control & 0x80) {
			// Sequence
			char byte = in[i+1];
			result.insert(result.end(), len, byte);
			i += 2;
		} else {
			// Bunch of stuff
			result.insert(result.end(), in.begin() + i + 1, in.begin() + i + 1 + len);
			i += len + 1;
		}
	}
	return result;
}
<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <stdlib.h> // For random.

#include <cstdlib>
#include <iostream>
#include <thread>

#include <mesos/executor.hpp>

#include <stout/duration.hpp>
#include <stout/lambda.hpp>
#include <stout/os.hpp>

using namespace mesos;

using std::cout;
using std::endl;
using std::string;

void run(ExecutorDriver* driver, const TaskInfo& task)
{
  os::sleep(Seconds(random() % 10));

  TaskStatus status;
  status.mutable_task_id()->MergeFrom(task.task_id());
  status.set_state(TASK_FINISHED);

  driver->sendStatusUpdate(status);
}

class LongLivedExecutor : public Executor
{
public:
  virtual ~LongLivedExecutor() {}

  virtual void registered(ExecutorDriver* driver,
                          const ExecutorInfo& executorInfo,
                          const FrameworkInfo& frameworkInfo,
                          const SlaveInfo& slaveInfo)
  {
    cout << "Registered executor on " << slaveInfo.hostname() << endl;
  }

  virtual void reregistered(ExecutorDriver* driver,
                            const SlaveInfo& slaveInfo)
  {
    cout << "Re-registered executor on " << slaveInfo.hostname() << endl;
  }

  virtual void disconnected(ExecutorDriver* driver) {}

  virtual void launchTask(ExecutorDriver* driver, const TaskInfo& task)
  {
    cout << "Starting task " << task.task_id().value() << endl;

    std::thread thread([=]() {
      run(driver, task);
    });

    thread.detach();

    TaskStatus status;
    status.mutable_task_id()->MergeFrom(task.task_id());
    status.set_state(TASK_RUNNING);

    driver->sendStatusUpdate(status);
  }

  virtual void killTask(ExecutorDriver* driver, const TaskID& taskId) {}
  virtual void frameworkMessage(ExecutorDriver* driver, const string& data) {}
  virtual void shutdown(ExecutorDriver* driver) {}
  virtual void error(ExecutorDriver* driver, const string& message) {}
};

int main(int argc, char** argv)
{
  LongLivedExecutor executor;
  MesosExecutorDriver driver(&executor);
  return driver.run() == DRIVER_STOPPED ? 0 : 1;
}
<commit_msg>Deleted the `run` method in long lived executor.<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <stdlib.h> // For random.

#include <cstdlib>
#include <iostream>
#include <thread>

#include <mesos/executor.hpp>

#include <stout/duration.hpp>
#include <stout/lambda.hpp>
#include <stout/os.hpp>

using namespace mesos;

using std::cout;
using std::endl;
using std::string;

class LongLivedExecutor : public Executor
{
public:
  virtual ~LongLivedExecutor() {}

  virtual void registered(ExecutorDriver* driver,
                          const ExecutorInfo& executorInfo,
                          const FrameworkInfo& frameworkInfo,
                          const SlaveInfo& slaveInfo)
  {
    cout << "Registered executor on " << slaveInfo.hostname() << endl;
  }

  virtual void reregistered(ExecutorDriver* driver,
                            const SlaveInfo& slaveInfo)
  {
    cout << "Re-registered executor on " << slaveInfo.hostname() << endl;
  }

  virtual void disconnected(ExecutorDriver* driver) {}

  virtual void launchTask(ExecutorDriver* driver, const TaskInfo& task)
  {
    cout << "Starting task " << task.task_id().value() << endl;

    std::thread thread([=]() {
      os::sleep(Seconds(random() % 10));

      TaskStatus status;
      status.mutable_task_id()->MergeFrom(task.task_id());
      status.set_state(TASK_FINISHED);

      driver->sendStatusUpdate(status);
    });

    thread.detach();

    TaskStatus status;
    status.mutable_task_id()->MergeFrom(task.task_id());
    status.set_state(TASK_RUNNING);

    driver->sendStatusUpdate(status);
  }

  virtual void killTask(ExecutorDriver* driver, const TaskID& taskId) {}
  virtual void frameworkMessage(ExecutorDriver* driver, const string& data) {}
  virtual void shutdown(ExecutorDriver* driver) {}
  virtual void error(ExecutorDriver* driver, const string& message) {}
};

int main(int argc, char** argv)
{
  LongLivedExecutor executor;
  MesosExecutorDriver driver(&executor);
  return driver.run() == DRIVER_STOPPED ? 0 : 1;
}
<|endoftext|>


<commit_before>#pragma once

#include "road_graph.hpp"

#include "../indexer/feature_data.hpp"
#include "../geometry/point2d.hpp"
#include "../std/scoped_ptr.hpp"
#include "../std/vector.hpp"
#include "../base/cache.hpp"

class Index;
class FeatureType;

namespace routing
{

class IVehicleModel;

class FeaturesRoadGraph : public IRoadGraph
{
  struct CachedFeature
  {
    CachedFeature() : m_speed(0), m_isOneway(false) {}

    buffer_vector<m2::PointD, 32> m_points;
    double m_speed;
    bool m_isOneway;
  };

  CachedFeature const & GetCachedFeature(uint32_t const ftId, FeatureType & ft, bool fullLoad);

public:
  FeaturesRoadGraph(Index const * pIndex, size_t mwmID);

  virtual void GetPossibleTurns(RoadPos const & pos, vector<PossibleTurn> & turns, bool noOptimize = true);
  virtual void ReconstructPath(RoadPosVectorT const & positions, Route & route);

  static uint32_t GetStreetReadScale();

  inline size_t GetMwmID() const { return m_mwmID; }

  double GetCacheMiss() const { return (double)m_cacheMiss / (double)m_cacheAccess; }

private:
  friend class CrossFeaturesLoader;

  bool IsOneWay(FeatureType const & ft) const;
  double GetSpeed(FeatureType const & ft) const;
  void LoadFeature(uint32_t id, FeatureType & ft);

private:
  Index const * m_pIndex;
  size_t m_mwmID;
  scoped_ptr<IVehicleModel> m_vehicleModel;
  my::Cache<uint32_t, CachedFeature> m_cache;

  uint32_t m_cacheMiss;
  uint32_t m_cacheAccess;
};

} // namespace routing
<commit_msg>[routing] Fix division by zero.<commit_after>#pragma once

#include "road_graph.hpp"

#include "../indexer/feature_data.hpp"
#include "../geometry/point2d.hpp"
#include "../std/scoped_ptr.hpp"
#include "../std/vector.hpp"
#include "../base/cache.hpp"

class Index;
class FeatureType;

namespace routing
{

class IVehicleModel;

class FeaturesRoadGraph : public IRoadGraph
{
  struct CachedFeature
  {
    CachedFeature() : m_speed(0), m_isOneway(false) {}

    buffer_vector<m2::PointD, 32> m_points;
    double m_speed;
    bool m_isOneway;
  };

  CachedFeature const & GetCachedFeature(uint32_t const ftId, FeatureType & ft, bool fullLoad);

public:
  FeaturesRoadGraph(Index const * pIndex, size_t mwmID);

  virtual void GetPossibleTurns(RoadPos const & pos, vector<PossibleTurn> & turns, bool noOptimize = true);
  virtual void ReconstructPath(RoadPosVectorT const & positions, Route & route);

  static uint32_t GetStreetReadScale();

  inline size_t GetMwmID() const { return m_mwmID; }

  double GetCacheMiss() const
  {
    if (m_cacheAccess == 0)
      return 0.0;
    return (double)m_cacheMiss / (double)m_cacheAccess;
  }

private:
  friend class CrossFeaturesLoader;

  bool IsOneWay(FeatureType const & ft) const;
  double GetSpeed(FeatureType const & ft) const;
  void LoadFeature(uint32_t id, FeatureType & ft);

private:
  Index const * m_pIndex;
  size_t m_mwmID;
  scoped_ptr<IVehicleModel> m_vehicleModel;
  my::Cache<uint32_t, CachedFeature> m_cache;

  uint32_t m_cacheMiss;
  uint32_t m_cacheAccess;
};

} // namespace routing
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "image_space.h"

#include <sys/types.h>
#include <sys/wait.h>

#include "base/stl_util.h"
#include "base/unix_file/fd_file.h"
#include "gc/accounting/space_bitmap-inl.h"
#include "mirror/abstract_method.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
#include "oat_file.h"
#include "os.h"
#include "runtime.h"
#include "space-inl.h"
#include "utils.h"

namespace art {
namespace gc {
namespace space {

size_t ImageSpace::bitmap_index_ = 0;

ImageSpace::ImageSpace(const std::string& name, MemMap* mem_map)
: MemMapSpace(name, mem_map, mem_map->Size(), kGcRetentionPolicyNeverCollect) {
  const size_t bitmap_index = bitmap_index_++;
  live_bitmap_.reset(accounting::SpaceBitmap::Create(
      StringPrintf("imagespace %s live-bitmap %d", name.c_str(), static_cast<int>(bitmap_index)),
      Begin(), Capacity()));
  DCHECK(live_bitmap_.get() != NULL) << "could not create imagespace live bitmap #" << bitmap_index;
}

static bool GenerateImage(const std::string& image_file_name) {
  const std::string boot_class_path_string(Runtime::Current()->GetBootClassPathString());
  std::vector<std::string> boot_class_path;
  Split(boot_class_path_string, ':', boot_class_path);
  if (boot_class_path.empty()) {
    LOG(FATAL) << "Failed to generate image because no boot class path specified";
  }

  std::vector<char*> arg_vector;

  std::string dex2oat_string(GetAndroidRoot());
  dex2oat_string += (kIsDebugBuild ? "/bin/dex2oatd" : "/bin/dex2oat");
  const char* dex2oat = dex2oat_string.c_str();
  arg_vector.push_back(strdup(dex2oat));

  std::string image_option_string("--image=");
  image_option_string += image_file_name;
  const char* image_option = image_option_string.c_str();
  arg_vector.push_back(strdup(image_option));

  arg_vector.push_back(strdup("--runtime-arg"));
  arg_vector.push_back(strdup("-Xms64m"));

  arg_vector.push_back(strdup("--runtime-arg"));
  arg_vector.push_back(strdup("-Xmx64m"));

  for (size_t i = 0; i < boot_class_path.size(); i++) {
    std::string dex_file_option_string("--dex-file=");
    dex_file_option_string += boot_class_path[i];
    const char* dex_file_option = dex_file_option_string.c_str();
    arg_vector.push_back(strdup(dex_file_option));
  }

  std::string oat_file_option_string("--oat-file=");
  oat_file_option_string += image_file_name;
  oat_file_option_string.erase(oat_file_option_string.size() - 3);
  oat_file_option_string += "oat";
  const char* oat_file_option = oat_file_option_string.c_str();
  arg_vector.push_back(strdup(oat_file_option));

  std::string base_option_string(StringPrintf("--base=0x%x", ART_BASE_ADDRESS));
  arg_vector.push_back(strdup(base_option_string.c_str()));

  if (kIsTargetBuild) {
    arg_vector.push_back(strdup("--image-classes-zip=/system/framework/framework.jar"));
    arg_vector.push_back(strdup("--image-classes=preloaded-classes"));
  } else {
    arg_vector.push_back(strdup("--host"));
  }

  std::string command_line(Join(arg_vector, ' '));
  LOG(INFO) << "GenerateImage: " << command_line;

  arg_vector.push_back(NULL);
  char** argv = &arg_vector[0];

  // fork and exec dex2oat
  pid_t pid = fork();
  if (pid == 0) {
    // no allocation allowed between fork and exec

    // change process groups, so we don't get reaped by ProcessManager
    setpgid(0, 0);

    execv(dex2oat, argv);

    PLOG(FATAL) << "execv(" << dex2oat << ") failed";
    return false;
  } else {
    STLDeleteElements(&arg_vector);

    // wait for dex2oat to finish
    int status;
    pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
    if (got_pid != pid) {
      PLOG(ERROR) << "waitpid failed: wanted " << pid << ", got " << got_pid;
      return false;
    }
    if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
      LOG(ERROR) << dex2oat << " failed: " << command_line;
      return false;
    }
  }
  return true;
}

ImageSpace* ImageSpace::Create(const std::string& original_image_file_name) {
  if (OS::FileExists(original_image_file_name.c_str())) {
    // If the /system file exists, it should be up-to-date, don't try to generate
    return space::ImageSpace::Init(original_image_file_name, false);
  }
  // If the /system file didn't exist, we need to use one from the dalvik-cache.
  // If the cache file exists, try to open, but if it fails, regenerate.
  // If it does not exist, generate.
  std::string image_file_name(GetDalvikCacheFilenameOrDie(original_image_file_name));
  if (OS::FileExists(image_file_name.c_str())) {
    space::ImageSpace* image_space = space::ImageSpace::Init(image_file_name, true);
    if (image_space != NULL) {
      return image_space;
    }
  }
  CHECK(GenerateImage(image_file_name)) << "Failed to generate image: " << image_file_name;
  return space::ImageSpace::Init(image_file_name, true);
}

ImageSpace* ImageSpace::Init(const std::string& image_file_name, bool validate_oat_file) {
  CHECK(!image_file_name.empty());

  uint64_t start_time = 0;
  if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
    start_time = NanoTime();
    LOG(INFO) << "ImageSpace::Init entering image_file_name=" << image_file_name;
  }

  UniquePtr<File> file(OS::OpenFile(image_file_name.c_str(), false));
  if (file.get() == NULL) {
    LOG(ERROR) << "Failed to open " << image_file_name;
    return NULL;
  }
  ImageHeader image_header;
  bool success = file->ReadFully(&image_header, sizeof(image_header));
  if (!success || !image_header.IsValid()) {
    LOG(ERROR) << "Invalid image header " << image_file_name;
    return NULL;
  }
  UniquePtr<MemMap> map(MemMap::MapFileAtAddress(image_header.GetImageBegin(),
                                                 file->GetLength(),
                                                 PROT_READ | PROT_WRITE,
                                                 MAP_PRIVATE | MAP_FIXED,
                                                 file->Fd(),
                                                 0,
                                                 false));
  if (map.get() == NULL) {
    LOG(ERROR) << "Failed to map " << image_file_name;
    return NULL;
  }
  CHECK_EQ(image_header.GetImageBegin(), map->Begin());
  DCHECK_EQ(0, memcmp(&image_header, map->Begin(), sizeof(ImageHeader)));

  Runtime* runtime = Runtime::Current();
  mirror::Object* resolution_method = image_header.GetImageRoot(ImageHeader::kResolutionMethod);
  runtime->SetResolutionMethod(down_cast<mirror::AbstractMethod*>(resolution_method));

  mirror::Object* callee_save_method = image_header.GetImageRoot(ImageHeader::kCalleeSaveMethod);
  runtime->SetCalleeSaveMethod(down_cast<mirror::AbstractMethod*>(callee_save_method), Runtime::kSaveAll);
  callee_save_method = image_header.GetImageRoot(ImageHeader::kRefsOnlySaveMethod);
  runtime->SetCalleeSaveMethod(down_cast<mirror::AbstractMethod*>(callee_save_method), Runtime::kRefsOnly);
  callee_save_method = image_header.GetImageRoot(ImageHeader::kRefsAndArgsSaveMethod);
  runtime->SetCalleeSaveMethod(down_cast<mirror::AbstractMethod*>(callee_save_method), Runtime::kRefsAndArgs);

  UniquePtr<ImageSpace> space(new ImageSpace(image_file_name, map.release()));

  space->oat_file_.reset(space->OpenOatFile());
  if (space->oat_file_.get() == NULL) {
    LOG(ERROR) << "Failed to open oat file for image: " << image_file_name;
    return NULL;
  }

  if (validate_oat_file && !space->ValidateOatFile()) {
    LOG(WARNING) << "Failed to validate oat file for image: " << image_file_name;
    return NULL;
  }

  if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
    LOG(INFO) << "ImageSpace::Init exiting (" << PrettyDuration(NanoTime() - start_time)
             << ") " << *space.get();
  }
  return space.release();
}

OatFile* ImageSpace::OpenOatFile() const {
  const Runtime* runtime = Runtime::Current();
  const ImageHeader& image_header = GetImageHeader();
  // Grab location but don't use Object::AsString as we haven't yet initialized the roots to
  // check the down cast
  mirror::String* oat_location =
      down_cast<mirror::String*>(image_header.GetImageRoot(ImageHeader::kOatLocation));
  std::string oat_filename;
  oat_filename += runtime->GetHostPrefix();
  oat_filename += oat_location->ToModifiedUtf8();
  OatFile* oat_file = OatFile::Open(oat_filename, oat_filename, image_header.GetOatDataBegin(),
                                    !Runtime::Current()->IsCompiler());
  if (oat_file == NULL) {
    LOG(ERROR) << "Failed to open oat file " << oat_filename << " referenced from image.";
    return NULL;
  }
  uint32_t oat_checksum = oat_file->GetOatHeader().GetChecksum();
  uint32_t image_oat_checksum = image_header.GetOatChecksum();
  if (oat_checksum != image_oat_checksum) {
    LOG(ERROR) << "Failed to match oat file checksum " << std::hex << oat_checksum
               << " to expected oat checksum " << std::hex << image_oat_checksum
               << " in image";
    return NULL;
  }
  return oat_file;
}

bool ImageSpace::ValidateOatFile() const {
  CHECK(oat_file_.get() != NULL);
  std::vector<const OatFile::OatDexFile*> oat_dex_files = oat_file_->GetOatDexFiles();
  for (size_t i = 0; i < oat_dex_files.size(); i++) {
    const OatFile::OatDexFile* oat_dex_file = oat_dex_files[i];
    const std::string& dex_file_location = oat_dex_file->GetDexFileLocation();
    uint32_t dex_file_location_checksum;
    if (!DexFile::GetChecksum(dex_file_location.c_str(), dex_file_location_checksum)) {
      LOG(WARNING) << "ValidateOatFile could not find checksum for " << dex_file_location;
      return false;
    }
    if (dex_file_location_checksum != oat_dex_file->GetDexFileLocationChecksum()) {
      LOG(WARNING) << "ValidateOatFile found checksum mismatch between oat file "
                   << oat_file_->GetLocation() << " and dex file " << dex_file_location
                   << " (" << oat_dex_file->GetDexFileLocationChecksum() << " != "
                   << dex_file_location_checksum << ")";
      return false;
    }
  }
  return true;
}

OatFile& ImageSpace::ReleaseOatFile() {
  CHECK(oat_file_.get() != NULL);
  return *oat_file_.release();
}

void ImageSpace::RecordImageAllocations(accounting::SpaceBitmap* live_bitmap) const {
  uint64_t start_time = 0;
  if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
    LOG(INFO) << "ImageSpace::RecordImageAllocations entering";
    start_time = NanoTime();
  }
  DCHECK(!Runtime::Current()->IsStarted());
  CHECK(live_bitmap != NULL);
  byte* current = Begin() + RoundUp(sizeof(ImageHeader), kObjectAlignment);
  byte* end = End();
  while (current < end) {
    DCHECK_ALIGNED(current, kObjectAlignment);
    const mirror::Object* obj = reinterpret_cast<const mirror::Object*>(current);
    live_bitmap->Set(obj);
    current += RoundUp(obj->SizeOf(), kObjectAlignment);
  }
  if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
    LOG(INFO) << "ImageSpace::RecordImageAllocations exiting ("
        << PrettyDuration(NanoTime() - start_time) << ")";
  }
}

void ImageSpace::Dump(std::ostream& os) const {
  os << GetType()
      << "begin=" << reinterpret_cast<void*>(Begin())
      << ",end=" << reinterpret_cast<void*>(End())
      << ",size=" << PrettySize(Size())
      << ",name=\"" << GetName() << "\"]";
}

}  // namespace space
}  // namespace gc
}  // namespace art
<commit_msg>am 266099b1: Merge "Fix mismatched malloc / delete."<commit_after>/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "image_space.h"

#include <sys/types.h>
#include <sys/wait.h>

#include "base/stl_util.h"
#include "base/unix_file/fd_file.h"
#include "gc/accounting/space_bitmap-inl.h"
#include "mirror/abstract_method.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
#include "oat_file.h"
#include "os.h"
#include "runtime.h"
#include "space-inl.h"
#include "utils.h"

namespace art {
namespace gc {
namespace space {

size_t ImageSpace::bitmap_index_ = 0;

ImageSpace::ImageSpace(const std::string& name, MemMap* mem_map)
: MemMapSpace(name, mem_map, mem_map->Size(), kGcRetentionPolicyNeverCollect) {
  const size_t bitmap_index = bitmap_index_++;
  live_bitmap_.reset(accounting::SpaceBitmap::Create(
      StringPrintf("imagespace %s live-bitmap %d", name.c_str(), static_cast<int>(bitmap_index)),
      Begin(), Capacity()));
  DCHECK(live_bitmap_.get() != NULL) << "could not create imagespace live bitmap #" << bitmap_index;
}

static bool GenerateImage(const std::string& image_file_name) {
  const std::string boot_class_path_string(Runtime::Current()->GetBootClassPathString());
  std::vector<std::string> boot_class_path;
  Split(boot_class_path_string, ':', boot_class_path);
  if (boot_class_path.empty()) {
    LOG(FATAL) << "Failed to generate image because no boot class path specified";
  }

  std::vector<std::string> arg_vector;

  const char* dex2oat = GetAndroidRoot();
  std::string dex2oat_string(dex2oat);
  dex2oat_string += (kIsDebugBuild ? "/bin/dex2oatd" : "/bin/dex2oat");
  arg_vector.push_back(dex2oat_string);

  std::string image_option_string("--image=");
  image_option_string += image_file_name;
  arg_vector.push_back(image_option_string);

  arg_vector.push_back("--runtime-arg");
  arg_vector.push_back("-Xms64m");

  arg_vector.push_back("--runtime-arg");
  arg_vector.push_back("-Xmx64m");

  for (size_t i = 0; i < boot_class_path.size(); i++) {
    arg_vector.push_back(std::string("--dex-file=") + boot_class_path[i]);
  }

  std::string oat_file_option_string("--oat-file=");
  oat_file_option_string += image_file_name;
  oat_file_option_string.erase(oat_file_option_string.size() - 3);
  oat_file_option_string += "oat";
  arg_vector.push_back(oat_file_option_string);

  arg_vector.push_back(StringPrintf("--base=0x%x", ART_BASE_ADDRESS));

  if (kIsTargetBuild) {
    arg_vector.push_back("--image-classes-zip=/system/framework/framework.jar");
    arg_vector.push_back("--image-classes=preloaded-classes");
  } else {
    arg_vector.push_back("--host");
  }

  std::string command_line(Join(arg_vector, ' '));
  LOG(INFO) << "GenerateImage: " << command_line;

  // Convert the args to char pointers.
  std::vector<char*> char_args;
  for (std::vector<std::string>::iterator it = arg_vector.begin(); it != arg_vector.end();
      ++it) {
    char_args.push_back(const_cast<char*>(it->c_str()));
  }
  char_args.push_back(NULL);

  // fork and exec dex2oat
  pid_t pid = fork();
  if (pid == 0) {
    // no allocation allowed between fork and exec

    // change process groups, so we don't get reaped by ProcessManager
    setpgid(0, 0);

    execv(dex2oat, &char_args[0]);

    PLOG(FATAL) << "execv(" << dex2oat << ") failed";
    return false;
  } else {
    if (pid == -1) {
      PLOG(ERROR) << "fork failed";
    }

    // wait for dex2oat to finish
    int status;
    pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
    if (got_pid != pid) {
      PLOG(ERROR) << "waitpid failed: wanted " << pid << ", got " << got_pid;
      return false;
    }
    if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
      LOG(ERROR) << dex2oat << " failed: " << command_line;
      return false;
    }
  }
  return true;
}

ImageSpace* ImageSpace::Create(const std::string& original_image_file_name) {
  if (OS::FileExists(original_image_file_name.c_str())) {
    // If the /system file exists, it should be up-to-date, don't try to generate
    return space::ImageSpace::Init(original_image_file_name, false);
  }
  // If the /system file didn't exist, we need to use one from the dalvik-cache.
  // If the cache file exists, try to open, but if it fails, regenerate.
  // If it does not exist, generate.
  std::string image_file_name(GetDalvikCacheFilenameOrDie(original_image_file_name));
  if (OS::FileExists(image_file_name.c_str())) {
    space::ImageSpace* image_space = space::ImageSpace::Init(image_file_name, true);
    if (image_space != NULL) {
      return image_space;
    }
  }
  CHECK(GenerateImage(image_file_name)) << "Failed to generate image: " << image_file_name;
  return space::ImageSpace::Init(image_file_name, true);
}

ImageSpace* ImageSpace::Init(const std::string& image_file_name, bool validate_oat_file) {
  CHECK(!image_file_name.empty());

  uint64_t start_time = 0;
  if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
    start_time = NanoTime();
    LOG(INFO) << "ImageSpace::Init entering image_file_name=" << image_file_name;
  }

  UniquePtr<File> file(OS::OpenFile(image_file_name.c_str(), false));
  if (file.get() == NULL) {
    LOG(ERROR) << "Failed to open " << image_file_name;
    return NULL;
  }
  ImageHeader image_header;
  bool success = file->ReadFully(&image_header, sizeof(image_header));
  if (!success || !image_header.IsValid()) {
    LOG(ERROR) << "Invalid image header " << image_file_name;
    return NULL;
  }
  UniquePtr<MemMap> map(MemMap::MapFileAtAddress(image_header.GetImageBegin(),
                                                 file->GetLength(),
                                                 PROT_READ | PROT_WRITE,
                                                 MAP_PRIVATE | MAP_FIXED,
                                                 file->Fd(),
                                                 0,
                                                 false));
  if (map.get() == NULL) {
    LOG(ERROR) << "Failed to map " << image_file_name;
    return NULL;
  }
  CHECK_EQ(image_header.GetImageBegin(), map->Begin());
  DCHECK_EQ(0, memcmp(&image_header, map->Begin(), sizeof(ImageHeader)));

  Runtime* runtime = Runtime::Current();
  mirror::Object* resolution_method = image_header.GetImageRoot(ImageHeader::kResolutionMethod);
  runtime->SetResolutionMethod(down_cast<mirror::AbstractMethod*>(resolution_method));

  mirror::Object* callee_save_method = image_header.GetImageRoot(ImageHeader::kCalleeSaveMethod);
  runtime->SetCalleeSaveMethod(down_cast<mirror::AbstractMethod*>(callee_save_method), Runtime::kSaveAll);
  callee_save_method = image_header.GetImageRoot(ImageHeader::kRefsOnlySaveMethod);
  runtime->SetCalleeSaveMethod(down_cast<mirror::AbstractMethod*>(callee_save_method), Runtime::kRefsOnly);
  callee_save_method = image_header.GetImageRoot(ImageHeader::kRefsAndArgsSaveMethod);
  runtime->SetCalleeSaveMethod(down_cast<mirror::AbstractMethod*>(callee_save_method), Runtime::kRefsAndArgs);

  UniquePtr<ImageSpace> space(new ImageSpace(image_file_name, map.release()));

  space->oat_file_.reset(space->OpenOatFile());
  if (space->oat_file_.get() == NULL) {
    LOG(ERROR) << "Failed to open oat file for image: " << image_file_name;
    return NULL;
  }

  if (validate_oat_file && !space->ValidateOatFile()) {
    LOG(WARNING) << "Failed to validate oat file for image: " << image_file_name;
    return NULL;
  }

  if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
    LOG(INFO) << "ImageSpace::Init exiting (" << PrettyDuration(NanoTime() - start_time)
             << ") " << *space.get();
  }
  return space.release();
}

OatFile* ImageSpace::OpenOatFile() const {
  const Runtime* runtime = Runtime::Current();
  const ImageHeader& image_header = GetImageHeader();
  // Grab location but don't use Object::AsString as we haven't yet initialized the roots to
  // check the down cast
  mirror::String* oat_location =
      down_cast<mirror::String*>(image_header.GetImageRoot(ImageHeader::kOatLocation));
  std::string oat_filename;
  oat_filename += runtime->GetHostPrefix();
  oat_filename += oat_location->ToModifiedUtf8();
  OatFile* oat_file = OatFile::Open(oat_filename, oat_filename, image_header.GetOatDataBegin(),
                                    !Runtime::Current()->IsCompiler());
  if (oat_file == NULL) {
    LOG(ERROR) << "Failed to open oat file " << oat_filename << " referenced from image.";
    return NULL;
  }
  uint32_t oat_checksum = oat_file->GetOatHeader().GetChecksum();
  uint32_t image_oat_checksum = image_header.GetOatChecksum();
  if (oat_checksum != image_oat_checksum) {
    LOG(ERROR) << "Failed to match oat file checksum " << std::hex << oat_checksum
               << " to expected oat checksum " << std::hex << image_oat_checksum
               << " in image";
    return NULL;
  }
  return oat_file;
}

bool ImageSpace::ValidateOatFile() const {
  CHECK(oat_file_.get() != NULL);
  std::vector<const OatFile::OatDexFile*> oat_dex_files = oat_file_->GetOatDexFiles();
  for (size_t i = 0; i < oat_dex_files.size(); i++) {
    const OatFile::OatDexFile* oat_dex_file = oat_dex_files[i];
    const std::string& dex_file_location = oat_dex_file->GetDexFileLocation();
    uint32_t dex_file_location_checksum;
    if (!DexFile::GetChecksum(dex_file_location.c_str(), dex_file_location_checksum)) {
      LOG(WARNING) << "ValidateOatFile could not find checksum for " << dex_file_location;
      return false;
    }
    if (dex_file_location_checksum != oat_dex_file->GetDexFileLocationChecksum()) {
      LOG(WARNING) << "ValidateOatFile found checksum mismatch between oat file "
                   << oat_file_->GetLocation() << " and dex file " << dex_file_location
                   << " (" << oat_dex_file->GetDexFileLocationChecksum() << " != "
                   << dex_file_location_checksum << ")";
      return false;
    }
  }
  return true;
}

OatFile& ImageSpace::ReleaseOatFile() {
  CHECK(oat_file_.get() != NULL);
  return *oat_file_.release();
}

void ImageSpace::RecordImageAllocations(accounting::SpaceBitmap* live_bitmap) const {
  uint64_t start_time = 0;
  if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
    LOG(INFO) << "ImageSpace::RecordImageAllocations entering";
    start_time = NanoTime();
  }
  DCHECK(!Runtime::Current()->IsStarted());
  CHECK(live_bitmap != NULL);
  byte* current = Begin() + RoundUp(sizeof(ImageHeader), kObjectAlignment);
  byte* end = End();
  while (current < end) {
    DCHECK_ALIGNED(current, kObjectAlignment);
    const mirror::Object* obj = reinterpret_cast<const mirror::Object*>(current);
    live_bitmap->Set(obj);
    current += RoundUp(obj->SizeOf(), kObjectAlignment);
  }
  if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
    LOG(INFO) << "ImageSpace::RecordImageAllocations exiting ("
        << PrettyDuration(NanoTime() - start_time) << ")";
  }
}

void ImageSpace::Dump(std::ostream& os) const {
  os << GetType()
      << "begin=" << reinterpret_cast<void*>(Begin())
      << ",end=" << reinterpret_cast<void*>(End())
      << ",size=" << PrettySize(Size())
      << ",name=\"" << GetName() << "\"]";
}

}  // namespace space
}  // namespace gc
}  // namespace art
<|endoftext|>


<commit_before><commit_msg>fdo#75962: Write test for this first.<commit_after><|endoftext|>