<commit_before>/*************************************************************************
 *
 *  $RCSfile: unmodpg.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: ka $ $Date: 2001-10-22 13:36:57 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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 library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SVDLAYER
#include <svx/svdlayer.hxx>
#endif
#ifndef _SFXDISPATCH_HXX
#include <sfx2/dispatch.hxx>
#endif
#ifndef _SFXVIEWFRM_HXX
#include <sfx2/viewfrm.hxx>
#endif

#pragma hdrstop

#include "strings.hrc"
#include "glob.hrc"         // STR_BCKGRND, STR_BCKGRNDOBJ
#include "app.hrc"          // SID_SWITCHPAGE

#include "unmodpg.hxx"
#include "sdpage.hxx"
#include "sdresid.hxx"
#include "drawdoc.hxx"

TYPEINIT1(ModifyPageUndoAction, SdUndoAction);

/*************************************************************************
|*
|* Konstruktor
|*
\************************************************************************/

ModifyPageUndoAction::ModifyPageUndoAction(
    SfxUndoManager* pTheManager, // #67720#
    SdDrawDocument* pTheDoc,
    SdPage* pThePage,
    String aTheNewName,
    AutoLayout  eTheNewAutoLayout,
    BOOL bTheNewBckgrndVisible,
    BOOL bTheNewBckgrndObjsVisible)
:   SdUndoAction(pTheDoc),
    mpManager(pTheManager)
{
    DBG_ASSERT(pThePage, "Undo ohne Seite ???");

    pPage                   = pThePage;
    aNewName                = aTheNewName;
    eNewAutoLayout          = eTheNewAutoLayout;
    bNewBckgrndVisible      = bTheNewBckgrndVisible;
    bNewBckgrndObjsVisible  = bTheNewBckgrndObjsVisible;

    eOldAutoLayout          = pPage->GetAutoLayout();

    if (!pPage->IsMasterPage())
    {
        aOldName = pPage->GetName();
        SdrLayerAdmin& rLayerAdmin = pDoc->GetLayerAdmin();
        BYTE aBckgrnd = rLayerAdmin.GetLayerID(String(SdResId(STR_LAYER_BCKGRND)), FALSE);
        BYTE aBckgrndObj = rLayerAdmin.GetLayerID(String(SdResId(STR_LAYER_BCKGRNDOBJ)), FALSE);
        USHORT nPos = 0;
        SetOfByte aVisibleLayers = pPage->GetMasterPageVisibleLayers(nPos);

        bOldBckgrndVisible = aVisibleLayers.IsSet(aBckgrnd);
        bOldBckgrndObjsVisible = aVisibleLayers.IsSet(aBckgrndObj);
    }

    aComment = String(SdResId(STR_UNDO_MODIFY_PAGE));
}

/*************************************************************************
|*
|* Undo()
|*
\************************************************************************/

void ModifyPageUndoAction::Undo()
{
    pPage->SetAutoLayout(eOldAutoLayout, TRUE);

    if (!pPage->IsMasterPage())
    {
        if (pPage->GetName() != aOldName)
        {
            pPage->SetName(aOldName);

            if (pPage->GetPageKind() == PK_STANDARD)
            {
                SdPage* pNotesPage = (SdPage*)pDoc->GetPage(pPage->GetPageNum() + 1);
                pNotesPage->SetName(aOldName);
            }
        }

        SdrLayerAdmin& rLayerAdmin = pDoc->GetLayerAdmin();
        BYTE aBckgrnd = rLayerAdmin.GetLayerID(String(SdResId(STR_LAYER_BCKGRND)), FALSE);
        BYTE aBckgrndObj = rLayerAdmin.GetLayerID(String(SdResId(STR_LAYER_BCKGRNDOBJ)), FALSE);
        USHORT nPos = 0;
        SetOfByte aVisibleLayers;
        aVisibleLayers.Set(aBckgrnd, bOldBckgrndVisible);
        aVisibleLayers.Set(aBckgrndObj, bOldBckgrndObjsVisible);

        nPos = 0;
        pPage->SetMasterPageVisibleLayers(aVisibleLayers, nPos);
    }

    // Redisplay
    SfxViewFrame::Current()->GetDispatcher()->Execute(
        SID_SWITCHPAGE, SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD );

    // #67720# clear undo manager
    if(mpManager)
    {
        // BEWARE: Do this as LAST action here since this will delete
        // all actions which are added, inclusive to this one (!)
        mpManager->Clear();
    }
}

/*************************************************************************
|*
|* Redo()
|*
\************************************************************************/

void ModifyPageUndoAction::Redo()
{
    pPage->SetAutoLayout(eNewAutoLayout, TRUE);

    if (!pPage->IsMasterPage())
    {
        if (pPage->GetName() != aNewName)
        {
            pPage->SetName(aNewName);

            if (pPage->GetPageKind() == PK_STANDARD)
            {
                SdPage* pNotesPage = (SdPage*)pDoc->GetPage(pPage->GetPageNum() + 1);
                pNotesPage->SetName(aNewName);
            }
        }

        SdrLayerAdmin& rLayerAdmin = pDoc->GetLayerAdmin();
        BYTE aBckgrnd = rLayerAdmin.GetLayerID(String(SdResId(STR_LAYER_BCKGRND)), FALSE);
        BYTE aBckgrndObj = rLayerAdmin.GetLayerID(String(SdResId(STR_LAYER_BCKGRNDOBJ)), FALSE);
        USHORT nPos = 0;
        SetOfByte aVisibleLayers;
        aVisibleLayers.Set(aBckgrnd, bNewBckgrndVisible);
        aVisibleLayers.Set(aBckgrndObj, bNewBckgrndObjsVisible);

        nPos = 0;
        pPage->SetMasterPageVisibleLayers(aVisibleLayers, nPos);
    }

    // Redisplay
    SfxViewFrame::Current()->GetDispatcher()->Execute(
        SID_SWITCHPAGE, SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD );

    // #67720# clear undo manager
    if(mpManager)
    {
        // BEWARE: Do this as LAST action here since this will delete
        // all actions which are added, inclusive to this one (!)
        mpManager->Clear();
    }
}

/*************************************************************************
|*
|* Repeat()
|*
\************************************************************************/

void ModifyPageUndoAction::Repeat()
{
    DBG_ASSERT(FALSE, "ModifyPageUndoAction::Repeat: nicht implementiert");
}

/*************************************************************************
|*
|* Destruktor
|*
\************************************************************************/

ModifyPageUndoAction::~ModifyPageUndoAction()
{
}

/*************************************************************************
|*
|* Kommentar liefern
|*
\************************************************************************/

String ModifyPageUndoAction::GetComment() const
{
    return aComment;
}

<commit_msg>#94637# invalidate Selection, there could be objects deleted in tis UNDO which are no longer allowed to be selected then.<commit_after>/*************************************************************************
 *
 *  $RCSfile: unmodpg.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: aw $ $Date: 2001-11-13 18:11:53 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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 library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SVDLAYER
#include <svx/svdlayer.hxx>
#endif
#ifndef _SFXDISPATCH_HXX
#include <sfx2/dispatch.hxx>
#endif
#ifndef _SFXVIEWFRM_HXX
#include <sfx2/viewfrm.hxx>
#endif

#pragma hdrstop

#include "strings.hrc"
#include "glob.hrc"         // STR_BCKGRND, STR_BCKGRNDOBJ
#include "app.hrc"          // SID_SWITCHPAGE

#include "unmodpg.hxx"
#include "sdpage.hxx"
#include "sdresid.hxx"
#include "drawdoc.hxx"

TYPEINIT1(ModifyPageUndoAction, SdUndoAction);

/*************************************************************************
|*
|* Konstruktor
|*
\************************************************************************/

ModifyPageUndoAction::ModifyPageUndoAction(
    SfxUndoManager* pTheManager, // #67720#
    SdDrawDocument* pTheDoc,
    SdPage* pThePage,
    String aTheNewName,
    AutoLayout  eTheNewAutoLayout,
    BOOL bTheNewBckgrndVisible,
    BOOL bTheNewBckgrndObjsVisible)
:   SdUndoAction(pTheDoc),
    mpManager(pTheManager)
{
    DBG_ASSERT(pThePage, "Undo ohne Seite ???");

    pPage                   = pThePage;
    aNewName                = aTheNewName;
    eNewAutoLayout          = eTheNewAutoLayout;
    bNewBckgrndVisible      = bTheNewBckgrndVisible;
    bNewBckgrndObjsVisible  = bTheNewBckgrndObjsVisible;

    eOldAutoLayout          = pPage->GetAutoLayout();

    if (!pPage->IsMasterPage())
    {
        aOldName = pPage->GetName();
        SdrLayerAdmin& rLayerAdmin = pDoc->GetLayerAdmin();
        BYTE aBckgrnd = rLayerAdmin.GetLayerID(String(SdResId(STR_LAYER_BCKGRND)), FALSE);
        BYTE aBckgrndObj = rLayerAdmin.GetLayerID(String(SdResId(STR_LAYER_BCKGRNDOBJ)), FALSE);
        USHORT nPos = 0;
        SetOfByte aVisibleLayers = pPage->GetMasterPageVisibleLayers(nPos);

        bOldBckgrndVisible = aVisibleLayers.IsSet(aBckgrnd);
        bOldBckgrndObjsVisible = aVisibleLayers.IsSet(aBckgrndObj);
    }

    aComment = String(SdResId(STR_UNDO_MODIFY_PAGE));
}

/*************************************************************************
|*
|* Undo()
|*
\************************************************************************/

#ifndef _SVDVITER_HXX
#include <svx/svdviter.hxx>
#endif
#ifndef _SVDVIEW_HXX
#include <svx/svdview.hxx>
#endif
void ModifyPageUndoAction::Undo()
{
    // #94637# invalidate Selection, there could be objects deleted in tis UNDO
    // which are no longer allowed to be selected then.
      SdrViewIter aIter(pPage);
    SdrView* pView = aIter.FirstView();

    while(pView)
    {
        if(pView->HasMarked())
            pView->UnmarkAll();
        pView = aIter.NextView();
    }

    pPage->SetAutoLayout(eOldAutoLayout, TRUE);

    if (!pPage->IsMasterPage())
    {
        if (pPage->GetName() != aOldName)
        {
            pPage->SetName(aOldName);

            if (pPage->GetPageKind() == PK_STANDARD)
            {
                SdPage* pNotesPage = (SdPage*)pDoc->GetPage(pPage->GetPageNum() + 1);
                pNotesPage->SetName(aOldName);
            }
        }

        SdrLayerAdmin& rLayerAdmin = pDoc->GetLayerAdmin();
        BYTE aBckgrnd = rLayerAdmin.GetLayerID(String(SdResId(STR_LAYER_BCKGRND)), FALSE);
        BYTE aBckgrndObj = rLayerAdmin.GetLayerID(String(SdResId(STR_LAYER_BCKGRNDOBJ)), FALSE);
        USHORT nPos = 0;
        SetOfByte aVisibleLayers;
        aVisibleLayers.Set(aBckgrnd, bOldBckgrndVisible);
        aVisibleLayers.Set(aBckgrndObj, bOldBckgrndObjsVisible);

        nPos = 0;
        pPage->SetMasterPageVisibleLayers(aVisibleLayers, nPos);
    }

    // Redisplay
    SfxViewFrame::Current()->GetDispatcher()->Execute(
        SID_SWITCHPAGE, SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD );

    // #67720# clear undo manager
    if(mpManager)
    {
        // BEWARE: Do this as LAST action here since this will delete
        // all actions which are added, inclusive to this one (!)
        mpManager->Clear();
    }
}

/*************************************************************************
|*
|* Redo()
|*
\************************************************************************/

void ModifyPageUndoAction::Redo()
{
    // #94637# invalidate Selection, there could be objects deleted in tis UNDO
    // which are no longer allowed to be selected then.
      SdrViewIter aIter(pPage);
    SdrView* pView = aIter.FirstView();

    while(pView)
    {
        if(pView->HasMarked())
            pView->UnmarkAll();
        pView = aIter.NextView();
    }

    pPage->SetAutoLayout(eNewAutoLayout, TRUE);

    if (!pPage->IsMasterPage())
    {
        if (pPage->GetName() != aNewName)
        {
            pPage->SetName(aNewName);

            if (pPage->GetPageKind() == PK_STANDARD)
            {
                SdPage* pNotesPage = (SdPage*)pDoc->GetPage(pPage->GetPageNum() + 1);
                pNotesPage->SetName(aNewName);
            }
        }

        SdrLayerAdmin& rLayerAdmin = pDoc->GetLayerAdmin();
        BYTE aBckgrnd = rLayerAdmin.GetLayerID(String(SdResId(STR_LAYER_BCKGRND)), FALSE);
        BYTE aBckgrndObj = rLayerAdmin.GetLayerID(String(SdResId(STR_LAYER_BCKGRNDOBJ)), FALSE);
        USHORT nPos = 0;
        SetOfByte aVisibleLayers;
        aVisibleLayers.Set(aBckgrnd, bNewBckgrndVisible);
        aVisibleLayers.Set(aBckgrndObj, bNewBckgrndObjsVisible);

        nPos = 0;
        pPage->SetMasterPageVisibleLayers(aVisibleLayers, nPos);
    }

    // Redisplay
    SfxViewFrame::Current()->GetDispatcher()->Execute(
        SID_SWITCHPAGE, SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD );

    // #67720# clear undo manager
    if(mpManager)
    {
        // BEWARE: Do this as LAST action here since this will delete
        // all actions which are added, inclusive to this one (!)
        mpManager->Clear();
    }
}

/*************************************************************************
|*
|* Repeat()
|*
\************************************************************************/

void ModifyPageUndoAction::Repeat()
{
    DBG_ASSERT(FALSE, "ModifyPageUndoAction::Repeat: nicht implementiert");
}

/*************************************************************************
|*
|* Destruktor
|*
\************************************************************************/

ModifyPageUndoAction::~ModifyPageUndoAction()
{
}

/*************************************************************************
|*
|* Kommentar liefern
|*
\************************************************************************/

String ModifyPageUndoAction::GetComment() const
{
    return aComment;
}

<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2004 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named LICENSE that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* interface header */
#include "PositionTracker.h"

/* implementation system headers */
#include <iostream>
#include <string>

/* implementation common headers */
#include "MathUtils.h"

/* private */

/* protected */

/* public: */

PositionTracker::PositionTracker()
{
  return;
}
PositionTracker::PositionTracker(const PositionTracker& tracker)
  : _trackedItem(tracker._trackedItem),
    _waypointDistance(tracker._waypointDistance)
{
  return;
}
PositionTracker::~PositionTracker()
{
  // clear out all the tracked items vectors
  for (std::map<std::string, TrackedItemVector>::iterator jano = _trackedItem.begin(); jano != _trackedItem.end(); jano++) {
    TrackedItemVector& trackSet = (*jano).second;
    for (unsigned int i = 0; i != trackSet.size(); i++) {
      /* sanity clear */
      trackSet[i]->id = UNSET_ID;
      trackSet[i]->intID = 0;
      trackSet[i]->strID = std::string("");
      trackSet[i]->lastUpdate = TimeKeeper::getNullTime();
      trackSet[i]->position[0] = trackSet[i]->position[1] = trackSet[i]->position[2] = 0.0;
      trackSet[i]->forgotten = true;
      delete trackSet[i];
    }
  }
  _trackedItem.clear();

  // clear out any waypoints
  _waypointDistance.clear();

  return;
}

/* Linear O(n) time to track a new item since the entire vector is
 * searched.  if the item is not found, an item is created and added.
 */
unsigned short PositionTracker::track(const std::string id, std::string group)
{
  TrackedItemVector& trackSet = _trackedItem[group];
  for (unsigned int i = 0; i != trackSet.size(); i++) {
    switch (trackSet[i]->id) {
      case STR_ID:
	if (id == trackSet[i]->strID) {
	  return i;
	}
	break;
      case INT_ID:
      case UNSET_ID:
	break;
      default:
	std::cerr << "Unknown tracker ID type (id == " << trackSet[i]->id << ")" << std::endl;
	break;
    }
  }

  // the item was not found, so create it
  item_t *newTracking = new item_t;
  newTracking->id = STR_ID;
  newTracking->intID = 0;
  newTracking->strID = id;
  newTracking->lastUpdate = TimeKeeper::getNullTime();
  newTracking->position[0] = newTracking->position[1] = newTracking->position[2] = 0.0;
  newTracking->forgotten = false;

  // and add it
  trackSet.push_back(newTracking);

  // nothing is deleted so should be last index
  return trackSet.size() - 1;
}

/* alternative track() passing our own id */
unsigned short PositionTracker::track(long int id, std::string group)
{
  TrackedItemVector& trackSet = _trackedItem[group];
  for (unsigned int i = 0; i != trackSet.size(); i++) {
    switch (trackSet[i]->id) {
      case INT_ID:
	if (id == trackSet[i]->intID) {
	  return i;
	}
	break;
      case STR_ID:
      case UNSET_ID:
	break;
      default:
	std::cerr << "Unknown tracker ID type (id == " << trackSet[i]->id << ")" << std::endl;
	break;
    }
  }

  // the item was not found, so create it
  item_t *newTracking = new item_t;
  newTracking->id = INT_ID;
  newTracking->intID = id;
  newTracking->strID = std::string("");
  newTracking->lastUpdate = TimeKeeper::getNullTime();
  newTracking->position[0] = newTracking->position[1] = newTracking->position[2] = 0.0;
  newTracking->forgotten = false;

  // and add it
  trackSet.push_back(newTracking);

  // nothing is deleted so should be last index
  return trackSet.size() - 1;
}

bool PositionTracker::update(unsigned short int token, const std::string id, const double position[3], std::string group)
{
  TrackedItemVector& trackSet = _trackedItem[group];
  if ((token >= trackSet.size()) ||
      (trackSet[token]->id != STR_ID) ||
      (trackSet[token]->strID != id) ||
      (trackSet[token]->forgotten)) {
    return false;
  }

  trackSet[token]->position[0] = position[0];
  trackSet[token]->position[1] = position[1];
  trackSet[token]->position[2] = position[2];
  trackSet[token]->lastUpdate = TimeKeeper::getCurrent();

  return true;
}
bool PositionTracker::update(unsigned short int token, const std::string id, const float position[3], std::string group)
{
  double pos[3];
  pos[0] = (double)position[0];
  pos[1] = (double)position[1];
  pos[2] = (double)position[2];
  return update(token, id, pos, group);
}
bool PositionTracker::update(unsigned short int token, long int id, const double position[3], std::string group)
{
  TrackedItemVector& trackSet = _trackedItem[group];
  if ((token >= trackSet.size()) ||
      (trackSet[token]->id != INT_ID) ||
      (trackSet[token]->intID != id) ||
      (trackSet[token]->forgotten)) {
    return false;
  }

  trackSet[token]->position[0] = position[0];
  trackSet[token]->position[1] = position[1];
  trackSet[token]->position[2] = position[2];
  trackSet[token]->lastUpdate = TimeKeeper::getCurrent();

  return true;
}
bool PositionTracker::update(unsigned short int token, long int id, const float position[3], std::string group)
{
  double pos[3];
  pos[0] = (double)position[0];
  pos[1] = (double)position[1];
  pos[2] = (double)position[2];
  return update(token, id, pos, group);
}

bool PositionTracker::addWaypoint(const double from[3], const double to[3], double distance)
{
  unsigned short int fromToken, toToken;
  bool updated;
  bool foundPoint;

  TrackedItemVector& waypointSet = _trackedItem[std::string("__waypoint__")];

  // see if the first point already exists
  foundPoint = false;
  for (unsigned int i = 0; i != waypointSet.size(); i++) {
    if ((waypointSet[i]->position[0] = from[0]) &&
	(waypointSet[i]->position[1] = from[1]) &&
	(waypointSet[i]->position[2] = from[2])) {
      foundPoint = true;
      fromToken = waypointSet[i]->intID;
    }
  }
  if (!foundPoint) {
    // add the first point
    unsigned short int nextID = waypointSet.size();
    fromToken = track((long int)nextID, std::string("__waypoint__"));
    updated = update(fromToken, nextID, from, std::string("__waypoint__"));
    if (!updated) {
      std::cerr << "Unable to add waypoint?!" << std::endl;
      return false;
    }
  }

  // see if the second point already exists
  foundPoint = false;
  for (unsigned int i = 0; i != waypointSet.size(); i++) {
    if ((waypointSet[i]->position[0] = to[0]) &&
	(waypointSet[i]->position[1] = to[1]) &&
	(waypointSet[i]->position[2] = to[2])) {
      foundPoint = true;
      toToken = waypointSet[i]->intID;
    }
  }
  if (!foundPoint) {
    // add the second point
    unsigned short int nextID = waypointSet.size();
    toToken = track((long int)nextID, std::string("__waypoint__"));
    updated = update(toToken, nextID, to, std::string("__waypoint__"));
    if (!updated) {
      std::cerr << "Unable to add waypoint?!" << std::endl;
      return false;
    }
  }

  // compute and use real distance if distance passed was negative
  if (distance < 0.0) {
    distance = distanceBetween(fromToken, toToken, std::string("__waypoint__"), std::string("__waypoint__"));
  }
  std::pair<unsigned short int, unsigned short int> waypoint = std::make_pair(fromToken, toToken);

  // see if the waypoint pair have already been added
  /*
  std::map<std::pair<unsigned short int, unsigned short int>, double>::iterator jano = _waypointDistance.find(waypoint);
  if (jano != _waypointDistance.end()) {
    // waypoint already added, but set distance anyways (might be an update)
    (*jano).second = distance;
  }
  */
  _waypointDistance[waypoint] = distance;

  return true;
}
bool PositionTracker::addWaypoint(const float from[3], const float to[3], double distance)
{
  double fromPos[3], toPos[3];
  fromPos[0] = from[0];
  fromPos[1] = from[1];
  fromPos[2] = from[2];
  toPos[0] = to[0];
  toPos[1] = to[1];
  toPos[2] = to[2];
  return addWaypoint(fromPos, toPos, distance);
}

bool PositionTracker::forget(unsigned short int token, const std::string id, std::string group)
{
  TrackedItemVector& trackSet = _trackedItem[group];
  if ((token >= trackSet.size()) ||
      (trackSet[token]->id != STR_ID) ||
      (trackSet[token]->strID != id) ||
      (trackSet[token]->forgotten)) {
    return false;
  }

  trackSet[token]->position[0] = trackSet[token]->position[1] = trackSet[token]->position[2] = 0.0;
  trackSet[token]->forgotten = true;

  return true;
}
bool PositionTracker::forget(unsigned short int token, long int id, std::string group)
{
  TrackedItemVector& trackSet = _trackedItem[group];
  if ((token >= trackSet.size()) ||
      (trackSet[token]->id != INT_ID) ||
      (trackSet[token]->intID != id) ||
      (trackSet[token]->forgotten)) {
    return false;
  }

  trackSet[token]->position[0] = trackSet[token]->position[1] = trackSet[token]->position[2] = 0.0;
  trackSet[token]->forgotten = true;

  return true;
}

double PositionTracker::distanceBetween(unsigned short int fromToken, unsigned short int toToken, std::string fromGroup, std::string toGroup) const
{
  // this indirection nastiness is needed to maintain constness
  std::map <std::string, TrackedItemVector>::const_iterator fromIterator = _trackedItem.find(fromGroup);
  std::map <std::string, TrackedItemVector>::const_iterator toIterator = _trackedItem.find(toGroup);
  const TrackedItemVector& fromSet = (*fromIterator).second;
  const TrackedItemVector& toSet = (*toIterator).second;

  if ((fromToken > fromSet.size()) ||
      (toToken > toSet.size()) ||
      (fromToken == toToken)) {
    return 0.0;
  }

  // basic Cartesian 3-space formula for distance between two points
  double distanceSquared = (((fromSet[fromToken]->position[0] - toSet[toToken]->position[0]) *
			     (fromSet[fromToken]->position[0] - toSet[toToken]->position[0])) +
			    ((fromSet[fromToken]->position[1] - toSet[toToken]->position[1]) *
			     (fromSet[fromToken]->position[1] - toSet[toToken]->position[1])) +
			    ((fromSet[fromToken]->position[2] - toSet[toToken]->position[2]) *
			     (fromSet[fromToken]->position[2] - toSet[toToken]->position[2])));

  return math_util::fastsqrt((float)distanceSquared);
}

double PositionTracker::waypointDistance(unsigned short int fromToken, unsigned short int toToken, std::string fromGroup, std::string toGroup) const
{
  double separationDistance = distanceBetween(fromToken, toToken, fromGroup, toGroup);
  double shortestDistance = separationDistance;

  // horrible linear search
  std::map<std::pair<unsigned short int, unsigned short int>, double>::const_iterator waypointIterator;
  for (waypointIterator = _waypointDistance.begin(); waypointIterator != _waypointDistance.end(); waypointIterator++) {
    double fromDist, toDist, waypointDist;
    fromDist = distanceBetween(fromToken, (*waypointIterator).first.first, fromGroup, std::string("__waypoint__"));
    toDist = distanceBetween((*waypointIterator).first.second, toToken, std::string("__waypoint__"), toGroup);
    waypointDist = fromDist + (*waypointIterator).second + toDist;
    if (waypointDist < shortestDistance) {
      shortestDistance = waypointDist;
    }
  }

  return shortestDistance;
}

unsigned short int PositionTracker::trackedCount(std::string group) const
{
  std::map <std::string, TrackedItemVector>::const_iterator i = _trackedItem.find(group);
  const TrackedItemVector& trackSet = (*i).second;

  return trackSet.size();
}

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>the redefinition of i strikes again<commit_after>/* bzflag
 * Copyright (c) 1993 - 2004 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named LICENSE that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* interface header */
#include "PositionTracker.h"

/* implementation system headers */
#include <iostream>
#include <string>

/* implementation common headers */
#include "MathUtils.h"

/* private */

/* protected */

/* public: */

PositionTracker::PositionTracker()
{
  return;
}
PositionTracker::PositionTracker(const PositionTracker& tracker)
  : _trackedItem(tracker._trackedItem),
    _waypointDistance(tracker._waypointDistance)
{
  return;
}
PositionTracker::~PositionTracker()
{
  // clear out all the tracked items vectors
  for (std::map<std::string, TrackedItemVector>::iterator jano = _trackedItem.begin(); jano != _trackedItem.end(); jano++) {
    TrackedItemVector& trackSet = (*jano).second;
    for (unsigned int i = 0; i != trackSet.size(); i++) {
      /* sanity clear */
      trackSet[i]->id = UNSET_ID;
      trackSet[i]->intID = 0;
      trackSet[i]->strID = std::string("");
      trackSet[i]->lastUpdate = TimeKeeper::getNullTime();
      trackSet[i]->position[0] = trackSet[i]->position[1] = trackSet[i]->position[2] = 0.0;
      trackSet[i]->forgotten = true;
      delete trackSet[i];
    }
  }
  _trackedItem.clear();

  // clear out any waypoints
  _waypointDistance.clear();

  return;
}

/* Linear O(n) time to track a new item since the entire vector is
 * searched.  if the item is not found, an item is created and added.
 */
unsigned short PositionTracker::track(const std::string id, std::string group)
{
  TrackedItemVector& trackSet = _trackedItem[group];
  for (unsigned int i = 0; i != trackSet.size(); i++) {
    switch (trackSet[i]->id) {
      case STR_ID:
	if (id == trackSet[i]->strID) {
	  return i;
	}
	break;
      case INT_ID:
      case UNSET_ID:
	break;
      default:
	std::cerr << "Unknown tracker ID type (id == " << trackSet[i]->id << ")" << std::endl;
	break;
    }
  }

  // the item was not found, so create it
  item_t *newTracking = new item_t;
  newTracking->id = STR_ID;
  newTracking->intID = 0;
  newTracking->strID = id;
  newTracking->lastUpdate = TimeKeeper::getNullTime();
  newTracking->position[0] = newTracking->position[1] = newTracking->position[2] = 0.0;
  newTracking->forgotten = false;

  // and add it
  trackSet.push_back(newTracking);

  // nothing is deleted so should be last index
  return trackSet.size() - 1;
}

/* alternative track() passing our own id */
unsigned short PositionTracker::track(long int id, std::string group)
{
  TrackedItemVector& trackSet = _trackedItem[group];
  for (unsigned int i = 0; i != trackSet.size(); i++) {
    switch (trackSet[i]->id) {
      case INT_ID:
	if (id == trackSet[i]->intID) {
	  return i;
	}
	break;
      case STR_ID:
      case UNSET_ID:
	break;
      default:
	std::cerr << "Unknown tracker ID type (id == " << trackSet[i]->id << ")" << std::endl;
	break;
    }
  }

  // the item was not found, so create it
  item_t *newTracking = new item_t;
  newTracking->id = INT_ID;
  newTracking->intID = id;
  newTracking->strID = std::string("");
  newTracking->lastUpdate = TimeKeeper::getNullTime();
  newTracking->position[0] = newTracking->position[1] = newTracking->position[2] = 0.0;
  newTracking->forgotten = false;

  // and add it
  trackSet.push_back(newTracking);

  // nothing is deleted so should be last index
  return trackSet.size() - 1;
}

bool PositionTracker::update(unsigned short int token, const std::string id, const double position[3], std::string group)
{
  TrackedItemVector& trackSet = _trackedItem[group];
  if ((token >= trackSet.size()) ||
      (trackSet[token]->id != STR_ID) ||
      (trackSet[token]->strID != id) ||
      (trackSet[token]->forgotten)) {
    return false;
  }

  trackSet[token]->position[0] = position[0];
  trackSet[token]->position[1] = position[1];
  trackSet[token]->position[2] = position[2];
  trackSet[token]->lastUpdate = TimeKeeper::getCurrent();

  return true;
}
bool PositionTracker::update(unsigned short int token, const std::string id, const float position[3], std::string group)
{
  double pos[3];
  pos[0] = (double)position[0];
  pos[1] = (double)position[1];
  pos[2] = (double)position[2];
  return update(token, id, pos, group);
}
bool PositionTracker::update(unsigned short int token, long int id, const double position[3], std::string group)
{
  TrackedItemVector& trackSet = _trackedItem[group];
  if ((token >= trackSet.size()) ||
      (trackSet[token]->id != INT_ID) ||
      (trackSet[token]->intID != id) ||
      (trackSet[token]->forgotten)) {
    return false;
  }

  trackSet[token]->position[0] = position[0];
  trackSet[token]->position[1] = position[1];
  trackSet[token]->position[2] = position[2];
  trackSet[token]->lastUpdate = TimeKeeper::getCurrent();

  return true;
}
bool PositionTracker::update(unsigned short int token, long int id, const float position[3], std::string group)
{
  double pos[3];
  pos[0] = (double)position[0];
  pos[1] = (double)position[1];
  pos[2] = (double)position[2];
  return update(token, id, pos, group);
}

bool PositionTracker::addWaypoint(const double from[3], const double to[3], double distance)
{
  unsigned short int fromToken, toToken;
  bool updated;
  bool foundPoint;
  unsigned int i;

  TrackedItemVector& waypointSet = _trackedItem[std::string("__waypoint__")];

  // see if the first point already exists
  foundPoint = false;
  for (i = 0; i != waypointSet.size(); i++) {
    if ((waypointSet[i]->position[0] = from[0]) &&
	(waypointSet[i]->position[1] = from[1]) &&
	(waypointSet[i]->position[2] = from[2])) {
      foundPoint = true;
      fromToken = waypointSet[i]->intID;
    }
  }
  if (!foundPoint) {
    // add the first point
    unsigned short int nextID = waypointSet.size();
    fromToken = track((long int)nextID, std::string("__waypoint__"));
    updated = update(fromToken, nextID, from, std::string("__waypoint__"));
    if (!updated) {
      std::cerr << "Unable to add waypoint?!" << std::endl;
      return false;
    }
  }

  // see if the second point already exists
  foundPoint = false;
  for (i = 0; i != waypointSet.size(); i++) {
    if ((waypointSet[i]->position[0] = to[0]) &&
	(waypointSet[i]->position[1] = to[1]) &&
	(waypointSet[i]->position[2] = to[2])) {
      foundPoint = true;
      toToken = waypointSet[i]->intID;
    }
  }
  if (!foundPoint) {
    // add the second point
    unsigned short int nextID = waypointSet.size();
    toToken = track((long int)nextID, std::string("__waypoint__"));
    updated = update(toToken, nextID, to, std::string("__waypoint__"));
    if (!updated) {
      std::cerr << "Unable to add waypoint?!" << std::endl;
      return false;
    }
  }

  // compute and use real distance if distance passed was negative
  if (distance < 0.0) {
    distance = distanceBetween(fromToken, toToken, std::string("__waypoint__"), std::string("__waypoint__"));
  }
  std::pair<unsigned short int, unsigned short int> waypoint = std::make_pair(fromToken, toToken);

  // see if the waypoint pair have already been added
  /*
  std::map<std::pair<unsigned short int, unsigned short int>, double>::iterator jano = _waypointDistance.find(waypoint);
  if (jano != _waypointDistance.end()) {
    // waypoint already added, but set distance anyways (might be an update)
    (*jano).second = distance;
  }
  */
  _waypointDistance[waypoint] = distance;

  return true;
}
bool PositionTracker::addWaypoint(const float from[3], const float to[3], double distance)
{
  double fromPos[3], toPos[3];
  fromPos[0] = from[0];
  fromPos[1] = from[1];
  fromPos[2] = from[2];
  toPos[0] = to[0];
  toPos[1] = to[1];
  toPos[2] = to[2];
  return addWaypoint(fromPos, toPos, distance);
}

bool PositionTracker::forget(unsigned short int token, const std::string id, std::string group)
{
  TrackedItemVector& trackSet = _trackedItem[group];
  if ((token >= trackSet.size()) ||
      (trackSet[token]->id != STR_ID) ||
      (trackSet[token]->strID != id) ||
      (trackSet[token]->forgotten)) {
    return false;
  }

  trackSet[token]->position[0] = trackSet[token]->position[1] = trackSet[token]->position[2] = 0.0;
  trackSet[token]->forgotten = true;

  return true;
}
bool PositionTracker::forget(unsigned short int token, long int id, std::string group)
{
  TrackedItemVector& trackSet = _trackedItem[group];
  if ((token >= trackSet.size()) ||
      (trackSet[token]->id != INT_ID) ||
      (trackSet[token]->intID != id) ||
      (trackSet[token]->forgotten)) {
    return false;
  }

  trackSet[token]->position[0] = trackSet[token]->position[1] = trackSet[token]->position[2] = 0.0;
  trackSet[token]->forgotten = true;

  return true;
}

double PositionTracker::distanceBetween(unsigned short int fromToken, unsigned short int toToken, std::string fromGroup, std::string toGroup) const
{
  // this indirection nastiness is needed to maintain constness
  std::map <std::string, TrackedItemVector>::const_iterator fromIterator = _trackedItem.find(fromGroup);
  std::map <std::string, TrackedItemVector>::const_iterator toIterator = _trackedItem.find(toGroup);
  const TrackedItemVector& fromSet = (*fromIterator).second;
  const TrackedItemVector& toSet = (*toIterator).second;

  if ((fromToken > fromSet.size()) ||
      (toToken > toSet.size()) ||
      (fromToken == toToken)) {
    return 0.0;
  }

  // basic Cartesian 3-space formula for distance between two points
  double distanceSquared = (((fromSet[fromToken]->position[0] - toSet[toToken]->position[0]) *
			     (fromSet[fromToken]->position[0] - toSet[toToken]->position[0])) +
			    ((fromSet[fromToken]->position[1] - toSet[toToken]->position[1]) *
			     (fromSet[fromToken]->position[1] - toSet[toToken]->position[1])) +
			    ((fromSet[fromToken]->position[2] - toSet[toToken]->position[2]) *
			     (fromSet[fromToken]->position[2] - toSet[toToken]->position[2])));

  return math_util::fastsqrt((float)distanceSquared);
}

double PositionTracker::waypointDistance(unsigned short int fromToken, unsigned short int toToken, std::string fromGroup, std::string toGroup) const
{
  double separationDistance = distanceBetween(fromToken, toToken, fromGroup, toGroup);
  double shortestDistance = separationDistance;

  // horrible linear search
  std::map<std::pair<unsigned short int, unsigned short int>, double>::const_iterator waypointIterator;
  for (waypointIterator = _waypointDistance.begin(); waypointIterator != _waypointDistance.end(); waypointIterator++) {
    double fromDist, toDist, waypointDist;
    fromDist = distanceBetween(fromToken, (*waypointIterator).first.first, fromGroup, std::string("__waypoint__"));
    toDist = distanceBetween((*waypointIterator).first.second, toToken, std::string("__waypoint__"), toGroup);
    waypointDist = fromDist + (*waypointIterator).second + toDist;
    if (waypointDist < shortestDistance) {
      shortestDistance = waypointDist;
    }
  }

  return shortestDistance;
}

unsigned short int PositionTracker::trackedCount(std::string group) const
{
  std::map <std::string, TrackedItemVector>::const_iterator i = _trackedItem.find(group);
  const TrackedItemVector& trackSet = (*i).second;

  return trackSet.size();
}

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>


<commit_before>/*
 *
 * Copyright 2016 gRPC authors.
 *
 * 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 <map>

#include "src/compiler/config.h"
#include "src/compiler/generator_helpers.h"
#include "src/compiler/node_generator_helpers.h"

using grpc::protobuf::Descriptor;
using grpc::protobuf::FileDescriptor;
using grpc::protobuf::MethodDescriptor;
using grpc::protobuf::ServiceDescriptor;
using grpc::protobuf::io::Printer;
using grpc::protobuf::io::StringOutputStream;
using std::map;

namespace grpc_node_generator {
namespace {

// Returns the alias we assign to the module of the given .proto filename
// when importing. Copied entirely from
// github:google/protobuf/src/google/protobuf/compiler/js/js_generator.cc#L154
grpc::string ModuleAlias(const grpc::string filename) {
  // This scheme could technically cause problems if a file includes any 2 of:
  //   foo/bar_baz.proto
  //   foo_bar_baz.proto
  //   foo_bar/baz.proto
  //
  // We'll worry about this problem if/when we actually see it.  This name isn't
  // exposed to users so we can change it later if we need to.
  grpc::string basename = grpc_generator::StripProto(filename);
  basename = grpc_generator::StringReplace(basename, "-", "$");
  basename = grpc_generator::StringReplace(basename, "/", "_");
  basename = grpc_generator::StringReplace(basename, ".", "_");
  return basename + "_pb";
}

// Given a filename like foo/bar/baz.proto, returns the corresponding JavaScript
// message file foo/bar/baz.js
grpc::string GetJSMessageFilename(const grpc::string& filename) {
  grpc::string name = filename;
  return grpc_generator::StripProto(name) + "_pb.js";
}

// Given a filename like foo/bar/baz.proto, returns the root directory
// path ../../
grpc::string GetRootPath(const grpc::string& from_filename,
                         const grpc::string& to_filename) {
  if (to_filename.find("google/protobuf") == 0) {
    // Well-known types (.proto files in the google/protobuf directory) are
    // assumed to come from the 'google-protobuf' npm package.  We may want to
    // generalize this exception later by letting others put generated code in
    // their own npm packages.
    return "google-protobuf/";
  }
  size_t slashes = std::count(from_filename.begin(), from_filename.end(), '/');
  if (slashes == 0) {
    return "./";
  }
  grpc::string result = "";
  for (size_t i = 0; i < slashes; i++) {
    result += "../";
  }
  return result;
}

// Return the relative path to load to_file from the directory containing
// from_file, assuming that both paths are relative to the same directory
grpc::string GetRelativePath(const grpc::string& from_file,
                             const grpc::string& to_file) {
  return GetRootPath(from_file, to_file) + to_file;
}

/* Finds all message types used in all services in the file, and returns them
 * as a map of fully qualified message type name to message descriptor */
map<grpc::string, const Descriptor*> GetAllMessages(
    const FileDescriptor* file) {
  map<grpc::string, const Descriptor*> message_types;
  for (int service_num = 0; service_num < file->service_count();
       service_num++) {
    const ServiceDescriptor* service = file->service(service_num);
    for (int method_num = 0; method_num < service->method_count();
         method_num++) {
      const MethodDescriptor* method = service->method(method_num);
      const Descriptor* input_type = method->input_type();
      const Descriptor* output_type = method->output_type();
      message_types[input_type->full_name()] = input_type;
      message_types[output_type->full_name()] = output_type;
    }
  }
  return message_types;
}

grpc::string MessageIdentifierName(const grpc::string& name) {
  return grpc_generator::StringReplace(name, ".", "_");
}

grpc::string NodeObjectPath(const Descriptor* descriptor) {
  grpc::string module_alias = ModuleAlias(descriptor->file()->name());
  grpc::string name = descriptor->full_name();
  grpc_generator::StripPrefix(&name, descriptor->file()->package() + ".");
  return module_alias + "." + name;
}

// Prints out the message serializer and deserializer functions
void PrintMessageTransformer(const Descriptor* descriptor, Printer* out) {
  map<grpc::string, grpc::string> template_vars;
  grpc::string full_name = descriptor->full_name();
  template_vars["identifier_name"] = MessageIdentifierName(full_name);
  template_vars["name"] = full_name;
  template_vars["node_name"] = NodeObjectPath(descriptor);
  // Print the serializer
  out->Print(template_vars, "function serialize_$identifier_name$(arg) {\n");
  out->Indent();
  out->Print(template_vars, "if (!(arg instanceof $node_name$)) {\n");
  out->Indent();
  out->Print(template_vars,
             "throw new Error('Expected argument of type $name$');\n");
  out->Outdent();
  out->Print("}\n");
  out->Print("return new Buffer(arg.serializeBinary());\n");
  out->Outdent();
  out->Print("}\n\n");

  // Print the deserializer
  out->Print(template_vars,
             "function deserialize_$identifier_name$(buffer_arg) {\n");
  out->Indent();
  out->Print(
      template_vars,
      "return $node_name$.deserializeBinary(new Uint8Array(buffer_arg));\n");
  out->Outdent();
  out->Print("}\n\n");
}

void PrintMethod(const MethodDescriptor* method, Printer* out) {
  const Descriptor* input_type = method->input_type();
  const Descriptor* output_type = method->output_type();
  map<grpc::string, grpc::string> vars;
  vars["service_name"] = method->service()->full_name();
  vars["name"] = method->name();
  vars["input_type"] = NodeObjectPath(input_type);
  vars["input_type_id"] = MessageIdentifierName(input_type->full_name());
  vars["output_type"] = NodeObjectPath(output_type);
  vars["output_type_id"] = MessageIdentifierName(output_type->full_name());
  vars["client_stream"] = method->client_streaming() ? "true" : "false";
  vars["server_stream"] = method->server_streaming() ? "true" : "false";
  out->Print("{\n");
  out->Indent();
  out->Print(vars, "path: '/$service_name$/$name$',\n");
  out->Print(vars, "requestStream: $client_stream$,\n");
  out->Print(vars, "responseStream: $server_stream$,\n");
  out->Print(vars, "requestType: $input_type$,\n");
  out->Print(vars, "responseType: $output_type$,\n");
  out->Print(vars, "requestSerialize: serialize_$input_type_id$,\n");
  out->Print(vars, "requestDeserialize: deserialize_$input_type_id$,\n");
  out->Print(vars, "responseSerialize: serialize_$output_type_id$,\n");
  out->Print(vars, "responseDeserialize: deserialize_$output_type_id$,\n");
  out->Outdent();
  out->Print("}");
}

// Prints out the service descriptor object
void PrintService(const ServiceDescriptor* service, Printer* out) {
  map<grpc::string, grpc::string> template_vars;
  out->Print(GetNodeComments(service, true).c_str());
  template_vars["name"] = service->name();
  out->Print(template_vars, "var $name$Service = exports.$name$Service = {\n");
  out->Indent();
  for (int i = 0; i < service->method_count(); i++) {
    grpc::string method_name =
        grpc_generator::LowercaseFirstLetter(service->method(i)->name());
    out->Print(GetNodeComments(service->method(i), true).c_str());
    out->Print("$method_name$: ", "method_name", method_name);
    PrintMethod(service->method(i), out);
    out->Print(",\n");
    out->Print(GetNodeComments(service->method(i), false).c_str());
  }
  out->Outdent();
  out->Print("};\n\n");
  out->Print(template_vars,
             "exports.$name$Client = "
             "grpc.makeGenericClientConstructor($name$Service);\n");
  out->Print(GetNodeComments(service, false).c_str());
}

void PrintImports(const FileDescriptor* file, Printer* out) {
  out->Print("var grpc = require('grpc');\n");
  if (file->message_type_count() > 0) {
    grpc::string file_path =
        GetRelativePath(file->name(), GetJSMessageFilename(file->name()));
    out->Print("var $module_alias$ = require('$file_path$');\n", "module_alias",
               ModuleAlias(file->name()), "file_path", file_path);
  }

  for (int i = 0; i < file->dependency_count(); i++) {
    grpc::string file_path = GetRelativePath(
        file->name(), GetJSMessageFilename(file->dependency(i)->name()));
    out->Print("var $module_alias$ = require('$file_path$');\n", "module_alias",
               ModuleAlias(file->dependency(i)->name()), "file_path",
               file_path);
  }
  out->Print("\n");
}

void PrintTransformers(const FileDescriptor* file, Printer* out) {
  map<grpc::string, const Descriptor*> messages = GetAllMessages(file);
  for (std::map<grpc::string, const Descriptor*>::iterator it =
           messages.begin();
       it != messages.end(); it++) {
    PrintMessageTransformer(it->second, out);
  }
  out->Print("\n");
}

void PrintServices(const FileDescriptor* file, Printer* out) {
  for (int i = 0; i < file->service_count(); i++) {
    PrintService(file->service(i), out);
  }
}
}  // namespace

grpc::string GenerateFile(const FileDescriptor* file) {
  grpc::string output;
  {
    StringOutputStream output_stream(&output);
    Printer out(&output_stream, '$');

    if (file->service_count() == 0) {
      return output;
    }
    out.Print("// GENERATED CODE -- DO NOT EDIT!\n\n");

    grpc::string leading_comments = GetNodeComments(file, true);
    if (!leading_comments.empty()) {
      out.Print("// Original file comments:\n");
      out.PrintRaw(leading_comments.c_str());
    }

    out.Print("'use strict';\n");

    PrintImports(file, &out);

    PrintTransformers(file, &out);

    PrintServices(file, &out);

    out.Print(GetNodeComments(file, false).c_str());
  }
  return output;
}

}  // namespace grpc_node_generator
<commit_msg>Switch to Buffer.from to avoid using deprecated constructor<commit_after>/*
 *
 * Copyright 2016 gRPC authors.
 *
 * 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 <map>

#include "src/compiler/config.h"
#include "src/compiler/generator_helpers.h"
#include "src/compiler/node_generator_helpers.h"

using grpc::protobuf::Descriptor;
using grpc::protobuf::FileDescriptor;
using grpc::protobuf::MethodDescriptor;
using grpc::protobuf::ServiceDescriptor;
using grpc::protobuf::io::Printer;
using grpc::protobuf::io::StringOutputStream;
using std::map;

namespace grpc_node_generator {
namespace {

// Returns the alias we assign to the module of the given .proto filename
// when importing. Copied entirely from
// github:google/protobuf/src/google/protobuf/compiler/js/js_generator.cc#L154
grpc::string ModuleAlias(const grpc::string filename) {
  // This scheme could technically cause problems if a file includes any 2 of:
  //   foo/bar_baz.proto
  //   foo_bar_baz.proto
  //   foo_bar/baz.proto
  //
  // We'll worry about this problem if/when we actually see it.  This name isn't
  // exposed to users so we can change it later if we need to.
  grpc::string basename = grpc_generator::StripProto(filename);
  basename = grpc_generator::StringReplace(basename, "-", "$");
  basename = grpc_generator::StringReplace(basename, "/", "_");
  basename = grpc_generator::StringReplace(basename, ".", "_");
  return basename + "_pb";
}

// Given a filename like foo/bar/baz.proto, returns the corresponding JavaScript
// message file foo/bar/baz.js
grpc::string GetJSMessageFilename(const grpc::string& filename) {
  grpc::string name = filename;
  return grpc_generator::StripProto(name) + "_pb.js";
}

// Given a filename like foo/bar/baz.proto, returns the root directory
// path ../../
grpc::string GetRootPath(const grpc::string& from_filename,
                         const grpc::string& to_filename) {
  if (to_filename.find("google/protobuf") == 0) {
    // Well-known types (.proto files in the google/protobuf directory) are
    // assumed to come from the 'google-protobuf' npm package.  We may want to
    // generalize this exception later by letting others put generated code in
    // their own npm packages.
    return "google-protobuf/";
  }
  size_t slashes = std::count(from_filename.begin(), from_filename.end(), '/');
  if (slashes == 0) {
    return "./";
  }
  grpc::string result = "";
  for (size_t i = 0; i < slashes; i++) {
    result += "../";
  }
  return result;
}

// Return the relative path to load to_file from the directory containing
// from_file, assuming that both paths are relative to the same directory
grpc::string GetRelativePath(const grpc::string& from_file,
                             const grpc::string& to_file) {
  return GetRootPath(from_file, to_file) + to_file;
}

/* Finds all message types used in all services in the file, and returns them
 * as a map of fully qualified message type name to message descriptor */
map<grpc::string, const Descriptor*> GetAllMessages(
    const FileDescriptor* file) {
  map<grpc::string, const Descriptor*> message_types;
  for (int service_num = 0; service_num < file->service_count();
       service_num++) {
    const ServiceDescriptor* service = file->service(service_num);
    for (int method_num = 0; method_num < service->method_count();
         method_num++) {
      const MethodDescriptor* method = service->method(method_num);
      const Descriptor* input_type = method->input_type();
      const Descriptor* output_type = method->output_type();
      message_types[input_type->full_name()] = input_type;
      message_types[output_type->full_name()] = output_type;
    }
  }
  return message_types;
}

grpc::string MessageIdentifierName(const grpc::string& name) {
  return grpc_generator::StringReplace(name, ".", "_");
}

grpc::string NodeObjectPath(const Descriptor* descriptor) {
  grpc::string module_alias = ModuleAlias(descriptor->file()->name());
  grpc::string name = descriptor->full_name();
  grpc_generator::StripPrefix(&name, descriptor->file()->package() + ".");
  return module_alias + "." + name;
}

// Prints out the message serializer and deserializer functions
void PrintMessageTransformer(const Descriptor* descriptor, Printer* out) {
  map<grpc::string, grpc::string> template_vars;
  grpc::string full_name = descriptor->full_name();
  template_vars["identifier_name"] = MessageIdentifierName(full_name);
  template_vars["name"] = full_name;
  template_vars["node_name"] = NodeObjectPath(descriptor);
  // Print the serializer
  out->Print(template_vars, "function serialize_$identifier_name$(arg) {\n");
  out->Indent();
  out->Print(template_vars, "if (!(arg instanceof $node_name$)) {\n");
  out->Indent();
  out->Print(template_vars,
             "throw new Error('Expected argument of type $name$');\n");
  out->Outdent();
  out->Print("}\n");
  out->Print("return Buffer.from(arg.serializeBinary());\n");
  out->Outdent();
  out->Print("}\n\n");

  // Print the deserializer
  out->Print(template_vars,
             "function deserialize_$identifier_name$(buffer_arg) {\n");
  out->Indent();
  out->Print(
      template_vars,
      "return $node_name$.deserializeBinary(new Uint8Array(buffer_arg));\n");
  out->Outdent();
  out->Print("}\n\n");
}

void PrintMethod(const MethodDescriptor* method, Printer* out) {
  const Descriptor* input_type = method->input_type();
  const Descriptor* output_type = method->output_type();
  map<grpc::string, grpc::string> vars;
  vars["service_name"] = method->service()->full_name();
  vars["name"] = method->name();
  vars["input_type"] = NodeObjectPath(input_type);
  vars["input_type_id"] = MessageIdentifierName(input_type->full_name());
  vars["output_type"] = NodeObjectPath(output_type);
  vars["output_type_id"] = MessageIdentifierName(output_type->full_name());
  vars["client_stream"] = method->client_streaming() ? "true" : "false";
  vars["server_stream"] = method->server_streaming() ? "true" : "false";
  out->Print("{\n");
  out->Indent();
  out->Print(vars, "path: '/$service_name$/$name$',\n");
  out->Print(vars, "requestStream: $client_stream$,\n");
  out->Print(vars, "responseStream: $server_stream$,\n");
  out->Print(vars, "requestType: $input_type$,\n");
  out->Print(vars, "responseType: $output_type$,\n");
  out->Print(vars, "requestSerialize: serialize_$input_type_id$,\n");
  out->Print(vars, "requestDeserialize: deserialize_$input_type_id$,\n");
  out->Print(vars, "responseSerialize: serialize_$output_type_id$,\n");
  out->Print(vars, "responseDeserialize: deserialize_$output_type_id$,\n");
  out->Outdent();
  out->Print("}");
}

// Prints out the service descriptor object
void PrintService(const ServiceDescriptor* service, Printer* out) {
  map<grpc::string, grpc::string> template_vars;
  out->Print(GetNodeComments(service, true).c_str());
  template_vars["name"] = service->name();
  out->Print(template_vars, "var $name$Service = exports.$name$Service = {\n");
  out->Indent();
  for (int i = 0; i < service->method_count(); i++) {
    grpc::string method_name =
        grpc_generator::LowercaseFirstLetter(service->method(i)->name());
    out->Print(GetNodeComments(service->method(i), true).c_str());
    out->Print("$method_name$: ", "method_name", method_name);
    PrintMethod(service->method(i), out);
    out->Print(",\n");
    out->Print(GetNodeComments(service->method(i), false).c_str());
  }
  out->Outdent();
  out->Print("};\n\n");
  out->Print(template_vars,
             "exports.$name$Client = "
             "grpc.makeGenericClientConstructor($name$Service);\n");
  out->Print(GetNodeComments(service, false).c_str());
}

void PrintImports(const FileDescriptor* file, Printer* out) {
  out->Print("var grpc = require('grpc');\n");
  if (file->message_type_count() > 0) {
    grpc::string file_path =
        GetRelativePath(file->name(), GetJSMessageFilename(file->name()));
    out->Print("var $module_alias$ = require('$file_path$');\n", "module_alias",
               ModuleAlias(file->name()), "file_path", file_path);
  }

  for (int i = 0; i < file->dependency_count(); i++) {
    grpc::string file_path = GetRelativePath(
        file->name(), GetJSMessageFilename(file->dependency(i)->name()));
    out->Print("var $module_alias$ = require('$file_path$');\n", "module_alias",
               ModuleAlias(file->dependency(i)->name()), "file_path",
               file_path);
  }
  out->Print("\n");
}

void PrintTransformers(const FileDescriptor* file, Printer* out) {
  map<grpc::string, const Descriptor*> messages = GetAllMessages(file);
  for (std::map<grpc::string, const Descriptor*>::iterator it =
           messages.begin();
       it != messages.end(); it++) {
    PrintMessageTransformer(it->second, out);
  }
  out->Print("\n");
}

void PrintServices(const FileDescriptor* file, Printer* out) {
  for (int i = 0; i < file->service_count(); i++) {
    PrintService(file->service(i), out);
  }
}
}  // namespace

grpc::string GenerateFile(const FileDescriptor* file) {
  grpc::string output;
  {
    StringOutputStream output_stream(&output);
    Printer out(&output_stream, '$');

    if (file->service_count() == 0) {
      return output;
    }
    out.Print("// GENERATED CODE -- DO NOT EDIT!\n\n");

    grpc::string leading_comments = GetNodeComments(file, true);
    if (!leading_comments.empty()) {
      out.Print("// Original file comments:\n");
      out.PrintRaw(leading_comments.c_str());
    }

    out.Print("'use strict';\n");

    PrintImports(file, &out);

    PrintTransformers(file, &out);

    PrintServices(file, &out);

    out.Print(GetNodeComments(file, false).c_str());
  }
  return output;
}

}  // namespace grpc_node_generator
<|endoftext|>


<commit_before>#include "components/BulletMover.h"

#include <bullet/btBulletCollisionCommon.h>
#include <bullet/btBulletDynamicsCommon.h>

namespace Sigma {

	BulletMover::BulletMover(const int entityID) : IBulletShape(entityID), transform(nullptr) {}

	BulletMover::~BulletMover() {}

	void BulletMover::ApplyForces(const double delta) {
		if (this->transform) {
			glm::vec3 deltavec(delta);
			glm::vec3 totalForce;
			glm::vec3 targetrvel;

			for (auto rotitr = this->rotationForces.begin(); rotitr != this->rotationForces.end(); ++rotitr) {
				this->transform->Rotate((*rotitr) * deltavec);
			}

			// Inertial rotation
			targetrvel = _rotationtarget * deltavec;
			if(fabs(targetrvel.x) > 0.0001f || fabs(targetrvel.y) > 0.0001f || fabs(targetrvel.z) > 0.0001f) {
				targetrvel = this->transform->Restrict(targetrvel);
				this->transform->Rotate(targetrvel);
				_rotationtarget -= targetrvel;
			}
			targetrvel = this->transform->Restrict(targetrvel);
			this->rotationForces.clear();

			for (auto forceitr = this->forces.begin(); forceitr != this->forces.end(); ++forceitr) {
				totalForce += *forceitr;
			}

			glm::vec3 finalForce = (totalForce.z * this->transform->GetForward()) +
								   (totalForce.y * this->transform->GetUp()) +
								   (totalForce.x * this->transform->GetRight());

			body->setActivationState(DISABLE_DEACTIVATION);
			this->body->setLinearVelocity(btVector3(finalForce.x, this->body->getLinearVelocity().y() + 0.000000001f, finalForce.z));
		}
	}

	void BulletMover::UpdateTransform() {
		if (this->transform) {
			btTransform trans;
			this->body->getMotionState()->getWorldTransform(trans);
			this->transform->TranslateTo(trans.getOrigin().x(),trans.getOrigin().y(), trans.getOrigin().z());
		}
	}

	void BulletMover::InitializeRigidBody(float x, float y, float z, float rx, float ry, float rz) {
		this->shape = new btCapsuleShape(0.3f, 1.3f);
		btScalar mass = 1;
		btVector3 fallInertia(0,0,0);
		this->motionState =	new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3(x, y, z)));
		btRigidBody::btRigidBodyConstructionInfo fallRigidBodyCI(mass, motionState, shape,fallInertia);
		this->shape->calculateLocalInertia(mass,fallInertia);
		this->body = new btRigidBody(fallRigidBodyCI);
	}

	void BulletMover::InitializeRigidBody() {
		if(this->transform) {
			this->InitializeRigidBody(
				this->transform->GetPosition().x,
				this->transform->GetPosition().y,
				this->transform->GetPosition().z,
				this->transform->GetPitch(),
				this->transform->GetYaw(),
				this->transform->GetRoll()
			);
		}
		else {
			this->InitializeRigidBody(0,1.5f,0,0,0,0);
		}
	}

	// immediate mode rotation (for mouse motion)
	void BulletMover::RotateNow(float x, float y, float z) {
		if (this->transform) {
			this->transform->Rotate(x,y,z);
		}
	}
	void BulletMover::RotateTarget(float x, float y, float z) {
		if (this->transform) {
			this->_rotationtarget += glm::vec3(x,y,z);
		}
	}
}
<commit_msg>Fix entity id type of BulletMover<commit_after>#include "components/BulletMover.h"

#include <bullet/btBulletCollisionCommon.h>
#include <bullet/btBulletDynamicsCommon.h>

namespace Sigma {

	BulletMover::BulletMover(const id_t entityID) : IBulletShape(entityID), transform(nullptr) {}

	BulletMover::~BulletMover() {}

	void BulletMover::ApplyForces(const double delta) {
		if (this->transform) {
			glm::vec3 deltavec(delta);
			glm::vec3 totalForce;
			glm::vec3 targetrvel;

			for (auto rotitr = this->rotationForces.begin(); rotitr != this->rotationForces.end(); ++rotitr) {
				this->transform->Rotate((*rotitr) * deltavec);
			}

			// Inertial rotation
			targetrvel = _rotationtarget * deltavec;
			if(fabs(targetrvel.x) > 0.0001f || fabs(targetrvel.y) > 0.0001f || fabs(targetrvel.z) > 0.0001f) {
				targetrvel = this->transform->Restrict(targetrvel);
				this->transform->Rotate(targetrvel);
				_rotationtarget -= targetrvel;
			}
			targetrvel = this->transform->Restrict(targetrvel);
			this->rotationForces.clear();

			for (auto forceitr = this->forces.begin(); forceitr != this->forces.end(); ++forceitr) {
				totalForce += *forceitr;
			}

			glm::vec3 finalForce = (totalForce.z * this->transform->GetForward()) +
								   (totalForce.y * this->transform->GetUp()) +
								   (totalForce.x * this->transform->GetRight());

			body->setActivationState(DISABLE_DEACTIVATION);
			this->body->setLinearVelocity(btVector3(finalForce.x, this->body->getLinearVelocity().y() + 0.000000001f, finalForce.z));
		}
	}

	void BulletMover::UpdateTransform() {
		if (this->transform) {
			btTransform trans;
			this->body->getMotionState()->getWorldTransform(trans);
			this->transform->TranslateTo(trans.getOrigin().x(),trans.getOrigin().y(), trans.getOrigin().z());
		}
	}

	void BulletMover::InitializeRigidBody(float x, float y, float z, float rx, float ry, float rz) {
		this->shape = new btCapsuleShape(0.3f, 1.3f);
		btScalar mass = 1;
		btVector3 fallInertia(0,0,0);
		this->motionState =	new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3(x, y, z)));
		btRigidBody::btRigidBodyConstructionInfo fallRigidBodyCI(mass, motionState, shape,fallInertia);
		this->shape->calculateLocalInertia(mass,fallInertia);
		this->body = new btRigidBody(fallRigidBodyCI);
	}

	void BulletMover::InitializeRigidBody() {
		if(this->transform) {
			this->InitializeRigidBody(
				this->transform->GetPosition().x,
				this->transform->GetPosition().y,
				this->transform->GetPosition().z,
				this->transform->GetPitch(),
				this->transform->GetYaw(),
				this->transform->GetRoll()
			);
		}
		else {
			this->InitializeRigidBody(0,1.5f,0,0,0,0);
		}
	}

	// immediate mode rotation (for mouse motion)
	void BulletMover::RotateNow(float x, float y, float z) {
		if (this->transform) {
			this->transform->Rotate(x,y,z);
		}
	}
	void BulletMover::RotateTarget(float x, float y, float z) {
		if (this->transform) {
			this->_rotationtarget += glm::vec3(x,y,z);
		}
	}
}
<|endoftext|>


<commit_before>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * 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 "condor_common.h"
#include "condor_debug.h"
#include "selector.h"

void display_fd_set( char *msg, fd_set *set, int max );

int Selector::_fd_select_size = -1;

fd_set *Selector::cached_read_fds = NULL;
fd_set *Selector::cached_write_fds = NULL;
fd_set *Selector::cached_except_fds = NULL;

fd_set *Selector::cached_save_read_fds = NULL;
fd_set *Selector::cached_save_write_fds = NULL;
fd_set *Selector::cached_save_except_fds = NULL;

Selector::Selector()
{
#if defined(WIN32)
		// On Windows, we can't treat fd_set as an open-ended bit array.
		// fd_set can take up to FD_SETSIZE sockets (not any socket whose
		// fd is <= FD_SETSIZE) and that's it. Currently, we set
		// FD_SETSIZE to 1024. I'm not sure what we can do if we ever
		// have more than 1024 sockets to select on.
	fd_set_size = 1;
#else
	int nfdbits = 8 * sizeof(fd_set);
	fd_set_size = ( fd_select_size() + (nfdbits - 1) ) / nfdbits;
#endif

	if ( cached_read_fds ) {
		read_fds = cached_read_fds;
		write_fds = cached_write_fds;
		except_fds = cached_except_fds;

		save_read_fds = cached_save_read_fds;
		save_write_fds = cached_save_write_fds;
		save_except_fds = cached_save_except_fds;

		cached_read_fds = NULL;
		cached_write_fds = NULL;
		cached_except_fds = NULL;
		cached_save_read_fds = NULL;
		cached_save_write_fds = NULL;
		cached_save_except_fds = NULL;
	} else {
		read_fds = (fd_set *)calloc( fd_set_size, sizeof(fd_set) );
		write_fds = (fd_set *)calloc( fd_set_size, sizeof(fd_set) );
		except_fds = (fd_set *)calloc( fd_set_size, sizeof(fd_set) );

		save_read_fds = (fd_set *)calloc( fd_set_size, sizeof(fd_set) );
		save_write_fds = (fd_set *)calloc( fd_set_size, sizeof(fd_set) );
		save_except_fds = (fd_set *)calloc( fd_set_size, sizeof(fd_set) );
	}

	reset();
}

Selector::~Selector()
{
	if ( cached_read_fds == NULL ) {
		cached_read_fds = read_fds;
		cached_write_fds = write_fds;
		cached_except_fds = except_fds;

		cached_save_read_fds = save_read_fds;
		cached_save_write_fds = save_write_fds;
		cached_save_except_fds = save_except_fds;
	} else {
		free( read_fds );
		free( write_fds );
		free( except_fds );

		free( save_read_fds );
		free( save_write_fds );
		free( save_except_fds );
	}
}

void
Selector::reset()
{
	_select_retval = -2;
	state = VIRGIN;
	timeout_wanted = FALSE;
	max_fd = -1;
#if defined(WIN32)
	FD_ZERO( save_read_fds );
	FD_ZERO( save_write_fds );
	FD_ZERO( save_except_fds );
#else
	memset( save_read_fds, 0, fd_set_size * sizeof(fd_set) );
	memset( save_write_fds, 0, fd_set_size * sizeof(fd_set) );
	memset( save_except_fds, 0, fd_set_size * sizeof(fd_set) );
#endif
}

int
Selector::fd_select_size()
{
	if ( _fd_select_size < 0 ) {
#if defined(WIN32)
		// On Windows, fd_set is not a bit-array, but a structure that can
		// hold up to 1024 different file descriptors (not just file
		// descriptors whose value is less than 1024). We set max_fd to
		// 1024 (FD_SETSIZE) as a reasonable approximation.
		_fd_select_size = FD_SETSIZE;
#elif defined(Solaris)
		// Solaris's select() can't handle fds greater than FD_SETSIZE.
		int max_fds = getdtablesize();
		if ( max_fds < FD_SETSIZE ) {
			_fd_select_size = max_fds;
		} else {
			_fd_select_size = FD_SETSIZE;
		}
#else
		_fd_select_size = getdtablesize();
#endif
	}
	return _fd_select_size;
}

void
Selector::add_fd( int fd, IO_FUNC interest )
{
	// update max_fd (the highest valid index in fd_set's array) and also
	// make sure we're not overflowing our fd_set
	//
#if defined(WIN32)
	max_fd++;
	if (max_fd > fd_select_size() - 1) {
		EXCEPT("Selector::add_fd(): fd_set is full");
	}
#else
	if( fd > max_fd ) {
		max_fd = fd;
	}
	if ( fd < 0 || fd >= fd_select_size() ) {
		EXCEPT( "Selector::add_fd(): fd %d outside valid range 0-%d",
				fd, _fd_select_size-1 );
	}
#endif

	switch( interest ) {

	  case IO_READ:
		FD_SET( fd, save_read_fds );
		break;

	  case IO_WRITE:
		FD_SET( fd, save_write_fds );
		break;

	  case IO_EXCEPT:
		FD_SET( fd, save_except_fds );
		break;

	}
}

void
Selector::delete_fd( int fd, IO_FUNC interest )
{
	// on Windows, we need to update max_fd since it keeps track of
	// how many sockets are in our fd_set. in UNIX, just do a sanity
	// check based on the value of fd
	//
#if defined(WIN32)
	max_fd--;
#else
	if ( fd < 0 || fd > fd_select_size() ) {
		EXCEPT( "Selector::delete_fd(): fd %d outside valid range 0-%d",
				fd, _fd_select_size-1 );
	}
#endif

	switch( interest ) {

	  case IO_READ:
		FD_CLR( fd, save_read_fds );
		break;

	  case IO_WRITE:
		FD_CLR( fd, save_write_fds );
		break;

	  case IO_EXCEPT:
		FD_CLR( fd, save_except_fds );
		break;

	}
}

void
Selector::set_timeout( time_t sec, long usec )
{
	timeout_wanted = TRUE;

	timeout.tv_sec = sec;
	timeout.tv_usec = usec;
}

void
Selector::set_timeout( timeval tv )
{
	timeout_wanted = TRUE;

	timeout = tv;
}

void
Selector::unset_timeout()
{
	timeout_wanted = FALSE;
}

void
Selector::execute()
{
	int		nfds;
	struct timeval	*tp;

	memcpy( read_fds, save_read_fds, fd_set_size * sizeof(fd_set) );
	memcpy( write_fds, save_write_fds, fd_set_size * sizeof(fd_set) );
	memcpy( except_fds, save_except_fds, fd_set_size * sizeof(fd_set) );

	if( timeout_wanted ) {
		tp = &timeout;
	} else {
		tp = NULL;
	}

	nfds = select( max_fd + 1,
				  (SELECT_FDSET_PTR) read_fds,
				  (SELECT_FDSET_PTR) write_fds,
				  (SELECT_FDSET_PTR) except_fds,
				  tp );
	_select_retval = nfds;

	if( nfds < 0 ) {
#if !defined(WIN32)
		if( errno == EINTR ) {
			state = SIGNALLED;
			return;
		}
#endif
		state = FAILED;
		return;
	}

	if( nfds == 0 ) {
		state = TIMED_OUT;
	} else {
		state = FDS_READY;
	}
	return;
}

int
Selector::select_retval()
{
	return _select_retval;
}

BOOLEAN
Selector::fd_ready( int fd, IO_FUNC interest )
{
	if( state != FDS_READY && state != TIMED_OUT ) {
		EXCEPT(
			"Selector::fd_ready() called, but selector not in FDS_READY state"
		);
	}

#if !defined(WIN32)
	// on UNIX, make sure the value of fd makes sense
	//
	if ( fd < 0 || fd > fd_select_size() ) {
		return FALSE;
	}
#endif

	switch( interest ) {

	  case IO_READ:
		return FD_ISSET( fd, read_fds );
		break;

	  case IO_WRITE:
		return FD_ISSET( fd, write_fds );
		break;

	  case IO_EXCEPT:
		return FD_ISSET( fd, except_fds );
		break;

	}

		// Can never get here
	return FALSE;
}

BOOLEAN
Selector::timed_out()
{
	return state == TIMED_OUT;
}

BOOLEAN
Selector::signalled()
{
	return state == SIGNALLED;
}

BOOLEAN
Selector::failed()
{
	return state == FAILED;
}

BOOLEAN
Selector::has_ready()
{
	return state == FDS_READY;
}

void
Selector::display()
{

	switch( state ) {

	  case VIRGIN:
		dprintf( D_ALWAYS, "State = VIRGIN\n" );
		break;

	  case FDS_READY:
		dprintf( D_ALWAYS, "State = FDS_READY\n" );
		break;

	  case TIMED_OUT:
		dprintf( D_ALWAYS, "State = TIMED_OUT\n" );
		break;

	  case SIGNALLED:
		dprintf( D_ALWAYS, "State = SIGNALLED\n" );
		break;

	  case FAILED:
		dprintf( D_ALWAYS, "State = FAILED\n" );
		break;
	}

	dprintf( D_ALWAYS, "max_fd = %d\n", max_fd );

	dprintf( D_ALWAYS, "Selection FD's\n" );
	display_fd_set( "\tRead", save_read_fds, max_fd );
	display_fd_set( "\tWrite", save_write_fds, max_fd );
	display_fd_set( "\tExcept", save_except_fds, max_fd );

	if( state == FDS_READY ) {
		dprintf( D_ALWAYS, "Ready FD's\n" );
		display_fd_set( "\tRead", read_fds, max_fd );
		display_fd_set( "\tWrite", write_fds, max_fd );
		display_fd_set( "\tExcept", except_fds, max_fd );
	}
	if( timeout_wanted ) {
		dprintf( D_ALWAYS,
			"Timeout = %ld.%06ld seconds\n", (long) timeout.tv_sec,
			(long) timeout.tv_usec
		);
	} else {
		dprintf( D_ALWAYS, "Timeout not wanted\n" );
	}

}

void
display_fd_set( char *msg, fd_set *set, int max )
{
	int		i;

	dprintf( D_ALWAYS, "%s {", msg );
	for( i=0; i<=max; i++ ) {
		if( FD_ISSET(i,set) ) {
			dprintf( D_ALWAYS | D_NOHEADER, "%d ", i );
		}
	}
	dprintf( D_ALWAYS | D_NOHEADER, "}\n" );
}
<commit_msg>Fix some minor problems in Selector, our wrapper for select(). We have not seen these bite running code yet, so no version history entry. * On Windows, the check for a full fd_set in add_fd() was wrong. * The display functions didn't work correctly on Windows. * Off-by-one errors in checking for out-of-range fds.<commit_after>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * 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 "condor_common.h"
#include "condor_debug.h"
#include "selector.h"

void display_fd_set( char *msg, fd_set *set, int max );

int Selector::_fd_select_size = -1;

fd_set *Selector::cached_read_fds = NULL;
fd_set *Selector::cached_write_fds = NULL;
fd_set *Selector::cached_except_fds = NULL;

fd_set *Selector::cached_save_read_fds = NULL;
fd_set *Selector::cached_save_write_fds = NULL;
fd_set *Selector::cached_save_except_fds = NULL;

Selector::Selector()
{
#if defined(WIN32)
		// On Windows, we can't treat fd_set as an open-ended bit array.
		// fd_set can take up to FD_SETSIZE sockets (not any socket whose
		// fd is <= FD_SETSIZE) and that's it. Currently, we set
		// FD_SETSIZE to 1024. I'm not sure what we can do if we ever
		// have more than 1024 sockets to select on.
	fd_set_size = 1;
#else
	int nfdbits = 8 * sizeof(fd_set);
	fd_set_size = ( fd_select_size() + (nfdbits - 1) ) / nfdbits;
#endif

	if ( cached_read_fds ) {
		read_fds = cached_read_fds;
		write_fds = cached_write_fds;
		except_fds = cached_except_fds;

		save_read_fds = cached_save_read_fds;
		save_write_fds = cached_save_write_fds;
		save_except_fds = cached_save_except_fds;

		cached_read_fds = NULL;
		cached_write_fds = NULL;
		cached_except_fds = NULL;
		cached_save_read_fds = NULL;
		cached_save_write_fds = NULL;
		cached_save_except_fds = NULL;
	} else {
		read_fds = (fd_set *)calloc( fd_set_size, sizeof(fd_set) );
		write_fds = (fd_set *)calloc( fd_set_size, sizeof(fd_set) );
		except_fds = (fd_set *)calloc( fd_set_size, sizeof(fd_set) );

		save_read_fds = (fd_set *)calloc( fd_set_size, sizeof(fd_set) );
		save_write_fds = (fd_set *)calloc( fd_set_size, sizeof(fd_set) );
		save_except_fds = (fd_set *)calloc( fd_set_size, sizeof(fd_set) );
	}

	reset();
}

Selector::~Selector()
{
	if ( cached_read_fds == NULL ) {
		cached_read_fds = read_fds;
		cached_write_fds = write_fds;
		cached_except_fds = except_fds;

		cached_save_read_fds = save_read_fds;
		cached_save_write_fds = save_write_fds;
		cached_save_except_fds = save_except_fds;
	} else {
		free( read_fds );
		free( write_fds );
		free( except_fds );

		free( save_read_fds );
		free( save_write_fds );
		free( save_except_fds );
	}
}

void
Selector::reset()
{
	_select_retval = -2;
	state = VIRGIN;
	timeout_wanted = FALSE;
	max_fd = -1;
#if defined(WIN32)
	FD_ZERO( save_read_fds );
	FD_ZERO( save_write_fds );
	FD_ZERO( save_except_fds );
#else
	memset( save_read_fds, 0, fd_set_size * sizeof(fd_set) );
	memset( save_write_fds, 0, fd_set_size * sizeof(fd_set) );
	memset( save_except_fds, 0, fd_set_size * sizeof(fd_set) );
#endif
}

int
Selector::fd_select_size()
{
	if ( _fd_select_size < 0 ) {
#if defined(WIN32)
		// On Windows, fd_set is not a bit-array, but a structure that can
		// hold up to 1024 different file descriptors (not just file
		// descriptors whose value is less than 1024). We set max_fds to
		// 1024 (FD_SETSIZE) as a reasonable approximation.
		_fd_select_size = FD_SETSIZE;
#elif defined(Solaris)
		// Solaris's select() can't handle fds greater than FD_SETSIZE.
		int max_fds = getdtablesize();
		if ( max_fds < FD_SETSIZE ) {
			_fd_select_size = max_fds;
		} else {
			_fd_select_size = FD_SETSIZE;
		}
#else
		_fd_select_size = getdtablesize();
#endif
	}
	return _fd_select_size;
}

void
Selector::add_fd( int fd, IO_FUNC interest )
{
	// update max_fd (the highest valid index in fd_set's array) and also
	// make sure we're not overflowing our fd_set
	// On Windows, we have to check the individual fd_set to see if it's
	// full.
	if( fd > max_fd ) {
		max_fd = fd;
	}
#if !defined(WIN32)
	if ( fd < 0 || fd >= fd_select_size() ) {
		EXCEPT( "Selector::add_fd(): fd %d outside valid range 0-%d",
				fd, _fd_select_size-1 );
	}
#endif

	switch( interest ) {

	  case IO_READ:
#if defined(WIN32)
		if ( save_read_fds->fd_count >= fd_select_size() ) {
			EXCEPT( "Selector::add_fd(): read fd_set is full" );
		}
#endif
		FD_SET( fd, save_read_fds );
		break;

	  case IO_WRITE:
#if defined(WIN32)
		if ( save_write_fds->fd_count >= fd_select_size() ) {
			EXCEPT( "Selector::add_fd(): write fd_set is full" );
		}
#endif
		FD_SET( fd, save_write_fds );
		break;

	  case IO_EXCEPT:
#if defined(WIN32)
		if ( save_except_fds->fd_count >= fd_select_size() ) {
			EXCEPT( "Selector::add_fd(): except fd_set is full" );
		}
#endif
		FD_SET( fd, save_except_fds );
		break;

	}
}

void
Selector::delete_fd( int fd, IO_FUNC interest )
{
#if !defined(WIN32)
	if ( fd < 0 || fd >= fd_select_size() ) {
		EXCEPT( "Selector::delete_fd(): fd %d outside valid range 0-%d",
				fd, _fd_select_size-1 );
	}
#endif

	switch( interest ) {

	  case IO_READ:
		FD_CLR( fd, save_read_fds );
		break;

	  case IO_WRITE:
		FD_CLR( fd, save_write_fds );
		break;

	  case IO_EXCEPT:
		FD_CLR( fd, save_except_fds );
		break;

	}
}

void
Selector::set_timeout( time_t sec, long usec )
{
	timeout_wanted = TRUE;

	timeout.tv_sec = sec;
	timeout.tv_usec = usec;
}

void
Selector::set_timeout( timeval tv )
{
	timeout_wanted = TRUE;

	timeout = tv;
}

void
Selector::unset_timeout()
{
	timeout_wanted = FALSE;
}

void
Selector::execute()
{
	int		nfds;
	struct timeval	*tp;

	memcpy( read_fds, save_read_fds, fd_set_size * sizeof(fd_set) );
	memcpy( write_fds, save_write_fds, fd_set_size * sizeof(fd_set) );
	memcpy( except_fds, save_except_fds, fd_set_size * sizeof(fd_set) );

	if( timeout_wanted ) {
		tp = &timeout;
	} else {
		tp = NULL;
	}

		// select() ignores its first argument on Windows. We still track
		// max_fd for the display() functions.
	nfds = select( max_fd + 1,
				  (SELECT_FDSET_PTR) read_fds,
				  (SELECT_FDSET_PTR) write_fds,
				  (SELECT_FDSET_PTR) except_fds,
				  tp );
	_select_retval = nfds;

	if( nfds < 0 ) {
#if !defined(WIN32)
		if( errno == EINTR ) {
			state = SIGNALLED;
			return;
		}
#endif
		state = FAILED;
		return;
	}

	if( nfds == 0 ) {
		state = TIMED_OUT;
	} else {
		state = FDS_READY;
	}
	return;
}

int
Selector::select_retval()
{
	return _select_retval;
}

BOOLEAN
Selector::fd_ready( int fd, IO_FUNC interest )
{
	if( state != FDS_READY && state != TIMED_OUT ) {
		EXCEPT(
			"Selector::fd_ready() called, but selector not in FDS_READY state"
		);
	}

#if !defined(WIN32)
	// on UNIX, make sure the value of fd makes sense
	//
	if ( fd < 0 || fd >= fd_select_size() ) {
		return FALSE;
	}
#endif

	switch( interest ) {

	  case IO_READ:
		return FD_ISSET( fd, read_fds );
		break;

	  case IO_WRITE:
		return FD_ISSET( fd, write_fds );
		break;

	  case IO_EXCEPT:
		return FD_ISSET( fd, except_fds );
		break;

	}

		// Can never get here
	return FALSE;
}

BOOLEAN
Selector::timed_out()
{
	return state == TIMED_OUT;
}

BOOLEAN
Selector::signalled()
{
	return state == SIGNALLED;
}

BOOLEAN
Selector::failed()
{
	return state == FAILED;
}

BOOLEAN
Selector::has_ready()
{
	return state == FDS_READY;
}

void
Selector::display()
{

	switch( state ) {

	  case VIRGIN:
		dprintf( D_ALWAYS, "State = VIRGIN\n" );
		break;

	  case FDS_READY:
		dprintf( D_ALWAYS, "State = FDS_READY\n" );
		break;

	  case TIMED_OUT:
		dprintf( D_ALWAYS, "State = TIMED_OUT\n" );
		break;

	  case SIGNALLED:
		dprintf( D_ALWAYS, "State = SIGNALLED\n" );
		break;

	  case FAILED:
		dprintf( D_ALWAYS, "State = FAILED\n" );
		break;
	}

	dprintf( D_ALWAYS, "max_fd = %d\n", max_fd );

	dprintf( D_ALWAYS, "Selection FD's\n" );
	display_fd_set( "\tRead", save_read_fds, max_fd );
	display_fd_set( "\tWrite", save_write_fds, max_fd );
	display_fd_set( "\tExcept", save_except_fds, max_fd );

	if( state == FDS_READY ) {
		dprintf( D_ALWAYS, "Ready FD's\n" );
		display_fd_set( "\tRead", read_fds, max_fd );
		display_fd_set( "\tWrite", write_fds, max_fd );
		display_fd_set( "\tExcept", except_fds, max_fd );
	}
	if( timeout_wanted ) {
		dprintf( D_ALWAYS,
			"Timeout = %ld.%06ld seconds\n", (long) timeout.tv_sec,
			(long) timeout.tv_usec
		);
	} else {
		dprintf( D_ALWAYS, "Timeout not wanted\n" );
	}

}

void
display_fd_set( char *msg, fd_set *set, int max )
{
	int		i;

	dprintf( D_ALWAYS, "%s {", msg );
	for( i=0; i<=max; i++ ) {
		if( FD_ISSET(i,set) ) {
			dprintf( D_ALWAYS | D_NOHEADER, "%d ", i );
		}
	}
	dprintf( D_ALWAYS | D_NOHEADER, "}\n" );
}
<|endoftext|>


<commit_before>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * 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 "condor_common.h"
#include "condor_classad.h"
#include "condor_version.h"
#include "condor_debug.h"
#include "condor_config.h"
#include "daemon.h"
#include "dc_collector.h"
#include "reli_sock.h"
#include "command_strings.h"
#include "condor_distribution.h"

int handleHistoryDir(ReliSock *);

void
usage( char *cmd )
{
	fprintf(stderr,"Usage: %s [options] <machine-name> <subsystem>[.ext]\n",cmd);
	fprintf(stderr,"Where options are:\n");
	fprintf(stderr,"    -help             Display options\n");
	fprintf(stderr,"    -version          Display Condor version\n");
	fprintf(stderr,"    -pool <hostname>  Use this central manager\n");
	fprintf(stderr,"    -debug            Show extra debugging info\n");
	fprintf(stderr,"To select a particular daemon to talk to (does NOT select log file), use:\n");
	fprintf(stderr,"    -master\n");
	fprintf(stderr,"    -schedd\n");
	fprintf(stderr,"    -startd\n");
	fprintf(stderr,"    -collector\n");
	fprintf(stderr,"    -negotiator\n");
	fprintf(stderr,"    -kbdd\n");
	fprintf(stderr,"    -view_collector\n");
	fprintf(stderr,"The subsystem name plus optional extension specifies the log file.\n");
	fprintf(stderr,"Possible subsystem names (anything with an entry XXX_LOG in remote config file):\n");

	fprintf(stderr,"    MASTER\n");
	fprintf(stderr,"    COLLECTOR\n");
	fprintf(stderr,"    NEGOTIATOR\n");
	fprintf(stderr,"    NEGOTIATOR_MATCH\n");
	fprintf(stderr,"    SCHEDD\n");
	fprintf(stderr,"    SHADOW\n");
	fprintf(stderr,"    STARTD\n");
	fprintf(stderr,"    STARTER\n");
	fprintf(stderr,"    KBDD\n");
	fprintf(stderr,"    HISTORY\n");
	fprintf(stderr,"    STARTD_HISTORY\n");
	fprintf(stderr,"\nExample 1: %s -debug coral STARTD\n",cmd);
	fprintf(stderr,"\nExample 2: %s -debug coral STARTER.slot2\n\n",cmd);
}

void
version()
{
	printf( "%s\n%s\n", CondorVersion(), CondorPlatform() );
}

int main( int argc, char *argv[] )
{
	char *machine_name = 0;
	char *log_name = 0;
	char *pool=0;
	int i;

	daemon_t type = DT_MASTER;

	myDistro->Init( argc, argv );
	config();

	for( i=1; i<argc; i++ ) {
		if(!strcmp(argv[i],"-help")) {
			usage(argv[0]);
			exit(0);
		} else if(!strcmp(argv[i],"-pool")) {
			i++;
			if(!argv[i]) {
				fprintf(stderr,"-pool requires an argument.\n\n");
				usage(argv[0]);
				exit(1);
			}
			pool = argv[i];
		} else if(!strcmp(argv[i],"-version")) {
			version();
			exit(0);
		} else if(!strcmp(argv[i],"-debug")) {
            dprintf_set_tool_debug("TOOL", 0);
		} else if(argv[i][0]=='-') {
			type = stringToDaemonType(&argv[i][1]);
			if( type == DT_NONE || type == DT_DAGMAN) {
				usage(argv[0]);
				exit(1);
			}
		} else if(argv[i][0]!='-') {
			if(!machine_name) {
				machine_name = argv[i];
			} else if(!log_name) {
				log_name = argv[i];
			} else {
				fprintf(stderr,"Extra argument: %s\n\n",argv[i]);
				usage(argv[0]);
				exit(1);
			}
		} else {
			usage(argv[0]);
			exit(1);
		}
	}

	if( !machine_name || !log_name ) {
		usage(argv[0]);
		exit(1);
	}

	Daemon *daemon;
	ReliSock *sock;

	if (pool) {
		DCCollector col( pool );
		if( ! col.addr() ) {
			fprintf( stderr, "Error: %s\n", col.error() );
			exit(1);
		}
		daemon = new Daemon( type, machine_name, col.addr() );
	} else {
		daemon = new Daemon( type, machine_name );
	}

	dprintf(D_FULLDEBUG,"Locating daemon process on %s...\n",machine_name);

	if(!daemon->locate()) {
		fprintf(stderr,"Couldn't locate daemon on %s: %s\n",machine_name,daemon->error());
		exit(1);
	}

	dprintf(D_FULLDEBUG,"Daemon %s is %s\n",daemon->hostname(),daemon->addr());

	sock = (ReliSock*)daemon->startCommand( DC_FETCH_LOG, Sock::reli_sock, 1200);

	if(!sock) {
		fprintf(stderr,"couldn't connect to daemon %s at %s\n",daemon->hostname(),daemon->addr());
		return 1;
	}

	int commandType = DC_FETCH_LOG_TYPE_PLAIN;
	if ((strcmp(log_name, "HISTORY") == 0) || (strcmp(log_name, "STARTD_HISTORY") == 0)) {
		commandType = DC_FETCH_LOG_TYPE_HISTORY;
	}

	if ((strcmp(log_name, "STARTD.PER_JOB_HISTORY_DIR") == 0) || (strcmp(log_name, "STARTD.PER_JOB_HISTORY_DIR") == 0)) {
		commandType = DC_FETCH_LOG_TYPE_HISTORY_DIR;
	}

	sock->put( commandType );
	sock->put( log_name );
	sock->end_of_message();

	if (commandType == DC_FETCH_LOG_TYPE_HISTORY_DIR) {
		return handleHistoryDir(sock);
	}

	int result = -1;
	int exitcode = 1;
	const char *reason=NULL;
	filesize_t filesize;

	sock->decode();
	sock->code(result);

	switch(result) {
		case -1:
			reason = "permission denied";
			break;
		case DC_FETCH_LOG_RESULT_SUCCESS:
			result = sock->get_file(&filesize,1,0);
			if(result>=0) {
				exitcode = 0;
			} else {
				reason = "connection lost";
			}
			while (!sock->get_file(&filesize, 1, 0)) ;
			break;
		case DC_FETCH_LOG_RESULT_NO_NAME:
			reason = "no log file by that name";
			break;
		case DC_FETCH_LOG_RESULT_CANT_OPEN:
			reason = "server was unable to access it";
			break;
		case DC_FETCH_LOG_RESULT_BAD_TYPE:
			reason = "server can't provide that type of log";
			break;
		default:
			reason = "unknown error";
			break;
	}

	if(exitcode!=0) {
		fprintf(stderr,"Couldn't fetch log: %s.\n",reason);
	}

	return exitcode;
}

int handleHistoryDir(ReliSock *sock) {
	int  result = -1;
	filesize_t filesize;
	char *filename = 0;

	sock->decode();

	sock->code(result);
	while (result == 1) {
			int fd = -1;
			filename = NULL;
			sock->code(filename);
			fd = safe_open_wrapper_follow(filename, O_CREAT | O_WRONLY);
			if (fd < 0) {
				printf("Can't open local file %s for writing\n", filename);
				exit(1);
			}
			result = sock->get_file(&filesize,fd,0);
			close(fd);

			sock->code(result);
			free(filename);
	}
	return 0;
}
<commit_msg>Check return code from sock->code() #6345<commit_after>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * 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 "condor_common.h"
#include "condor_classad.h"
#include "condor_version.h"
#include "condor_debug.h"
#include "condor_config.h"
#include "daemon.h"
#include "dc_collector.h"
#include "reli_sock.h"
#include "command_strings.h"
#include "condor_distribution.h"

int handleHistoryDir(ReliSock *);

void
usage( char *cmd )
{
	fprintf(stderr,"Usage: %s [options] <machine-name> <subsystem>[.ext]\n",cmd);
	fprintf(stderr,"Where options are:\n");
	fprintf(stderr,"    -help             Display options\n");
	fprintf(stderr,"    -version          Display Condor version\n");
	fprintf(stderr,"    -pool <hostname>  Use this central manager\n");
	fprintf(stderr,"    -debug            Show extra debugging info\n");
	fprintf(stderr,"To select a particular daemon to talk to (does NOT select log file), use:\n");
	fprintf(stderr,"    -master\n");
	fprintf(stderr,"    -schedd\n");
	fprintf(stderr,"    -startd\n");
	fprintf(stderr,"    -collector\n");
	fprintf(stderr,"    -negotiator\n");
	fprintf(stderr,"    -kbdd\n");
	fprintf(stderr,"    -view_collector\n");
	fprintf(stderr,"The subsystem name plus optional extension specifies the log file.\n");
	fprintf(stderr,"Possible subsystem names (anything with an entry XXX_LOG in remote config file):\n");

	fprintf(stderr,"    MASTER\n");
	fprintf(stderr,"    COLLECTOR\n");
	fprintf(stderr,"    NEGOTIATOR\n");
	fprintf(stderr,"    NEGOTIATOR_MATCH\n");
	fprintf(stderr,"    SCHEDD\n");
	fprintf(stderr,"    SHADOW\n");
	fprintf(stderr,"    STARTD\n");
	fprintf(stderr,"    STARTER\n");
	fprintf(stderr,"    KBDD\n");
	fprintf(stderr,"    HISTORY\n");
	fprintf(stderr,"    STARTD_HISTORY\n");
	fprintf(stderr,"\nExample 1: %s -debug coral STARTD\n",cmd);
	fprintf(stderr,"\nExample 2: %s -debug coral STARTER.slot2\n\n",cmd);
}

void
version()
{
	printf( "%s\n%s\n", CondorVersion(), CondorPlatform() );
}

int main( int argc, char *argv[] )
{
	char *machine_name = 0;
	char *log_name = 0;
	char *pool=0;
	int i;

	daemon_t type = DT_MASTER;

	myDistro->Init( argc, argv );
	config();

	for( i=1; i<argc; i++ ) {
		if(!strcmp(argv[i],"-help")) {
			usage(argv[0]);
			exit(0);
		} else if(!strcmp(argv[i],"-pool")) {
			i++;
			if(!argv[i]) {
				fprintf(stderr,"-pool requires an argument.\n\n");
				usage(argv[0]);
				exit(1);
			}
			pool = argv[i];
		} else if(!strcmp(argv[i],"-version")) {
			version();
			exit(0);
		} else if(!strcmp(argv[i],"-debug")) {
            dprintf_set_tool_debug("TOOL", 0);
		} else if(argv[i][0]=='-') {
			type = stringToDaemonType(&argv[i][1]);
			if( type == DT_NONE || type == DT_DAGMAN) {
				usage(argv[0]);
				exit(1);
			}
		} else if(argv[i][0]!='-') {
			if(!machine_name) {
				machine_name = argv[i];
			} else if(!log_name) {
				log_name = argv[i];
			} else {
				fprintf(stderr,"Extra argument: %s\n\n",argv[i]);
				usage(argv[0]);
				exit(1);
			}
		} else {
			usage(argv[0]);
			exit(1);
		}
	}

	if( !machine_name || !log_name ) {
		usage(argv[0]);
		exit(1);
	}

	Daemon *daemon;
	ReliSock *sock;

	if (pool) {
		DCCollector col( pool );
		if( ! col.addr() ) {
			fprintf( stderr, "Error: %s\n", col.error() );
			exit(1);
		}
		daemon = new Daemon( type, machine_name, col.addr() );
	} else {
		daemon = new Daemon( type, machine_name );
	}

	dprintf(D_FULLDEBUG,"Locating daemon process on %s...\n",machine_name);

	if(!daemon->locate()) {
		fprintf(stderr,"Couldn't locate daemon on %s: %s\n",machine_name,daemon->error());
		exit(1);
	}

	dprintf(D_FULLDEBUG,"Daemon %s is %s\n",daemon->hostname(),daemon->addr());

	sock = (ReliSock*)daemon->startCommand( DC_FETCH_LOG, Sock::reli_sock, 1200);

	if(!sock) {
		fprintf(stderr,"couldn't connect to daemon %s at %s\n",daemon->hostname(),daemon->addr());
		return 1;
	}

	int commandType = DC_FETCH_LOG_TYPE_PLAIN;
	if ((strcmp(log_name, "HISTORY") == 0) || (strcmp(log_name, "STARTD_HISTORY") == 0)) {
		commandType = DC_FETCH_LOG_TYPE_HISTORY;
	}

	if ((strcmp(log_name, "STARTD.PER_JOB_HISTORY_DIR") == 0) || (strcmp(log_name, "STARTD.PER_JOB_HISTORY_DIR") == 0)) {
		commandType = DC_FETCH_LOG_TYPE_HISTORY_DIR;
	}

	sock->put( commandType );
	sock->put( log_name );
	sock->end_of_message();

	if (commandType == DC_FETCH_LOG_TYPE_HISTORY_DIR) {
		return handleHistoryDir(sock);
	}

	int result = -1;
	int exitcode = 1;
	const char *reason=NULL;
	filesize_t filesize;

	sock->decode();
	if (!sock->code(result)) {
		fprintf(stderr,"Couldn't fetch log: server did not reply\n");
		return -1;
	}

	switch(result) {
		case -1:
			reason = "permission denied";
			break;
		case DC_FETCH_LOG_RESULT_SUCCESS:
			result = sock->get_file(&filesize,1,0);
			if(result>=0) {
				exitcode = 0;
			} else {
				reason = "connection lost";
			}
			while (!sock->get_file(&filesize, 1, 0)) ;
			break;
		case DC_FETCH_LOG_RESULT_NO_NAME:
			reason = "no log file by that name";
			break;
		case DC_FETCH_LOG_RESULT_CANT_OPEN:
			reason = "server was unable to access it";
			break;
		case DC_FETCH_LOG_RESULT_BAD_TYPE:
			reason = "server can't provide that type of log";
			break;
		default:
			reason = "unknown error";
			break;
	}

	if(exitcode!=0) {
		fprintf(stderr,"Couldn't fetch log: %s.\n",reason);
	}

	return exitcode;
}

int handleHistoryDir(ReliSock *sock) {
	int  result = -1;
	filesize_t filesize;
	char *filename = 0;

	sock->decode();

	if (!sock->code(result)) {
		printf("Can't connect to server\n");
		exit(1);
	}
	while (result == 1) {
			int fd = -1;
			filename = NULL;
			if (!sock->code(filename)) {
				printf("Can't get filename from server\n");
				exit(1);
			}
			fd = safe_open_wrapper_follow(filename, O_CREAT | O_WRONLY);
			if (fd < 0) {
				printf("Can't open local file %s for writing\n", filename);
				exit(1);
			}
			result = sock->get_file(&filesize,fd,0);
			close(fd);

			if (!sock->code(result)) {
				printf("Cannot get result status from server\n");
				result = -1;
			}
			free(filename);
	}
	return 0;
}
<|endoftext|>