<commit_before>/*
* this file is part of the oxygen gtk engine
* Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
*
* This  library is free  software; you can  redistribute it and/or
* modify it  under  the terms  of the  GNU Lesser  General  Public
* License  as published  by the Free  Software  Foundation; either
* version 2 of the License, or( at your option ) any later version.
*
* This 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., 51  Franklin St, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/

#include "oxygengtkcellinfo.h"
#include "oxygengeometry.h"

#include <iostream>
#include <cassert>

namespace Oxygen
{

    //____________________________________________________________________________
    Gtk::CellInfo::CellInfo( GtkTreeView* treeView, int x, int y, int w, int h ):
        _path(0L),
        _column(0L)
    {

        /*
        four attempts are made to get the path from any corner of the rectangle passed in arguments.
        This is necessary to handle half-hidden cells
        */
        gtk_tree_view_get_path_at_pos( treeView, (gint)x+1, (gint)y+1, &_path, &_column, 0L, 0L );

        if( !_path ) gtk_tree_view_get_path_at_pos( treeView, (gint)x+1, (gint)y+h-1, &_path, &_column, 0L, 0L );
        else return;

        if( !_path ) gtk_tree_view_get_path_at_pos( treeView, (gint)x+w-1, (gint)y+1, &_path, &_column, 0L, 0L );
        else return;

        if( !_path ) gtk_tree_view_get_path_at_pos( treeView, (gint)x+w-1, (gint)y+h-1, &_path, &_column, 0L, 0L );
        else return;

    }

    //____________________________________________________________________________
    bool Gtk::CellInfo::isLastVisibleColumn( GtkTreeView* treeView ) const
    {
        bool isLast( false );
        GList* columns( gtk_tree_view_get_columns( treeView ) );
        for( GList *child = g_list_last( columns ); child; child = g_list_previous( child ) )
        {
            if( !GTK_IS_TREE_VIEW_COLUMN( child->data ) ) continue;
            GtkTreeViewColumn* column( GTK_TREE_VIEW_COLUMN( child->data ) );
            if( gtk_tree_view_column_get_visible( column ) )
            {
                isLast = (_column == column );
                break;
            }

        }

        if( columns ) g_list_free( columns );
        return isLast;
    }

    //____________________________________________________________________________
    bool Gtk::CellInfo::isLeftOfExpanderColumn( GtkTreeView* treeView ) const
    {
        // check expander column
        GtkTreeViewColumn* expanderColumn( gtk_tree_view_get_expander_column( treeView ) );
        if( !expanderColumn || _column == expanderColumn ) return false;

        bool found( false );
        bool isLeft( false );

        // get all columns
        GList* columns( gtk_tree_view_get_columns( treeView ) );
        for( GList *child = g_list_first( columns ); child; child = g_list_next( child ) )
        {
            if( !GTK_IS_TREE_VIEW_COLUMN( child->data ) ) continue;
            GtkTreeViewColumn* column( GTK_TREE_VIEW_COLUMN( child->data ) );
            if( column == expanderColumn )
            {
                if( found )
                {

                    isLeft = true;
                    break;

                } else break;

            } else if( found ) break;
            else if( column == _column ) found = true;

        }

        if( columns ) g_list_free( columns );
        return isLeft;

    }

    //____________________________________________________________________________
    bool Gtk::CellInfo::hasParent( GtkTreeView* treeView ) const
    {
        // check treeview and path
        if( !( treeView && _path ) ) return false;

        // get model
        GtkTreeModel* model( gtk_tree_view_get_model( treeView ) );
        if( !model ) return false;

        // get iterator
        GtkTreeIter iter;
        if( !gtk_tree_model_get_iter( model, &iter, _path ) ) return false;

        GtkTreeIter parent;
        return gtk_tree_model_iter_parent( model, &parent, &iter );

    }

    //____________________________________________________________________________
    Gtk::CellInfo Gtk::CellInfo::parent( void ) const
    {
        CellInfo out;
        out._column = _column;

        // check path
        if( !_path ) return out;

        GtkTreePath* parent( gtk_tree_path_copy( _path ) );
        if( gtk_tree_path_up( parent ) ) out._path = parent;
        else gtk_tree_path_free( parent );

        return out;

    }

    //____________________________________________________________________________
    bool Gtk::CellInfo::hasChildren( GtkTreeView* treeView ) const
    {
        // check treeview and path
        if( !( treeView && _path ) ) return false;

        // get model
        GtkTreeModel* model( gtk_tree_view_get_model( treeView ) );
        if( !model ) return false;

        // get iterator
        GtkTreeIter iter;
        if( !gtk_tree_model_get_iter( model, &iter, _path ) ) return false;
        return gtk_tree_model_iter_has_child( model, &iter );

    }

    //____________________________________________________________________________
    bool Gtk::CellInfo::isLast( GtkTreeView* treeView ) const
    {
       // check treeview and path
        if( !( treeView && _path ) ) return false;

        // get model
        GtkTreeModel* model( gtk_tree_view_get_model( treeView ) );
        if( !model ) return false;

        // get iterator
        GtkTreeIter iter;
        if( !gtk_tree_model_get_iter( model, &iter, _path ) ) return false;
        return !gtk_tree_model_iter_next( model, &iter );
    }

    //____________________________________________________________________________
    GdkRectangle Gtk::CellInfo::backgroundRect( GtkTreeView* treeView ) const
    {
        GdkRectangle out = {0, 0, -1, -1 };
        if( treeView && isValid() )
        { gtk_tree_view_get_background_area( treeView, _path, _column, &out ); }

        return out;

    }

    //____________________________________________________________________________
    Gtk::CellInfoFlags::CellInfoFlags( GtkTreeView* treeView, const CellInfo& cellInfo ):
        _depth( cellInfo.depth() ),
        _expanderSize(0),
        _levelIndent(gtk_tree_view_get_level_indentation(treeView))
    {
        if( cellInfo.hasParent( treeView ) ) _flags |= HasParent;
        if( cellInfo.hasChildren( treeView ) ) _flags |= HasChildren;
        if( cellInfo.isLast( treeView ) ) _flags |= IsLast;

        gtk_widget_style_get( GTK_WIDGET( treeView ), "expander-size", &_expanderSize, NULL );

        /*
        for every parent of the current cell, one needs to know whether or not
        it is the last one at its level, to render the tree lines properly
        */
        _isLast = std::vector<bool>(_depth, false);

        unsigned int index( _depth-1 );
        for( CellInfo parent = cellInfo; parent.isValid() && parent.depth() > 0; parent = parent.parent() )
        {
            assert( index >= 0 );
            _isLast[index] = parent.isLast( treeView );
            --index;
        }

    }

}
<commit_msg>use Gtk::gdk_rectangle() to initialize empty rect.<commit_after>/*
* this file is part of the oxygen gtk engine
* Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
*
* This  library is free  software; you can  redistribute it and/or
* modify it  under  the terms  of the  GNU Lesser  General  Public
* License  as published  by the Free  Software  Foundation; either
* version 2 of the License, or( at your option ) any later version.
*
* This 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., 51  Franklin St, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/

#include "oxygengtkcellinfo.h"
#include "oxygengeometry.h"
#include "oxygengtkutils.h"

#include <iostream>
#include <cassert>

namespace Oxygen
{

    //____________________________________________________________________________
    Gtk::CellInfo::CellInfo( GtkTreeView* treeView, int x, int y, int w, int h ):
        _path(0L),
        _column(0L)
    {

        /*
        four attempts are made to get the path from any corner of the rectangle passed in arguments.
        This is necessary to handle half-hidden cells
        */
        gtk_tree_view_get_path_at_pos( treeView, (gint)x+1, (gint)y+1, &_path, &_column, 0L, 0L );

        if( !_path ) gtk_tree_view_get_path_at_pos( treeView, (gint)x+1, (gint)y+h-1, &_path, &_column, 0L, 0L );
        else return;

        if( !_path ) gtk_tree_view_get_path_at_pos( treeView, (gint)x+w-1, (gint)y+1, &_path, &_column, 0L, 0L );
        else return;

        if( !_path ) gtk_tree_view_get_path_at_pos( treeView, (gint)x+w-1, (gint)y+h-1, &_path, &_column, 0L, 0L );
        else return;

    }

    //____________________________________________________________________________
    bool Gtk::CellInfo::isLastVisibleColumn( GtkTreeView* treeView ) const
    {
        bool isLast( false );
        GList* columns( gtk_tree_view_get_columns( treeView ) );
        for( GList *child = g_list_last( columns ); child; child = g_list_previous( child ) )
        {
            if( !GTK_IS_TREE_VIEW_COLUMN( child->data ) ) continue;
            GtkTreeViewColumn* column( GTK_TREE_VIEW_COLUMN( child->data ) );
            if( gtk_tree_view_column_get_visible( column ) )
            {
                isLast = (_column == column );
                break;
            }

        }

        if( columns ) g_list_free( columns );
        return isLast;
    }

    //____________________________________________________________________________
    bool Gtk::CellInfo::isLeftOfExpanderColumn( GtkTreeView* treeView ) const
    {
        // check expander column
        GtkTreeViewColumn* expanderColumn( gtk_tree_view_get_expander_column( treeView ) );
        if( !expanderColumn || _column == expanderColumn ) return false;

        bool found( false );
        bool isLeft( false );

        // get all columns
        GList* columns( gtk_tree_view_get_columns( treeView ) );
        for( GList *child = g_list_first( columns ); child; child = g_list_next( child ) )
        {
            if( !GTK_IS_TREE_VIEW_COLUMN( child->data ) ) continue;
            GtkTreeViewColumn* column( GTK_TREE_VIEW_COLUMN( child->data ) );
            if( column == expanderColumn )
            {
                if( found )
                {

                    isLeft = true;
                    break;

                } else break;

            } else if( found ) break;
            else if( column == _column ) found = true;

        }

        if( columns ) g_list_free( columns );
        return isLeft;

    }

    //____________________________________________________________________________
    bool Gtk::CellInfo::hasParent( GtkTreeView* treeView ) const
    {
        // check treeview and path
        if( !( treeView && _path ) ) return false;

        // get model
        GtkTreeModel* model( gtk_tree_view_get_model( treeView ) );
        if( !model ) return false;

        // get iterator
        GtkTreeIter iter;
        if( !gtk_tree_model_get_iter( model, &iter, _path ) ) return false;

        GtkTreeIter parent;
        return gtk_tree_model_iter_parent( model, &parent, &iter );

    }

    //____________________________________________________________________________
    Gtk::CellInfo Gtk::CellInfo::parent( void ) const
    {
        CellInfo out;
        out._column = _column;

        // check path
        if( !_path ) return out;

        GtkTreePath* parent( gtk_tree_path_copy( _path ) );
        if( gtk_tree_path_up( parent ) ) out._path = parent;
        else gtk_tree_path_free( parent );

        return out;

    }

    //____________________________________________________________________________
    bool Gtk::CellInfo::hasChildren( GtkTreeView* treeView ) const
    {
        // check treeview and path
        if( !( treeView && _path ) ) return false;

        // get model
        GtkTreeModel* model( gtk_tree_view_get_model( treeView ) );
        if( !model ) return false;

        // get iterator
        GtkTreeIter iter;
        if( !gtk_tree_model_get_iter( model, &iter, _path ) ) return false;
        return gtk_tree_model_iter_has_child( model, &iter );

    }

    //____________________________________________________________________________
    bool Gtk::CellInfo::isLast( GtkTreeView* treeView ) const
    {
       // check treeview and path
        if( !( treeView && _path ) ) return false;

        // get model
        GtkTreeModel* model( gtk_tree_view_get_model( treeView ) );
        if( !model ) return false;

        // get iterator
        GtkTreeIter iter;
        if( !gtk_tree_model_get_iter( model, &iter, _path ) ) return false;
        return !gtk_tree_model_iter_next( model, &iter );
    }

    //____________________________________________________________________________
    GdkRectangle Gtk::CellInfo::backgroundRect( GtkTreeView* treeView ) const
    {
        GdkRectangle out( Gtk::gdk_rectangle() );
        if( treeView && isValid() )
        { gtk_tree_view_get_background_area( treeView, _path, _column, &out ); }

        return out;

    }

    //____________________________________________________________________________
    Gtk::CellInfoFlags::CellInfoFlags( GtkTreeView* treeView, const CellInfo& cellInfo ):
        _depth( cellInfo.depth() ),
        _expanderSize(0),
        _levelIndent(gtk_tree_view_get_level_indentation(treeView))
    {
        if( cellInfo.hasParent( treeView ) ) _flags |= HasParent;
        if( cellInfo.hasChildren( treeView ) ) _flags |= HasChildren;
        if( cellInfo.isLast( treeView ) ) _flags |= IsLast;

        gtk_widget_style_get( GTK_WIDGET( treeView ), "expander-size", &_expanderSize, NULL );

        /*
        for every parent of the current cell, one needs to know whether or not
        it is the last one at its level, to render the tree lines properly
        */
        _isLast = std::vector<bool>(_depth, false);

        unsigned int index( _depth-1 );
        for( CellInfo parent = cellInfo; parent.isValid() && parent.depth() > 0; parent = parent.parent() )
        {
            assert( index >= 0 );
            _isLast[index] = parent.isLast( treeView );
            --index;
        }

    }

}
<|endoftext|>


<commit_before>/*
 * global_sync.hpp
 *
 *  Copyright (c) 2015 Masatoshi Hanai
 *
 *  This software is released under MIT License.
 *  See LICENSE.
 *
 */
#ifndef SCALESIM_COM_MPI_GLOBAL_SYNC_HPP_
#define SCALESIM_COM_MPI_GLOBAL_SYNC_HPP_

#include <boost/thread/lock_guard.hpp>
#include <boost/thread/mutex.hpp>
#include <glog/logging.h>

namespace scalesim {

template<class App>
class mpi_gsync {
 private:
  mpi_gsync(const mpi_gsync&);
  void operator=(const mpi_gsync&);

  mpi_gsync(): send_counter_(0),
               rec_counter_(0),
               is_red_(false),
               processing_ev_interval_(0),
               local_min_(timestamp::null()),
               gvt_(timestamp::zero()),
               gvt_counter_(counter::instance("GVT")) {};

 private:
  int send_counter_;
  int rec_counter_;
  bool is_red_;
  int processing_ev_interval_;
  timestamp local_min_; boost::mutex mutex_;
  timestamp gvt_;
  counter* gvt_counter_;
  const boost::mpi::communicator* comm_world_;

 public:
  virtual ~mpi_gsync() {};
  static mpi_gsync* instance() {
    static mpi_gsync* instance_;
    if (!instance_) { instance_ = new mpi_gsync; }
    return instance_;
  };

  static void del_instance() {
    mpi_gsync* instance_ = mpi_gsync::instance();
    if (instance_) { delete instance_; instance_ = 0; }
  };

  void init(const boost::mpi::communicator* comm_world) {
    comm_world_ = comm_world;
  };
  void update_local(const timestamp& local_min_);
  void increment_interval();
  timestamp get_gvt();
  void check_sync();
  void increment_transit_conut() { ++send_counter_; };
  void decrement_transit_conut() { ++rec_counter_; };
  void reset_counter() {
    send_counter_ = 0;
    rec_counter_ = 0;
  };

  bool is_red() const { return is_red_; };
 private:
  int reduce_white_transit_num();
};

template<class App>
void mpi_gsync<App>::update_local(const timestamp& local_min) {
  boost::lock_guard<boost::mutex> guard(mutex_);
  if (local_min_ == timestamp::null()) {
    local_min_ = local_min;
  } else {
    local_min_ = std::min(local_min_, local_min);
  }
};

template<class App>
void mpi_gsync<App>::increment_interval() {
  ++processing_ev_interval_;
};

template<class App>
timestamp mpi_gsync<App>::get_gvt() {
  return gvt_;
};

template<class App>
void mpi_gsync<App>::check_sync() {
  if (gvt_.time() >= App::finish_time()) { return; }

  /* local_min_ has not updated after last gvt computing */
  if (local_min_ == timestamp::null()) { return; }

  /*
   * Interval between second cut and next first cut
   * The global_interval is a interval size between global virtual time.
   * Too small value causes wrong results because of events in send buffer.
   */
  if (processing_ev_interval_ < App::global_cut_interval()) { return; }

  /* make first cut (change RED from WHITE) */
  if (!is_red_) {
    is_red_ = true;
    return;
  }

  /* make second cut */
  if (is_red_) {
    boost::lock_guard<boost::mutex> guard(mutex_);
    stopwatch::instance("GlobalSync")->start();

    /* checking WHITE transit messages for making second cut */
    long transit_msg_num = reduce_white_transit_num();
    if (transit_msg_num == 0) {
      /* make second cut */
      is_red_ = false;
      processing_ev_interval_ = 0;

      /* compute GVT */
      timestamp new_gvt_
          = boost::mpi::all_reduce(*comm_world_, local_min_,
              boost::mpi::minimum<timestamp>());

      DLOG_ASSERT(new_gvt_.time() >= gvt_.time())
          << "new_global_virtual_time_: " << new_gvt_.time()
          << " global_virtual_time_: " << gvt_.time()
          << " Global virtual time fail. Check GSYNC_INTERVAL. "
             "Too small value causes wrong gvt because of send buffer.";

      gvt_ = new_gvt_;
      ++(*gvt_counter_);

      /* reset local_min_ */
      local_min_ = timestamp::null();
    }
    DLOG_ASSERT(transit_msg_num >= 0)
        << "transit message: " << transit_msg_num
        << ". Transit messages must be more than 0 !!! Check GSYNC_INTERVAL";

    stopwatch::instance("GlobalSync")->stop();
  }
};

template<class App>
int mpi_gsync<App>::reduce_white_transit_num() {
  int ret = send_counter_ - rec_counter_;
  ret = boost::mpi::all_reduce(*comm_world_, ret, std::plus<int>());
  return ret;
}

} /* namespace scalesim */

#endif /* SCALESIM_COM_MPI_GLOBAL_SYNC_HPP_ */
<commit_msg>Comment out bug TODO solve<commit_after>/*
 * global_sync.hpp
 *
 *  Copyright (c) 2015 Masatoshi Hanai
 *
 *  This software is released under MIT License.
 *  See LICENSE.
 *
 */
#ifndef SCALESIM_COM_MPI_GLOBAL_SYNC_HPP_
#define SCALESIM_COM_MPI_GLOBAL_SYNC_HPP_

#include <boost/thread/lock_guard.hpp>
#include <boost/thread/mutex.hpp>
#include <glog/logging.h>

namespace scalesim {

template<class App>
class mpi_gsync {
 private:
  mpi_gsync(const mpi_gsync&);
  void operator=(const mpi_gsync&);

  mpi_gsync(): send_counter_(0),
               rec_counter_(0),
               is_red_(false),
               processing_ev_interval_(0),
               local_min_(timestamp::null()),
               gvt_(timestamp::zero()),
               gvt_counter_(counter::instance("GVT")) {};

 private:
  int send_counter_;
  int rec_counter_;
  bool is_red_;
  int processing_ev_interval_;
  timestamp local_min_; boost::mutex mutex_;
  timestamp gvt_;
  counter* gvt_counter_;
  const boost::mpi::communicator* comm_world_;

 public:
  virtual ~mpi_gsync() {};
  static mpi_gsync* instance() {
    static mpi_gsync* instance_;
    if (!instance_) { instance_ = new mpi_gsync; }
    return instance_;
  };

  static void del_instance() {
    mpi_gsync* instance_ = mpi_gsync::instance();
    if (instance_) { delete instance_; instance_ = 0; }
  };

  void init(const boost::mpi::communicator* comm_world) {
    comm_world_ = comm_world;
  };
  void update_local(const timestamp& local_min_);
  void increment_interval();
  timestamp get_gvt();
  void check_sync();
  void increment_transit_conut() { ++send_counter_; };
  void decrement_transit_conut() { ++rec_counter_; };
  void reset_counter() {
    send_counter_ = 0;
    rec_counter_ = 0;
  };

  bool is_red() const { return is_red_; };
 private:
  int reduce_white_transit_num();
};

template<class App>
void mpi_gsync<App>::update_local(const timestamp& local_min) {
  boost::lock_guard<boost::mutex> guard(mutex_);
  if (local_min_ == timestamp::null()) {
    local_min_ = local_min;
  } else {
    local_min_ = std::min(local_min_, local_min);
  }
};

template<class App>
void mpi_gsync<App>::increment_interval() {
  ++processing_ev_interval_;
};

template<class App>
timestamp mpi_gsync<App>::get_gvt() {
  return gvt_;
};

template<class App>
void mpi_gsync<App>::check_sync() {
  if (gvt_.time() >= App::finish_time()) { return; }

  /* local_min_ has not updated after last gvt computing */
  if (local_min_ == timestamp::null()) { return; }

  /*
   * Interval between second cut and next first cut
   * The global_interval is a interval size between global virtual time.
   * Too small value causes wrong results because of events in send buffer.
   */
  if (processing_ev_interval_ < App::global_cut_interval()) { return; }

  /* make first cut (change RED from WHITE) */
  if (!is_red_) {
    is_red_ = true;
    return;
  }

  /* make second cut */
  if (is_red_) {
    boost::lock_guard<boost::mutex> guard(mutex_);
    //stopwatch::instance("GlobalSync")->start();

    /* checking WHITE transit messages for making second cut */
    long transit_msg_num = reduce_white_transit_num();
    if (transit_msg_num == 0) {
      /* make second cut */
      is_red_ = false;
      processing_ev_interval_ = 0;

      /* compute GVT */
      timestamp new_gvt_
          = boost::mpi::all_reduce(*comm_world_, local_min_,
              boost::mpi::minimum<timestamp>());

      DLOG_ASSERT(new_gvt_.time() >= gvt_.time())
          << "new_global_virtual_time_: " << new_gvt_.time()
          << " global_virtual_time_: " << gvt_.time()
          << " Global virtual time fail. Check GSYNC_INTERVAL. "
             "Too small value causes wrong gvt because of send buffer.";

      gvt_ = new_gvt_;
      ++(*gvt_counter_);

      /* reset local_min_ */
      local_min_ = timestamp::null();
    }
    DLOG_ASSERT(transit_msg_num >= 0)
        << "transit message: " << transit_msg_num
        << ". Transit messages must be more than 0 !!! Check GSYNC_INTERVAL";

    //stopwatch::instance("GlobalSync")->stop();
  }
};

template<class App>
int mpi_gsync<App>::reduce_white_transit_num() {
  int ret = send_counter_ - rec_counter_;
  ret = boost::mpi::all_reduce(*comm_world_, ret, std::plus<int>());
  return ret;
}

} /* namespace scalesim */

#endif /* SCALESIM_COM_MPI_GLOBAL_SYNC_HPP_ */
<|endoftext|>


<commit_before>#include "mesh_editor_plugin.h"

#include "tools/editor/editor_plugin.h"
#include "tools/editor/editor_node.h"
#include "scene/3d/mesh_instance.h"
#include "scene/3d/physics_body.h"
#include "scene/3d/body_shape.h"
#include "scene/gui/spin_box.h"
#include "scene/gui/box_container.h"
#include "scene/3d/mesh_instance.h"
#include "scene/3d/navigation_mesh.h"
#include "spatial_editor_plugin.h"

void MeshInstanceEditor::_node_removed(Node *p_node) {

	if(p_node==node) {
		node=NULL;
		options->hide();
	}

}

void MeshInstanceEditor::edit(MeshInstance *p_mesh) {

	node=p_mesh;

}

void MeshInstanceEditor::_menu_option(int p_option) {

	Ref<Mesh> mesh = node->get_mesh();
	if (mesh.is_null()) {
		err_dialog->set_text("Mesh is empty!");
		err_dialog->popup_centered(Size2(100,50));
		return;
	}

	switch(p_option) {
		case MENU_OPTION_CREATE_STATIC_TRIMESH_BODY: {

			Ref<Shape> shape = mesh->create_trimesh_shape();
			if (shape.is_null())
				return;
			StaticBody *body = memnew( StaticBody );
			CollisionShape *cshape = memnew( CollisionShape );
			cshape->set_shape(shape);
			body->add_child(cshape);
			Node *owner = node==get_tree()->get_edited_scene_root() ? node : node->get_owner();

			UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
			ur->create_action("Create Static Trimesh");
			ur->add_do_method(node,"add_child",body);
			ur->add_do_method(body,"set_owner",owner);
			ur->add_do_method(cshape,"set_owner",owner);
			ur->add_do_reference(body);
			ur->add_undo_method(node,"remove_child",body);
			ur->commit_action();

		} break;
		case MENU_OPTION_CREATE_STATIC_CONVEX_BODY: {

			Ref<Shape> shape = mesh->create_convex_shape();
			if (shape.is_null())
				return;
			StaticBody *body = memnew( StaticBody );
			CollisionShape *cshape = memnew( CollisionShape );
			cshape->set_shape(shape);
			body->add_child(cshape);
			Node *owner = node==get_tree()->get_edited_scene_root() ? node : node->get_owner();

			UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
			ur->create_action("Create Static Trimesh");
			ur->add_do_method(node,"add_child",body);
			ur->add_do_method(body,"set_owner",owner);
			ur->add_do_method(cshape,"set_owner",owner);
			ur->add_do_reference(body);
			ur->add_undo_method(node,"remove_child",body);
			ur->commit_action();

		} break;
		case MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE: {

			if (node==get_tree()->get_edited_scene_root()) {
				err_dialog->set_text("This doesn't work on scene root!");
				err_dialog->popup_centered(Size2(100,50));
				return;
			}
			Ref<Shape> shape = mesh->create_trimesh_shape();
			if (shape.is_null())
				return;
			CollisionShape *cshape = memnew( CollisionShape );
			cshape->set_shape(shape);

			Node *owner =  node->get_owner();

			UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
			ur->create_action("Create Static Trimesh");
			ur->add_do_method(node->get_parent(),"add_child",cshape);
			ur->add_do_method(node->get_parent(),"move_child",cshape,node->get_index()+1);
			ur->add_do_method(cshape,"set_owner",owner);
			ur->add_do_reference(cshape);
			ur->add_undo_method(node->get_parent(),"remove_child",cshape);
			ur->commit_action();

		} break;
		case MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE: {

			if (node==get_tree()->get_edited_scene_root()) {
				err_dialog->set_text("This doesn't work on scene root!");
				err_dialog->popup_centered(Size2(100,50));
				return;
			}
			Ref<Shape> shape = mesh->create_convex_shape();
			if (shape.is_null())
				return;
			CollisionShape *cshape = memnew( CollisionShape );
			cshape->set_shape(shape);

			Node *owner =  node->get_owner();

			UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
			ur->create_action("Create Static Trimesh");
			ur->add_do_method(node->get_parent(),"add_child",cshape);
			ur->add_do_method(node->get_parent(),"move_child",cshape,node->get_index()+1);
			ur->add_do_method(cshape,"set_owner",owner);
			ur->add_do_reference(cshape);
			ur->add_undo_method(node->get_parent(),"remove_child",cshape);
			ur->commit_action();

		} break;
		case MENU_OPTION_CREATE_NAVMESH: {

			Ref<NavigationMesh> nmesh = memnew( NavigationMesh );

			if (nmesh.is_null())
				return;

			nmesh->create_from_mesh(mesh);
			NavigationMeshInstance *nmi = memnew(  NavigationMeshInstance );
			nmi->set_navigation_mesh(nmesh);

			Node *owner = node==get_tree()->get_edited_scene_root() ? node : node->get_owner();

			UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
			ur->create_action("Create Navigation Mesh");

			ur->add_do_method(node,"add_child",nmi);
			ur->add_do_method(nmi,"set_owner",owner);

			ur->add_do_reference(nmi);
			ur->add_undo_method(node,"remove_child",nmi);
			ur->commit_action();
		} break;
		case MENU_OPTION_CREATE_OUTLINE_MESH: {

			outline_dialog->popup_centered(Size2(200,80));
		} break;
	}

}

void MeshInstanceEditor::_create_outline_mesh() {

	Ref<Mesh> mesh = node->get_mesh();
	if (mesh.is_null()) {
		err_dialog->set_text("MeshInstance lacks a Mesh!");
		err_dialog->popup_centered(Size2(100,50));
		return;
	}

	Ref<Mesh> mesho = mesh->create_outline(outline_size->get_val());

	if (mesho.is_null()) {
		err_dialog->set_text("Could not create outline!");
		err_dialog->popup_centered(Size2(100,50));
		return;
	}

	MeshInstance *mi = memnew( MeshInstance );
	mi->set_mesh(mesho);
	Node *owner=node->get_owner();
	if (get_tree()->get_edited_scene_root()==node) {
		owner=node;
	}

	UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();

	ur->create_action("Create Outline");

	ur->add_do_method(node,"add_child",mi);
	ur->add_do_method(mi,"set_owner",owner);

	ur->add_do_reference(mi);
	ur->add_undo_method(node,"remove_child",mi);
	ur->commit_action();
}

void MeshInstanceEditor::_bind_methods() {

	ObjectTypeDB::bind_method("_menu_option",&MeshInstanceEditor::_menu_option);
	ObjectTypeDB::bind_method("_create_outline_mesh",&MeshInstanceEditor::_create_outline_mesh);
}

MeshInstanceEditor::MeshInstanceEditor() {

	options = memnew( MenuButton );
	//add_child(options);
	SpatialEditor::get_singleton()->add_control_to_menu_panel(options);

	options->set_text("Mesh");
	options->get_popup()->add_item("Create Trimesh Static Body",MENU_OPTION_CREATE_STATIC_TRIMESH_BODY);
	options->get_popup()->add_item("Create Convex Static Body",MENU_OPTION_CREATE_STATIC_CONVEX_BODY);
	options->get_popup()->add_separator();
	options->get_popup()->add_item("Create Trimesh Collision Sibling",MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE);
	options->get_popup()->add_item("Create Convex Collision Sibling",MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE);
	options->get_popup()->add_separator();
	options->get_popup()->add_item("Create Navigation Mesh",MENU_OPTION_CREATE_NAVMESH);
	options->get_popup()->add_separator();
	options->get_popup()->add_item("Create Outline Mesh..",MENU_OPTION_CREATE_OUTLINE_MESH);

	options->get_popup()->connect("item_pressed", this,"_menu_option");

	outline_dialog = memnew( ConfirmationDialog );
	outline_dialog->set_title("Outline Size: ");
	outline_size = memnew( SpinBox );
	outline_size->set_min(0.001);
	outline_size->set_max(1024);
	outline_size->set_step(0.001);
	outline_size->set_val(0.05);
	outline_dialog->add_child(outline_size);
	outline_dialog->set_child_rect(outline_size);
	add_child(outline_dialog);
	outline_dialog->connect("confirmed",this,"_create_outline_mesh");

}

void MeshInstanceEditorPlugin::edit(Object *p_object) {

	mesh_editor->edit(p_object->cast_to<MeshInstance>());
}

bool MeshInstanceEditorPlugin::handles(Object *p_object) const {

	return p_object->is_type("MeshInstance");
}

void MeshInstanceEditorPlugin::make_visible(bool p_visible) {

	if (p_visible) {
		mesh_editor->options->show();
	} else {

		mesh_editor->options->hide();
		mesh_editor->edit(NULL);
	}

}

MeshInstanceEditorPlugin::MeshInstanceEditorPlugin(EditorNode *p_node) {

	editor=p_node;
	mesh_editor = memnew( MeshInstanceEditor );
	editor->get_viewport()->add_child(mesh_editor);

	mesh_editor->options->hide();
}

MeshInstanceEditorPlugin::~MeshInstanceEditorPlugin()
{
}

<commit_msg>fix_issue_#1594<commit_after>#include "mesh_editor_plugin.h"

#include "tools/editor/editor_plugin.h"
#include "tools/editor/editor_node.h"
#include "scene/3d/mesh_instance.h"
#include "scene/3d/physics_body.h"
#include "scene/3d/body_shape.h"
#include "scene/gui/spin_box.h"
#include "scene/gui/box_container.h"
#include "scene/3d/mesh_instance.h"
#include "scene/3d/navigation_mesh.h"
#include "spatial_editor_plugin.h"

void MeshInstanceEditor::_node_removed(Node *p_node) {

	if(p_node==node) {
		node=NULL;
		options->hide();
	}

}

void MeshInstanceEditor::edit(MeshInstance *p_mesh) {

	node=p_mesh;

}

void MeshInstanceEditor::_menu_option(int p_option) {

	Ref<Mesh> mesh = node->get_mesh();
	if (mesh.is_null()) {
		return;
	}

	switch(p_option) {
		case MENU_OPTION_CREATE_STATIC_TRIMESH_BODY: {

			Ref<Shape> shape = mesh->create_trimesh_shape();
			if (shape.is_null())
				return;
			StaticBody *body = memnew( StaticBody );
			CollisionShape *cshape = memnew( CollisionShape );
			cshape->set_shape(shape);
			body->add_child(cshape);
			Node *owner = node==get_tree()->get_edited_scene_root() ? node : node->get_owner();

			UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
			ur->create_action("Create Static Trimesh");
			ur->add_do_method(node,"add_child",body);
			ur->add_do_method(body,"set_owner",owner);
			ur->add_do_method(cshape,"set_owner",owner);
			ur->add_do_reference(body);
			ur->add_undo_method(node,"remove_child",body);
			ur->commit_action();

		} break;
		case MENU_OPTION_CREATE_STATIC_CONVEX_BODY: {

			Ref<Shape> shape = mesh->create_convex_shape();
			if (shape.is_null())
				return;
			StaticBody *body = memnew( StaticBody );
			CollisionShape *cshape = memnew( CollisionShape );
			cshape->set_shape(shape);
			body->add_child(cshape);
			Node *owner = node==get_tree()->get_edited_scene_root() ? node : node->get_owner();

			UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
			ur->create_action("Create Static Trimesh");
			ur->add_do_method(node,"add_child",body);
			ur->add_do_method(body,"set_owner",owner);
			ur->add_do_method(cshape,"set_owner",owner);
			ur->add_do_reference(body);
			ur->add_undo_method(node,"remove_child",body);
			ur->commit_action();

		} break;
		case MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE: {

			if (node==get_tree()->get_edited_scene_root()) {
				err_dialog->set_text("This doesn't work on scene root!");
				err_dialog->popup_centered(Size2(100,50));
				return;
			}
			Ref<Shape> shape = mesh->create_trimesh_shape();
			if (shape.is_null())
				return;
			CollisionShape *cshape = memnew( CollisionShape );
			cshape->set_shape(shape);

			Node *owner =  node->get_owner();

			UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
			ur->create_action("Create Static Trimesh");
			ur->add_do_method(node->get_parent(),"add_child",cshape);
			ur->add_do_method(node->get_parent(),"move_child",cshape,node->get_index()+1);
			ur->add_do_method(cshape,"set_owner",owner);
			ur->add_do_reference(cshape);
			ur->add_undo_method(node->get_parent(),"remove_child",cshape);
			ur->commit_action();

		} break;
		case MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE: {

			if (node==get_tree()->get_edited_scene_root()) {
				err_dialog->set_text("This doesn't work on scene root!");
				err_dialog->popup_centered(Size2(100,50));
				return;
			}
			Ref<Shape> shape = mesh->create_convex_shape();
			if (shape.is_null())
				return;
			CollisionShape *cshape = memnew( CollisionShape );
			cshape->set_shape(shape);

			Node *owner =  node->get_owner();

			UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
			ur->create_action("Create Static Trimesh");
			ur->add_do_method(node->get_parent(),"add_child",cshape);
			ur->add_do_method(node->get_parent(),"move_child",cshape,node->get_index()+1);
			ur->add_do_method(cshape,"set_owner",owner);
			ur->add_do_reference(cshape);
			ur->add_undo_method(node->get_parent(),"remove_child",cshape);
			ur->commit_action();

		} break;
		case MENU_OPTION_CREATE_NAVMESH: {

			Ref<NavigationMesh> nmesh = memnew( NavigationMesh );

			if (nmesh.is_null())
				return;

			nmesh->create_from_mesh(mesh);
			NavigationMeshInstance *nmi = memnew(  NavigationMeshInstance );
			nmi->set_navigation_mesh(nmesh);

			Node *owner = node==get_tree()->get_edited_scene_root() ? node : node->get_owner();

			UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
			ur->create_action("Create Navigation Mesh");

			ur->add_do_method(node,"add_child",nmi);
			ur->add_do_method(nmi,"set_owner",owner);

			ur->add_do_reference(nmi);
			ur->add_undo_method(node,"remove_child",nmi);
			ur->commit_action();
		} break;
		case MENU_OPTION_CREATE_OUTLINE_MESH: {

			outline_dialog->popup_centered(Size2(200,80));
		} break;
	}

}

void MeshInstanceEditor::_create_outline_mesh() {

	Ref<Mesh> mesh = node->get_mesh();
	if (mesh.is_null()) {
		err_dialog->set_text("MeshInstance lacks a Mesh!");
		err_dialog->popup_centered(Size2(100,50));
		return;
	}

	Ref<Mesh> mesho = mesh->create_outline(outline_size->get_val());

	if (mesho.is_null()) {
		err_dialog->set_text("Could not create outline!");
		err_dialog->popup_centered(Size2(100,50));
		return;
	}

	MeshInstance *mi = memnew( MeshInstance );
	mi->set_mesh(mesho);
	Node *owner=node->get_owner();
	if (get_tree()->get_edited_scene_root()==node) {
		owner=node;
	}

	UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();

	ur->create_action("Create Outline");

	ur->add_do_method(node,"add_child",mi);
	ur->add_do_method(mi,"set_owner",owner);

	ur->add_do_reference(mi);
	ur->add_undo_method(node,"remove_child",mi);
	ur->commit_action();
}

void MeshInstanceEditor::_bind_methods() {

	ObjectTypeDB::bind_method("_menu_option",&MeshInstanceEditor::_menu_option);
	ObjectTypeDB::bind_method("_create_outline_mesh",&MeshInstanceEditor::_create_outline_mesh);
}

MeshInstanceEditor::MeshInstanceEditor() {

	options = memnew( MenuButton );
	//add_child(options);
	SpatialEditor::get_singleton()->add_control_to_menu_panel(options);

	options->set_text("Mesh");
	options->get_popup()->add_item("Create Trimesh Static Body",MENU_OPTION_CREATE_STATIC_TRIMESH_BODY);
	options->get_popup()->add_item("Create Convex Static Body",MENU_OPTION_CREATE_STATIC_CONVEX_BODY);
	options->get_popup()->add_separator();
	options->get_popup()->add_item("Create Trimesh Collision Sibling",MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE);
	options->get_popup()->add_item("Create Convex Collision Sibling",MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE);
	options->get_popup()->add_separator();
	options->get_popup()->add_item("Create Navigation Mesh",MENU_OPTION_CREATE_NAVMESH);
	options->get_popup()->add_separator();
	options->get_popup()->add_item("Create Outline Mesh..",MENU_OPTION_CREATE_OUTLINE_MESH);

	options->get_popup()->connect("item_pressed", this,"_menu_option");

	outline_dialog = memnew( ConfirmationDialog );
	outline_dialog->set_title("Outline Size: ");
	outline_size = memnew( SpinBox );
	outline_size->set_min(0.001);
	outline_size->set_max(1024);
	outline_size->set_step(0.001);
	outline_size->set_val(0.05);
	outline_dialog->add_child(outline_size);
	outline_dialog->set_child_rect(outline_size);
	add_child(outline_dialog);
	outline_dialog->connect("confirmed",this,"_create_outline_mesh");

}

void MeshInstanceEditorPlugin::edit(Object *p_object) {

	mesh_editor->edit(p_object->cast_to<MeshInstance>());
}

bool MeshInstanceEditorPlugin::handles(Object *p_object) const {

	return p_object->is_type("MeshInstance");
}

void MeshInstanceEditorPlugin::make_visible(bool p_visible) {

	if (p_visible) {
		mesh_editor->options->show();
	} else {

		mesh_editor->options->hide();
		mesh_editor->edit(NULL);
	}

}

MeshInstanceEditorPlugin::MeshInstanceEditorPlugin(EditorNode *p_node) {

	editor=p_node;
	mesh_editor = memnew( MeshInstanceEditor );
	editor->get_viewport()->add_child(mesh_editor);

	mesh_editor->options->hide();
}

MeshInstanceEditorPlugin::~MeshInstanceEditorPlugin()
{
}

<|endoftext|>


<commit_before>// Copyright 2012 Cloudera Inc.
//
// 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 "util/impalad-metrics.h"

#include "util/debug-util.h"

using namespace std;

namespace impala {

// Naming convention: Components should be separated by '.' and words should
// be separated by '-'.
const char* ImpaladMetricKeys::IMPALA_SERVER_START_TIME =
    "impala-server.start-time";
const char* ImpaladMetricKeys::IMPALA_SERVER_VERSION =
    "impala-server.version";
const char* ImpaladMetricKeys::IMPALA_SERVER_READY =
    "impala-server.ready";
const char* ImpaladMetricKeys::IMPALA_SERVER_NUM_QUERIES =
    "impala-server.num-queries";
const char* ImpaladMetricKeys::IMPALA_SERVER_NUM_FRAGMENTS =
    "impala-server.num-fragments";
const char* ImpaladMetricKeys::TOTAL_SCAN_RANGES_PROCESSED =
    "impala-server.scan-ranges.total";
const char* ImpaladMetricKeys::NUM_SCAN_RANGES_MISSING_VOLUME_ID =
    "impala-server.scan-ranges.num-missing-volume-id";
const char* ImpaladMetricKeys::MEM_POOL_TOTAL_BYTES =
    "impala-server.mem-pool.total-bytes";
const char* ImpaladMetricKeys::HASH_TABLE_TOTAL_BYTES =
    "impala-server.hash-table.total-bytes";
const char* ImpaladMetricKeys::IO_MGR_NUM_OPEN_FILES =
    "impala-server.io-mgr.num-open-files";
const char* ImpaladMetricKeys::IO_MGR_NUM_BUFFERS =
    "impala-server.io-mgr.num-buffers";
const char* ImpaladMetricKeys::IO_MGR_TOTAL_BYTES =
    "impala-server.io-mgr.total-bytes";
const char* ImpaladMetricKeys::IO_MGR_NUM_UNUSED_BUFFERS =
    "impala-server.io-mgr.num-unused-buffers";
const char* ImpaladMetricKeys::IO_MGR_BYTES_READ =
    "impala-server.io-mgr.bytes-read";
const char* ImpaladMetricKeys::IO_MGR_LOCAL_BYTES_READ =
    "impala-server.io-mgr.local-bytes-read";
const char* ImpaladMetricKeys::IO_MGR_SHORT_CIRCUIT_BYTES_READ =
    "impala-server.io-mgr.short-circuit-bytes-read";
const char* ImpaladMetricKeys::IO_MGR_CACHED_BYTES_READ =
    "impala-server.io-mgr.cached-bytes-read";
const char* ImpaladMetricKeys::IO_MGR_BYTES_WRITTEN =
    "impala-server.io-mgr.bytes-written";
const char* ImpaladMetricKeys::CATALOG_NUM_DBS =
    "catalog.num-databases";
const char* ImpaladMetricKeys::CATALOG_NUM_TABLES =
    "catalog.num-tables";
const char* ImpaladMetricKeys::CATALOG_READY =
    "catalog.ready";
const char* ImpaladMetricKeys::NUM_FILES_OPEN_FOR_INSERT =
    "impala-server.num-files-open-for-insert";
const char* ImpaladMetricKeys::IMPALA_SERVER_NUM_OPEN_HS2_SESSIONS =
    "impala-server.num-open-hiveserver2-sessions";
const char* ImpaladMetricKeys::IMPALA_SERVER_NUM_OPEN_BEESWAX_SESSIONS =
    "impala-server.num-open-beeswax-sessions";
const char* ImpaladMetricKeys::NUM_SESSIONS_EXPIRED =
    "impala-server.num-sessions-expired";
const char* ImpaladMetricKeys::NUM_QUERIES_EXPIRED =
    "impala-server.num-queries-expired";
const char* ImpaladMetricKeys::NUM_QUERIES_SPILLED =
    "impala-server.num-queries-spilled";
const char* ImpaladMetricKeys::RESULTSET_CACHE_TOTAL_NUM_ROWS =
    "impala-server.resultset-cache.total-num-rows";
const char* ImpaladMetricKeys::RESULTSET_CACHE_TOTAL_BYTES =
    "impala-server.resultset-cache.total-bytes";

// These are created by impala-server during startup.
// =======
// Counters
IntGauge* ImpaladMetrics::HASH_TABLE_TOTAL_BYTES = NULL;
IntCounter* ImpaladMetrics::IMPALA_SERVER_NUM_FRAGMENTS = NULL;
IntCounter* ImpaladMetrics::IMPALA_SERVER_NUM_QUERIES = NULL;
IntCounter* ImpaladMetrics::NUM_QUERIES_EXPIRED = NULL;
IntCounter* ImpaladMetrics::NUM_QUERIES_SPILLED = NULL;
IntCounter* ImpaladMetrics::NUM_RANGES_MISSING_VOLUME_ID = NULL;
IntCounter* ImpaladMetrics::NUM_RANGES_PROCESSED = NULL;
IntCounter* ImpaladMetrics::NUM_SESSIONS_EXPIRED = NULL;

// Gauges
IntGauge* ImpaladMetrics::CATALOG_NUM_DBS = NULL;
IntGauge* ImpaladMetrics::CATALOG_NUM_TABLES = NULL;
IntGauge* ImpaladMetrics::IMPALA_SERVER_NUM_OPEN_BEESWAX_SESSIONS = NULL;
IntGauge* ImpaladMetrics::IMPALA_SERVER_NUM_OPEN_HS2_SESSIONS = NULL;
IntGauge* ImpaladMetrics::IO_MGR_NUM_BUFFERS = NULL;
IntGauge* ImpaladMetrics::IO_MGR_NUM_OPEN_FILES = NULL;
IntGauge* ImpaladMetrics::IO_MGR_NUM_UNUSED_BUFFERS = NULL;
IntGauge* ImpaladMetrics::IO_MGR_TOTAL_BYTES = NULL;
IntGauge* ImpaladMetrics::IO_MGR_BYTES_READ = NULL;
IntGauge* ImpaladMetrics::IO_MGR_LOCAL_BYTES_READ = NULL;
IntGauge* ImpaladMetrics::IO_MGR_SHORT_CIRCUIT_BYTES_READ = NULL;
IntGauge* ImpaladMetrics::IO_MGR_CACHED_BYTES_READ = NULL;
IntGauge* ImpaladMetrics::IO_MGR_BYTES_WRITTEN = NULL;
IntGauge* ImpaladMetrics::MEM_POOL_TOTAL_BYTES = NULL;
IntGauge* ImpaladMetrics::NUM_FILES_OPEN_FOR_INSERT = NULL;
IntGauge* ImpaladMetrics::RESULTSET_CACHE_TOTAL_NUM_ROWS = NULL;
IntGauge* ImpaladMetrics::RESULTSET_CACHE_TOTAL_BYTES = NULL;

// Properties
BooleanProperty* ImpaladMetrics::CATALOG_READY = NULL;
BooleanProperty* ImpaladMetrics::IMPALA_SERVER_READY = NULL;
StringProperty* ImpaladMetrics::IMPALA_SERVER_START_TIME = NULL;
StringProperty* ImpaladMetrics::IMPALA_SERVER_VERSION = NULL;

void ImpaladMetrics::CreateMetrics(MetricGroup* m) {
  // Initialize impalad metrics
  IMPALA_SERVER_START_TIME = m->AddProperty<string>(
      ImpaladMetricKeys::IMPALA_SERVER_START_TIME, "");
  IMPALA_SERVER_VERSION = m->AddProperty<string>(
      ImpaladMetricKeys::IMPALA_SERVER_VERSION, GetVersionString(true));
  IMPALA_SERVER_READY = m->AddProperty<bool>(
      ImpaladMetricKeys::IMPALA_SERVER_READY, false);

  IMPALA_SERVER_NUM_QUERIES = m->AddCounter(
      ImpaladMetricKeys::IMPALA_SERVER_NUM_QUERIES, 0L);
  NUM_QUERIES_EXPIRED = m->AddCounter(
      ImpaladMetricKeys::NUM_QUERIES_EXPIRED, 0L);
  NUM_QUERIES_SPILLED = m->AddCounter(
      ImpaladMetricKeys::NUM_QUERIES_SPILLED, 0L);
  IMPALA_SERVER_NUM_FRAGMENTS = m->AddCounter(
      ImpaladMetricKeys::IMPALA_SERVER_NUM_FRAGMENTS, 0L);
  IMPALA_SERVER_NUM_OPEN_HS2_SESSIONS = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IMPALA_SERVER_NUM_OPEN_HS2_SESSIONS, 0L);
  IMPALA_SERVER_NUM_OPEN_BEESWAX_SESSIONS = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IMPALA_SERVER_NUM_OPEN_BEESWAX_SESSIONS, 0L);
  NUM_SESSIONS_EXPIRED = m->AddCounter(
      ImpaladMetricKeys::NUM_SESSIONS_EXPIRED, 0L);
  RESULTSET_CACHE_TOTAL_NUM_ROWS = m->AddGauge(
      ImpaladMetricKeys::RESULTSET_CACHE_TOTAL_NUM_ROWS, 0L);
  RESULTSET_CACHE_TOTAL_BYTES = m->AddGauge(
      ImpaladMetricKeys::RESULTSET_CACHE_TOTAL_BYTES, 0L);

  // Initialize scan node metrics
  NUM_RANGES_PROCESSED = m->AddCounter(
      ImpaladMetricKeys::TOTAL_SCAN_RANGES_PROCESSED, 0L);
  NUM_RANGES_MISSING_VOLUME_ID = m->AddCounter(
      ImpaladMetricKeys::NUM_SCAN_RANGES_MISSING_VOLUME_ID, 0L);

  // Initialize memory usage metrics
  MEM_POOL_TOTAL_BYTES = m->AddGauge<int64_t>(
      ImpaladMetricKeys::MEM_POOL_TOTAL_BYTES, 0L, TUnit::BYTES);
  HASH_TABLE_TOTAL_BYTES = m->AddGauge(
      ImpaladMetricKeys::HASH_TABLE_TOTAL_BYTES, 0L, TUnit::BYTES);

  // Initialize insert metrics
  NUM_FILES_OPEN_FOR_INSERT = m->AddGauge<int64_t>(
      ImpaladMetricKeys::NUM_FILES_OPEN_FOR_INSERT, 0L);

  // Initialize IO mgr metrics
  IO_MGR_NUM_OPEN_FILES = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IO_MGR_NUM_OPEN_FILES, 0L);
  IO_MGR_NUM_BUFFERS = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IO_MGR_NUM_BUFFERS, 0L);
  IO_MGR_TOTAL_BYTES = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IO_MGR_TOTAL_BYTES, 0L, TUnit::BYTES);
  IO_MGR_NUM_UNUSED_BUFFERS = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IO_MGR_NUM_UNUSED_BUFFERS, 0L);

  IO_MGR_BYTES_READ = m->AddGauge(
      ImpaladMetricKeys::IO_MGR_BYTES_READ, 0L, TUnit::BYTES);
  IO_MGR_LOCAL_BYTES_READ = m->AddGauge(
      ImpaladMetricKeys::IO_MGR_LOCAL_BYTES_READ, 0L, TUnit::BYTES);
  IO_MGR_CACHED_BYTES_READ = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IO_MGR_CACHED_BYTES_READ, 0L, TUnit::BYTES);
  IO_MGR_SHORT_CIRCUIT_BYTES_READ = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IO_MGR_SHORT_CIRCUIT_BYTES_READ, 0L, TUnit::BYTES);
  IO_MGR_BYTES_WRITTEN = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IO_MGR_BYTES_WRITTEN, 0L);

  // Initialize catalog metrics
  CATALOG_NUM_DBS = m->AddGauge<int64_t>(
      ImpaladMetricKeys::CATALOG_NUM_DBS, 0L);
  CATALOG_NUM_TABLES = m->AddGauge<int64_t>(
      ImpaladMetricKeys::CATALOG_NUM_TABLES, 0L);
  CATALOG_READY = m->AddProperty<bool>(
      ImpaladMetricKeys::CATALOG_READY, false);
}

}
<commit_msg>Use BYTES unit for the io-mgr-bytes-written metric.<commit_after>// Copyright 2012 Cloudera Inc.
//
// 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 "util/impalad-metrics.h"

#include "util/debug-util.h"

using namespace std;

namespace impala {

// Naming convention: Components should be separated by '.' and words should
// be separated by '-'.
const char* ImpaladMetricKeys::IMPALA_SERVER_START_TIME =
    "impala-server.start-time";
const char* ImpaladMetricKeys::IMPALA_SERVER_VERSION =
    "impala-server.version";
const char* ImpaladMetricKeys::IMPALA_SERVER_READY =
    "impala-server.ready";
const char* ImpaladMetricKeys::IMPALA_SERVER_NUM_QUERIES =
    "impala-server.num-queries";
const char* ImpaladMetricKeys::IMPALA_SERVER_NUM_FRAGMENTS =
    "impala-server.num-fragments";
const char* ImpaladMetricKeys::TOTAL_SCAN_RANGES_PROCESSED =
    "impala-server.scan-ranges.total";
const char* ImpaladMetricKeys::NUM_SCAN_RANGES_MISSING_VOLUME_ID =
    "impala-server.scan-ranges.num-missing-volume-id";
const char* ImpaladMetricKeys::MEM_POOL_TOTAL_BYTES =
    "impala-server.mem-pool.total-bytes";
const char* ImpaladMetricKeys::HASH_TABLE_TOTAL_BYTES =
    "impala-server.hash-table.total-bytes";
const char* ImpaladMetricKeys::IO_MGR_NUM_OPEN_FILES =
    "impala-server.io-mgr.num-open-files";
const char* ImpaladMetricKeys::IO_MGR_NUM_BUFFERS =
    "impala-server.io-mgr.num-buffers";
const char* ImpaladMetricKeys::IO_MGR_TOTAL_BYTES =
    "impala-server.io-mgr.total-bytes";
const char* ImpaladMetricKeys::IO_MGR_NUM_UNUSED_BUFFERS =
    "impala-server.io-mgr.num-unused-buffers";
const char* ImpaladMetricKeys::IO_MGR_BYTES_READ =
    "impala-server.io-mgr.bytes-read";
const char* ImpaladMetricKeys::IO_MGR_LOCAL_BYTES_READ =
    "impala-server.io-mgr.local-bytes-read";
const char* ImpaladMetricKeys::IO_MGR_SHORT_CIRCUIT_BYTES_READ =
    "impala-server.io-mgr.short-circuit-bytes-read";
const char* ImpaladMetricKeys::IO_MGR_CACHED_BYTES_READ =
    "impala-server.io-mgr.cached-bytes-read";
const char* ImpaladMetricKeys::IO_MGR_BYTES_WRITTEN =
    "impala-server.io-mgr.bytes-written";
const char* ImpaladMetricKeys::CATALOG_NUM_DBS =
    "catalog.num-databases";
const char* ImpaladMetricKeys::CATALOG_NUM_TABLES =
    "catalog.num-tables";
const char* ImpaladMetricKeys::CATALOG_READY =
    "catalog.ready";
const char* ImpaladMetricKeys::NUM_FILES_OPEN_FOR_INSERT =
    "impala-server.num-files-open-for-insert";
const char* ImpaladMetricKeys::IMPALA_SERVER_NUM_OPEN_HS2_SESSIONS =
    "impala-server.num-open-hiveserver2-sessions";
const char* ImpaladMetricKeys::IMPALA_SERVER_NUM_OPEN_BEESWAX_SESSIONS =
    "impala-server.num-open-beeswax-sessions";
const char* ImpaladMetricKeys::NUM_SESSIONS_EXPIRED =
    "impala-server.num-sessions-expired";
const char* ImpaladMetricKeys::NUM_QUERIES_EXPIRED =
    "impala-server.num-queries-expired";
const char* ImpaladMetricKeys::NUM_QUERIES_SPILLED =
    "impala-server.num-queries-spilled";
const char* ImpaladMetricKeys::RESULTSET_CACHE_TOTAL_NUM_ROWS =
    "impala-server.resultset-cache.total-num-rows";
const char* ImpaladMetricKeys::RESULTSET_CACHE_TOTAL_BYTES =
    "impala-server.resultset-cache.total-bytes";

// These are created by impala-server during startup.
// =======
// Counters
IntGauge* ImpaladMetrics::HASH_TABLE_TOTAL_BYTES = NULL;
IntCounter* ImpaladMetrics::IMPALA_SERVER_NUM_FRAGMENTS = NULL;
IntCounter* ImpaladMetrics::IMPALA_SERVER_NUM_QUERIES = NULL;
IntCounter* ImpaladMetrics::NUM_QUERIES_EXPIRED = NULL;
IntCounter* ImpaladMetrics::NUM_QUERIES_SPILLED = NULL;
IntCounter* ImpaladMetrics::NUM_RANGES_MISSING_VOLUME_ID = NULL;
IntCounter* ImpaladMetrics::NUM_RANGES_PROCESSED = NULL;
IntCounter* ImpaladMetrics::NUM_SESSIONS_EXPIRED = NULL;

// Gauges
IntGauge* ImpaladMetrics::CATALOG_NUM_DBS = NULL;
IntGauge* ImpaladMetrics::CATALOG_NUM_TABLES = NULL;
IntGauge* ImpaladMetrics::IMPALA_SERVER_NUM_OPEN_BEESWAX_SESSIONS = NULL;
IntGauge* ImpaladMetrics::IMPALA_SERVER_NUM_OPEN_HS2_SESSIONS = NULL;
IntGauge* ImpaladMetrics::IO_MGR_NUM_BUFFERS = NULL;
IntGauge* ImpaladMetrics::IO_MGR_NUM_OPEN_FILES = NULL;
IntGauge* ImpaladMetrics::IO_MGR_NUM_UNUSED_BUFFERS = NULL;
IntGauge* ImpaladMetrics::IO_MGR_TOTAL_BYTES = NULL;
IntGauge* ImpaladMetrics::IO_MGR_BYTES_READ = NULL;
IntGauge* ImpaladMetrics::IO_MGR_LOCAL_BYTES_READ = NULL;
IntGauge* ImpaladMetrics::IO_MGR_SHORT_CIRCUIT_BYTES_READ = NULL;
IntGauge* ImpaladMetrics::IO_MGR_CACHED_BYTES_READ = NULL;
IntGauge* ImpaladMetrics::IO_MGR_BYTES_WRITTEN = NULL;
IntGauge* ImpaladMetrics::MEM_POOL_TOTAL_BYTES = NULL;
IntGauge* ImpaladMetrics::NUM_FILES_OPEN_FOR_INSERT = NULL;
IntGauge* ImpaladMetrics::RESULTSET_CACHE_TOTAL_NUM_ROWS = NULL;
IntGauge* ImpaladMetrics::RESULTSET_CACHE_TOTAL_BYTES = NULL;

// Properties
BooleanProperty* ImpaladMetrics::CATALOG_READY = NULL;
BooleanProperty* ImpaladMetrics::IMPALA_SERVER_READY = NULL;
StringProperty* ImpaladMetrics::IMPALA_SERVER_START_TIME = NULL;
StringProperty* ImpaladMetrics::IMPALA_SERVER_VERSION = NULL;

void ImpaladMetrics::CreateMetrics(MetricGroup* m) {
  // Initialize impalad metrics
  IMPALA_SERVER_START_TIME = m->AddProperty<string>(
      ImpaladMetricKeys::IMPALA_SERVER_START_TIME, "");
  IMPALA_SERVER_VERSION = m->AddProperty<string>(
      ImpaladMetricKeys::IMPALA_SERVER_VERSION, GetVersionString(true));
  IMPALA_SERVER_READY = m->AddProperty<bool>(
      ImpaladMetricKeys::IMPALA_SERVER_READY, false);

  IMPALA_SERVER_NUM_QUERIES = m->AddCounter(
      ImpaladMetricKeys::IMPALA_SERVER_NUM_QUERIES, 0L);
  NUM_QUERIES_EXPIRED = m->AddCounter(
      ImpaladMetricKeys::NUM_QUERIES_EXPIRED, 0L);
  NUM_QUERIES_SPILLED = m->AddCounter(
      ImpaladMetricKeys::NUM_QUERIES_SPILLED, 0L);
  IMPALA_SERVER_NUM_FRAGMENTS = m->AddCounter(
      ImpaladMetricKeys::IMPALA_SERVER_NUM_FRAGMENTS, 0L);
  IMPALA_SERVER_NUM_OPEN_HS2_SESSIONS = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IMPALA_SERVER_NUM_OPEN_HS2_SESSIONS, 0L);
  IMPALA_SERVER_NUM_OPEN_BEESWAX_SESSIONS = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IMPALA_SERVER_NUM_OPEN_BEESWAX_SESSIONS, 0L);
  NUM_SESSIONS_EXPIRED = m->AddCounter(
      ImpaladMetricKeys::NUM_SESSIONS_EXPIRED, 0L);
  RESULTSET_CACHE_TOTAL_NUM_ROWS = m->AddGauge(
      ImpaladMetricKeys::RESULTSET_CACHE_TOTAL_NUM_ROWS, 0L);
  RESULTSET_CACHE_TOTAL_BYTES = m->AddGauge(
      ImpaladMetricKeys::RESULTSET_CACHE_TOTAL_BYTES, 0L);

  // Initialize scan node metrics
  NUM_RANGES_PROCESSED = m->AddCounter(
      ImpaladMetricKeys::TOTAL_SCAN_RANGES_PROCESSED, 0L);
  NUM_RANGES_MISSING_VOLUME_ID = m->AddCounter(
      ImpaladMetricKeys::NUM_SCAN_RANGES_MISSING_VOLUME_ID, 0L);

  // Initialize memory usage metrics
  MEM_POOL_TOTAL_BYTES = m->AddGauge<int64_t>(
      ImpaladMetricKeys::MEM_POOL_TOTAL_BYTES, 0L, TUnit::BYTES);
  HASH_TABLE_TOTAL_BYTES = m->AddGauge(
      ImpaladMetricKeys::HASH_TABLE_TOTAL_BYTES, 0L, TUnit::BYTES);

  // Initialize insert metrics
  NUM_FILES_OPEN_FOR_INSERT = m->AddGauge<int64_t>(
      ImpaladMetricKeys::NUM_FILES_OPEN_FOR_INSERT, 0L);

  // Initialize IO mgr metrics
  IO_MGR_NUM_OPEN_FILES = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IO_MGR_NUM_OPEN_FILES, 0L);
  IO_MGR_NUM_BUFFERS = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IO_MGR_NUM_BUFFERS, 0L);
  IO_MGR_TOTAL_BYTES = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IO_MGR_TOTAL_BYTES, 0L, TUnit::BYTES);
  IO_MGR_NUM_UNUSED_BUFFERS = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IO_MGR_NUM_UNUSED_BUFFERS, 0L);

  IO_MGR_BYTES_READ = m->AddGauge(
      ImpaladMetricKeys::IO_MGR_BYTES_READ, 0L, TUnit::BYTES);
  IO_MGR_LOCAL_BYTES_READ = m->AddGauge(
      ImpaladMetricKeys::IO_MGR_LOCAL_BYTES_READ, 0L, TUnit::BYTES);
  IO_MGR_CACHED_BYTES_READ = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IO_MGR_CACHED_BYTES_READ, 0L, TUnit::BYTES);
  IO_MGR_SHORT_CIRCUIT_BYTES_READ = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IO_MGR_SHORT_CIRCUIT_BYTES_READ, 0L, TUnit::BYTES);
  IO_MGR_BYTES_WRITTEN = m->AddGauge<int64_t>(
      ImpaladMetricKeys::IO_MGR_BYTES_WRITTEN, 0L, TUnit::BYTES);

  // Initialize catalog metrics
  CATALOG_NUM_DBS = m->AddGauge<int64_t>(
      ImpaladMetricKeys::CATALOG_NUM_DBS, 0L);
  CATALOG_NUM_TABLES = m->AddGauge<int64_t>(
      ImpaladMetricKeys::CATALOG_NUM_TABLES, 0L);
  CATALOG_READY = m->AddProperty<bool>(
      ImpaladMetricKeys::CATALOG_READY, false);
}

}
<|endoftext|>


<commit_before>// Header for TargetAddressSpaces
//
// Copyright (c) 2013 Pekka Jääskeläinen / TUT
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#include "config.h"
#include <iostream>
#include <string>

#ifdef LLVM_3_2
# include <llvm/Instructions.h>
#else
# include <llvm/IR/Instructions.h>
# include <llvm/IR/Module.h>

#endif
#include <llvm/Transforms/Utils/ValueMapper.h>
#include "llvm/Transforms/Utils/Cloning.h"

#include "TargetAddressSpaces.h"
#include "Workgroup.h"
#include "LLVMUtils.h"
#include "pocl.h"

#define DEBUG_TARGET_ADDRESS_SPACES

namespace pocl {

using namespace llvm;

namespace {
  static
  RegisterPass<pocl::TargetAddressSpaces> X
  ("target-address-spaces",
   "Convert the 'fake' address space ids to the target specific ones.");
}

char TargetAddressSpaces::ID = 0;

TargetAddressSpaces::TargetAddressSpaces() : ModulePass(ID) {
}

static Type *
ConvertedType(llvm::Type *type, std::map<unsigned, unsigned> &addrSpaceMap) {

  if (type->isPointerTy()) {
    unsigned AS = type->getPointerAddressSpace();
    unsigned newAS = addrSpaceMap[AS];
    return PointerType::get(ConvertedType(type->getPointerElementType(), addrSpaceMap), newAS);
  } else if (type->isArrayTy()) {
    return ArrayType::get
      (ConvertedType(type->getArrayElementType(), addrSpaceMap), type->getArrayNumElements());
  } else { /* TODO: pointers inside structs */
    return type;
  }
}

static bool
UpdateAddressSpace(llvm::Value& val, std::map<unsigned, unsigned> &addrSpaceMap) {
  Type *type = val.getType();
  if (!type->isPointerTy()) return false;

  Type *newType = ConvertedType(type, addrSpaceMap);
  if (newType == type) return false;

  val.mutateType(newType);
  return true;
}

bool
TargetAddressSpaces::runOnModule(llvm::Module &M) {

  std::string triple = M.getTargetTriple();
  std::string arch = triple;
  size_t dash = triple.find("-");
  if (dash != std::string::npos) {
    arch = triple.substr(0, dash);
  }

  std::map<unsigned, unsigned> addrSpaceMap;

  if (arch == "x86_64") {
    /* For x86_64 the default isel seems to work with the
       fake address spaces. We could skip the processing,
       but let's do it for now to get it some regular testing. */
    //return false;
  } else if (arch == "tce") {
    addrSpaceMap[POCL_ADDRESS_SPACE_GLOBAL] = 3;
    addrSpaceMap[POCL_ADDRESS_SPACE_LOCAL] = 4;
    /* LLVM 3.2 detects 'constant' as cuda_constant (5) in the fake
       address space map. Add it for compatibility. */
    addrSpaceMap[5] = addrSpaceMap[POCL_ADDRESS_SPACE_CONSTANT] = 5;

  } else {
    /* Assume the fake address space map works directly in case not
       overridden here.  */
    return false;
  }

  bool changed = false;
  /* Handle global variables. */
  llvm::Module::global_iterator globalI = M.global_begin();
  llvm::Module::global_iterator globalE = M.global_end();
  for (; globalI != globalE; ++globalI) {
    llvm::Value &global = *globalI;
    changed |= UpdateAddressSpace(global, addrSpaceMap);
  }

  FunctionMapping funcReplacements;
  std::vector<llvm::Function*> unhandledFuncs;

  /* Collect the functions to process first because we add
     a new function per modified function which invalidates
     the Module's function iterator. */
  for (llvm::Module::iterator functionI = M.begin(), functionE = M.end();
       functionI != functionE; ++functionI) {
    if (functionI->empty() || functionI->getName().startswith("_GLOBAL"))
      continue;
    unhandledFuncs.push_back(functionI);
  }

  for (std::vector<llvm::Function*>::iterator i = unhandledFuncs.begin(),
         e = unhandledFuncs.end(); i != e; ++i) {
    llvm::Function &F = **i;

    /* Convert the FunctionType. Because there is no mutator API in
       LLVM for this, we need to recreate the whole darn function :( */
    SmallVector<Type *, 8> parameters;
    for (Function::const_arg_iterator i = F.arg_begin(),
           e = F.arg_end();
         i != e; ++i)
      parameters.push_back(ConvertedType(i->getType(), addrSpaceMap));

    llvm::FunctionType *ft = FunctionType::get
      (ConvertedType(F.getReturnType(), addrSpaceMap),
       parameters, F.isVarArg());

    llvm::Function *newFunc = Function::Create(ft, F.getLinkage(), "", &M);
    newFunc->takeName(&F);

    ValueToValueMapTy vv;
    Function::arg_iterator j = newFunc->arg_begin();
    for (Function::const_arg_iterator i = F.arg_begin(),
           e = F.arg_end();
         i != e; ++i) {
      j->setName(i->getName());
      vv[i] = j;
      ++j;
    }

    SmallVector<ReturnInst *, 1> ri;

    class AddressSpaceReMapper : public ValueMapTypeRemapper {
    public:
      AddressSpaceReMapper(std::map<unsigned, unsigned> &addrSpaceMap) :
        addrSpaceMap_(addrSpaceMap) {}
      Type* remapType(Type *type) {
        Type *newType = ConvertedType(type, addrSpaceMap_);
        if (newType == type) return type;
        return newType;
      }
    private:
      std::map<unsigned, unsigned>& addrSpaceMap_;
    } asvtm(addrSpaceMap);

    CloneFunctionInto(newFunc, &F, vv, true, ri, "", NULL, &asvtm);
    funcReplacements[&F] = newFunc;
  }

  /* Replace all references to the old function to the new one. */
  llvm::Module::iterator fI = M.begin();
  llvm::Module::iterator fE = M.end();
  for (; fI != fE; ++fI) {
    llvm::Function &F = *fI;
    for (llvm::Function::iterator bbi = F.begin(), bbe = F.end(); bbi != bbe;
         ++bbi)
      for (llvm::BasicBlock::iterator ii = bbi->begin(), ie = bbi->end(); ii != ie;
           ++ii) {
        llvm::Instruction *instr = ii;
        if (!isa<CallInst>(instr)) continue;
        llvm::CallInst *call = dyn_cast<CallInst>(instr);
        llvm::Function *calledF = call->getCalledFunction();
        if (funcReplacements.find(calledF) == funcReplacements.end()) continue;

        call->setCalledFunction(funcReplacements[calledF]);
      }
  }

  regenerate_kernel_metadata(M, funcReplacements);

  /* Delete the old functions. */
  for (FunctionMapping::iterator i = funcReplacements.begin(),
         e = funcReplacements.end(); i != e; ++i) {
    i->first->eraseFromParent();
  }

  return true;
}

}
<commit_msg>Skip the address space remapping for x86_64 as it seems to not be working for all cases (the pointers in struct case affects Mikael), and the all-to-zero mapping seems to work in the backend just fine.<commit_after>// Header for TargetAddressSpaces
//
// Copyright (c) 2013 Pekka Jääskeläinen / TUT
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#include "config.h"
#include <iostream>
#include <string>

#ifdef LLVM_3_2
# include <llvm/Instructions.h>
#else
# include <llvm/IR/Instructions.h>
# include <llvm/IR/Module.h>

#endif
#include <llvm/Transforms/Utils/ValueMapper.h>
#include "llvm/Transforms/Utils/Cloning.h"

#include "TargetAddressSpaces.h"
#include "Workgroup.h"
#include "LLVMUtils.h"
#include "pocl.h"

#define DEBUG_TARGET_ADDRESS_SPACES

namespace pocl {

using namespace llvm;

namespace {
  static
  RegisterPass<pocl::TargetAddressSpaces> X
  ("target-address-spaces",
   "Convert the 'fake' address space ids to the target specific ones.");
}

char TargetAddressSpaces::ID = 0;

TargetAddressSpaces::TargetAddressSpaces() : ModulePass(ID) {
}

static Type *
ConvertedType(llvm::Type *type, std::map<unsigned, unsigned> &addrSpaceMap) {

  if (type->isPointerTy()) {
    unsigned AS = type->getPointerAddressSpace();
    unsigned newAS = addrSpaceMap[AS];
    return PointerType::get(ConvertedType(type->getPointerElementType(), addrSpaceMap), newAS);
  } else if (type->isArrayTy()) {
    return ArrayType::get
      (ConvertedType(type->getArrayElementType(), addrSpaceMap), type->getArrayNumElements());
  } else { /* TODO: pointers inside structs */
    return type;
  }
}

static bool
UpdateAddressSpace(llvm::Value& val, std::map<unsigned, unsigned> &addrSpaceMap) {
  Type *type = val.getType();
  if (!type->isPointerTy()) return false;

  Type *newType = ConvertedType(type, addrSpaceMap);
  if (newType == type) return false;

  val.mutateType(newType);
  return true;
}

bool
TargetAddressSpaces::runOnModule(llvm::Module &M) {

  std::string triple = M.getTargetTriple();
  std::string arch = triple;
  size_t dash = triple.find("-");
  if (dash != std::string::npos) {
    arch = triple.substr(0, dash);
  }

  std::map<unsigned, unsigned> addrSpaceMap;

  if (arch == "x86_64") {
    /* For x86_64 the default isel seems to work with the
       fake address spaces. Skip the processing as it causes
       an overhead and is not fully implemented.
    */
    return false;
  } else if (arch == "tce") {
    /* TCE requires the remapping. */
    addrSpaceMap[POCL_ADDRESS_SPACE_GLOBAL] = 3;
    addrSpaceMap[POCL_ADDRESS_SPACE_LOCAL] = 4;
    /* LLVM 3.2 detects 'constant' as cuda_constant (5) in the fake
       address space map. Add it for compatibility. */
    addrSpaceMap[5] = addrSpaceMap[POCL_ADDRESS_SPACE_CONSTANT] = 5;

  } else {
    /* Assume the fake address space map works directly in case not
       overridden here.  */
    return false;
  }

  bool changed = false;
  /* Handle global variables. */
  llvm::Module::global_iterator globalI = M.global_begin();
  llvm::Module::global_iterator globalE = M.global_end();
  for (; globalI != globalE; ++globalI) {
    llvm::Value &global = *globalI;
    changed |= UpdateAddressSpace(global, addrSpaceMap);
  }

  FunctionMapping funcReplacements;
  std::vector<llvm::Function*> unhandledFuncs;

  /* Collect the functions to process first because we add
     a new function per modified function which invalidates
     the Module's function iterator. */
  for (llvm::Module::iterator functionI = M.begin(), functionE = M.end();
       functionI != functionE; ++functionI) {
    if (functionI->empty() || functionI->getName().startswith("_GLOBAL"))
      continue;
    unhandledFuncs.push_back(functionI);
  }

  for (std::vector<llvm::Function*>::iterator i = unhandledFuncs.begin(),
         e = unhandledFuncs.end(); i != e; ++i) {
    llvm::Function &F = **i;

    /* Convert the FunctionType. Because there is no mutator API in
       LLVM for this, we need to recreate the whole darn function :( */
    SmallVector<Type *, 8> parameters;
    for (Function::const_arg_iterator i = F.arg_begin(),
           e = F.arg_end();
         i != e; ++i)
      parameters.push_back(ConvertedType(i->getType(), addrSpaceMap));

    llvm::FunctionType *ft = FunctionType::get
      (ConvertedType(F.getReturnType(), addrSpaceMap),
       parameters, F.isVarArg());

    llvm::Function *newFunc = Function::Create(ft, F.getLinkage(), "", &M);
    newFunc->takeName(&F);

    ValueToValueMapTy vv;
    Function::arg_iterator j = newFunc->arg_begin();
    for (Function::const_arg_iterator i = F.arg_begin(),
           e = F.arg_end();
         i != e; ++i) {
      j->setName(i->getName());
      vv[i] = j;
      ++j;
    }

    SmallVector<ReturnInst *, 1> ri;

    class AddressSpaceReMapper : public ValueMapTypeRemapper {
    public:
      AddressSpaceReMapper(std::map<unsigned, unsigned> &addrSpaceMap) :
        addrSpaceMap_(addrSpaceMap) {}
      Type* remapType(Type *type) {
        Type *newType = ConvertedType(type, addrSpaceMap_);
        if (newType == type) return type;
        return newType;
      }
    private:
      std::map<unsigned, unsigned>& addrSpaceMap_;
    } asvtm(addrSpaceMap);

    CloneFunctionInto(newFunc, &F, vv, true, ri, "", NULL, &asvtm);
    funcReplacements[&F] = newFunc;
  }

  /* Replace all references to the old function to the new one. */
  llvm::Module::iterator fI = M.begin();
  llvm::Module::iterator fE = M.end();
  for (; fI != fE; ++fI) {
    llvm::Function &F = *fI;
    for (llvm::Function::iterator bbi = F.begin(), bbe = F.end(); bbi != bbe;
         ++bbi)
      for (llvm::BasicBlock::iterator ii = bbi->begin(), ie = bbi->end(); ii != ie;
           ++ii) {
        llvm::Instruction *instr = ii;
        if (!isa<CallInst>(instr)) continue;
        llvm::CallInst *call = dyn_cast<CallInst>(instr);
        llvm::Function *calledF = call->getCalledFunction();
        if (funcReplacements.find(calledF) == funcReplacements.end()) continue;

        call->setCalledFunction(funcReplacements[calledF]);
      }
  }

  regenerate_kernel_metadata(M, funcReplacements);

  /* Delete the old functions. */
  for (FunctionMapping::iterator i = funcReplacements.begin(),
         e = funcReplacements.end(); i != e; ++i) {
    i->first->eraseFromParent();
  }

  return true;
}

}
<|endoftext|>


<commit_before>#include "Server.h"

struct SvnLog{
	Vector<String> dirs;
	String author;
	Time date;
	String msg;
	int revision;
	void Load(String& log);
	void Store();
	void Clear();
	String AffectedPath();
	String ToString() const;
	SvnLog():msg("None"){};
};

Time XmlToTime(const String& text) {
	Time var;
	if(text.GetCount() > 15) {
		var.year = ScanInt(text.Left(4));
		var.month = ScanInt(text.Mid(5, 2));
		var.day = ScanInt(text.Mid(8, 2));
		var.hour = ScanInt(text.Mid(11, 2));
		var.minute = ScanInt(text.Mid(14, 2));
		var.second = ScanInt(text.Mid(17,2));
		if(var.IsValid())
			return var;
	}
	var = Null;
}

void SvnLog::Load(String& log) {
	Clear();
	XmlParser p(log);
	while(!p.End()){
		if(p.Tag("logentry")) {
			revision=p.Int("revision");
		} else if (p.Tag("author")){
			author = p.ReadText();
			p.SkipEnd();
		} else if (p.Tag("date")){
			date=XmlToTime(p.ReadText());
			p.SkipEnd();
		} else if (p.Tag("paths")){
			while(p.Tag("path")){
				String file = p.ReadText();
				dirs.Add(GetFileDirectory(file));
				p.SkipEnd();
			}
			p.SkipEnd();
		} else if (p.Tag("msg")){
			msg = p.ReadText();
			if(IsNull(msg))
				msg = "None";
			p.SkipEnd();
		} else {
			p.Skip();
		}
	}
}

void SvnLog::Store() {
	if(IsNull(date))
		date=Time(0,0,0);
	SQL * Insert(WORK)(REVISION,revision)
	                  (DT,date)
	                  (AUTHOR,author)
	                  (MSG, msg)
	                  (PATH, AffectedPath());
	SQL.Commit();
	SQL.Begin();
}

void SvnLog::Clear() {
	author = "unknown";
	msg = "*** no commit message ***";
	date = Null;
	dirs.Clear();
	revision = -1;
}

String SvnLog::AffectedPath() {
	for(int i = 0; i < dirs.GetCount(); i++){
		for(int j = i+1; j < dirs.GetCount(); j++){
			while(!dirs[j].StartsWith(dirs[i])){
				dirs[i] = GetFileDirectory(dirs[i].Left(dirs[i].GetCount()-1));
				if (dirs.IsEmpty())
					return "/";
			}
			dirs[j] = dirs[i];
		}
	}
	return dirs.GetCount()?dirs[0]:"/";
}

String SvnLog::ToString() const {
	String s;
	return s.Cat()<<date<<" "<<author<<": "<<msg;
}

void UpdateLogs(){
	String cmd = "svn log --xml --verbose --incremental --revision " + IntStr(lastrev()+1) + " " + Ini::svn;
	String xml;
	SvnLog svnlog;
	while(Sys(cmd, xml) == 0){
		lastrev()++;
		if(xml!="") {
			svnlog.Load(xml);
		} else {
			svnlog.Clear();
			svnlog.revision=lastrev();
		}
		svnlog.Store();
		cmd = "svn log --xml --verbose --incremental --revision " + IntStr(lastrev()+1) + " " + Ini::svn;
	}
}

void CleanResults(){
	SQL * Delete(RESULT)
	       .Where(STATUS==WD_INPROGRESS && START < GetSysTime()-int(Ini::max_test_time));
}

void CleanAuth(){
	SQL * Delete(AUTH).Where(VALID < GetSysTime()-600);
}

VectorMap<String,int> Paging(Http& http){
	int count = 3;
	int pagesize = max(min(Nvl(http.Int("cnt"), Nvl(http.Int(".cnt"), 10)),100),1);
	http.SessionSet("cnt",pagesize);
	int last = lastrev();
	int current = Nvl(http.Int("rev"), last);

	ValueArray va;
	ValueMap vm;
	for(int i = min(current+count*pagesize, last); i > current+pagesize-1; i-=pagesize){
		vm.Set("REV", i);
		vm.Set("TEXT", Format("[%i-%i]", min(last, i), i-pagesize+1));
		va.Add(vm);
	}
	if(current < last){
		vm.Set("REV", current + pagesize);
		vm.Set("TEXT", "< Newer");
		va.Add(vm);
	}
	if(current > pagesize){
		vm.Set("REV", current - pagesize);
		vm.Set("TEXT", "Older >");
		va.Add(vm);
	}
	for(int i = current - pagesize; i > max(current-(count+1)*pagesize, 0); i-=pagesize){
		vm.Set("REV", i);
		vm.Set("TEXT", Format("[%i-%i]", i, max(i-pagesize+1,0)));
		va.Add(vm);
	}
	http("PAGING", va);
//	http("cnt", pagesize);
	VectorMap<String,int> result;
	result.Add("min", current-pagesize+1);
	result.Add("max", current);
	result.Add("offfset", current-pagesize);
	result.Add("pagesize", pagesize);
	result.Add("current", current);
	return result;
}

bool CheckLocal(Http& http){
	if(http.GetHeader("host").StartsWith("localhost")
	 ||http.GetHeader("host").StartsWith("127.0.0.1"))
		return true;
	http.Response(403, "Forbiden");
	return false;
}

int& lastrev(){
	static Time last(Null);
	static int rev(0);
	if(GetSysTime() - last > 60){
		Sql sql;
		sql * Select(REVISION).From(WORK).OrderBy(Descending(REVISION)).Limit(1);
		if(sql.Fetch()){
			rev = sql[0];
			last = GetSysTime();
		} else {
			rev = 0;
			last = Null;
		}
	}
	return rev;
};

bool CheckAuth(Http& http, Sql& sql){
	String nonce = http.GetHeader("wd-nonce");
	sql * Delete(AUTH).Where(NONCE==nonce);
	if(sql.GetRowsProcessed() == 0){
		http << "Auth FAIL";
		http.Response(403,"Auth FAIL (nonce)");
		return false;
	}
	sql * Select(PASSWORD)
	      .From(CLIENT).Where(ID == http.Int("client_id"));
	String pwd;
	sql.Fetch(pwd);
	if (http.GetHeader("wd-auth")!=MD5String(nonce+pwd)) {
		http << "Auth FAIL";
		http.Response(403,"Auth FAIL (auth)");
		return false;
	}
	return true;
}

bool CheckAuth2(Http& http, Sql& sql, int client, const String& action){
	if(http.Int("client_id")!=client && http.Int("client_id")!=0){
		http << "Permission denied";
		http.Response(403,"Permission denied");
		return false;
	}
	if(http["wd_action"] != action) {
		http << "Auth FAIL (action)";
		http.Response(403,"Permission denied");
		return false;
	}
	String nonce = http["wd_nonce"];
	String auth = http["wd_auth"];
	sql * Delete(AUTH).Where(NONCE==nonce);
	if(sql.GetRowsProcessed() == 0){
		http << "Auth FAIL (nonce)";
		http.Response(403,"Permission denied");
		return false;
	}
	sql * Select(PASSWORD)
	      .From(CLIENT).Where(ID == http.Int("client_id"));
	String pwd;
	sql.Fetch(pwd);
	if (auth!=MD5String(nonce+String(http["wd_action"])+pwd)) {
		http << "Auth FAIL (auth)";
		http.Response(403,"Permission denied");
		return false;
	}
	return true;
}

void SendEmails(const Vector<String>& to, const Vector<String>& tokens, const String& subject, const String& text, const String& html){
	RLOG("Sending emails");
	Smtp mail;

	mail.Host(Ini::smtp_host)
	    .Port(Ini::smtp_port)
	    .SSL(Ini::smtp_use_ssl);
	if(!IsEmpty(Ini::smtp_user))
	   mail.Auth(Ini::smtp_user, Ini::smtp_password);
	String body, htmlbody;
	for(int i = 0; i < to.GetCount(); ++i){
		body = text;
		body.Replace("@token@",tokens[i]);
		mail.From(Ini::smtp_sender, Ini::smtp_from)
		    .To(to[i])
		    .Subject(subject)
		    .Body(body);
		if(!IsEmpty(html)){
			htmlbody = html;
			htmlbody.Replace("@token@",tokens[i]);
			mail.Body(htmlbody, "text/html");
		}
		if(mail.Send())
		    RLOG("Email successfully sent to " << to[i]);
		else
		    RLOG("Email sending failed: " << mail.GetError());
	}
}
void SendEmail(const String& to, const String& token, const String& subject, const String& text, const String& html){
	Vector<String> v1;
	v1.Add(to);
	Vector<String> v2;
	v2.Add(token);
	SendEmails(v1, v2, subject, text, html);
}

ValueArray ParseFilter(const String& filter){
	Vector<String> v = Split(filter,"&");
	ValueArray res;
	if(v.IsEmpty()) {
		res.Add("All the results");
		return res;
	}
	for(int i = 0; i < v.GetCount(); i++){
		if(v[i].StartsWith("author=")){
			v[i].Replace("author=","Author is ");
			res.Add(v[i]);
		} else if(v[i].StartsWith("path=")){
			v[i].Replace("path=","Commit affects path ");
			res.Add(v[i]);
		} else if(v[i].StartsWith("client=")){
			v[i].Replace("client=","");
			Sql sql;
			sql * Select(NAME).From(CLIENT).Where(ID==StrInt(v[i]));
			String name;
			sql.Fetch(name);
			res.Add("Client is " + name);
		} else if(v[i].StartsWith("status=")){
			res.Add(v[i].EndsWith("=ok")?"Only successfull":"Only failed");
		}
	}
	return res;
}

bool MatchFilter(const ValueMap& m, int revision, int client, int result, const String& author, const String& path){
	Vector<String> v = Split(AsString(m["FILTER"]),"&");
	if(v.IsEmpty())
		return true;
	bool matches = true;
	for(int i = 0; i < v.GetCount(); i++){
		if(v[i].StartsWith("author=")){
			v[i].Replace("author=","");
			matches = matches && (author == v[i]);
		} else if(v[i].StartsWith("path=")){
			v[i].Replace("path=","");
			matches = matches && (v[i].StartsWith(path));
		} else if(v[i].StartsWith("client=")){
			v[i].Replace("client=","");
			matches = matches && (StrInt(v[i]) == client);
		} else if(v[i].StartsWith("status=")){
			matches = matches && ((v[i].EndsWith("=ok") && result == WD_DONE) || (v[i].EndsWith("=failed") && result != WD_DONE));
		}
	}
	return matches;
}

SqlVal SqlEmptyString(){
	static SqlVal s("''",SqlS::HIGH);
	return s;
}

Value Duration(const Vector<Value>& arg, const Renderer *)
{
	int t = arg[0];
	if (t<=0)
		return "";
	else if (t<60)
		return Format("%d`s", t);
	else if (t<3600)
		return Format("%d`m %d`s", t/60, t%60);
	else
		return Format("%d`h %d`m %d`s", t/3600, (t%3600)/60, (t%3600)%60);
}

Value Email(const Vector<Value>& arg, const Renderer *)
{
	String name;
	switch(arg.GetCount()) {
	case 1:
		name = arg[0];
		break;
	case 2:
		name = arg[1];
		break;
	case 0:
	default:
		throw Exc("email: wrong number of arguments");
	}
	String addr;
	addr.Cat() << "<a href=\"mailto:" << arg[0] << "\">" << name << "";
	RawHtmlText r;
	r.text.Cat("");
	return RawPickToValue(r);
}

Value Dbg(const Vector<Value>& arg, const Renderer *r)
{
	if(!Ini::debug)
		return Value();
	String html;
	if(r) {
		const VectorMap<String, Value>& set = r->Variables();
		html << "

ID	VALUE
";
		for(int i = 0; i < set.GetCount(); i++)
			html << "
"
			     << EscapeHtml(set.GetKey(i))
			     << "
"
			     << EscapeHtml(AsString(set[i]))
			     << "

"
			;
		html << "

";
	}
	return Raw(html);
}

INITBLOCK {
	Compiler::Register("Duration", Duration);
	Compiler::Register("email", Email);
	Compiler::Register("dbg", Dbg);
};
<commit_msg>improved svn log parsing<commit_after>#include "Server.h"

struct SvnLog{
	Vector<String> dirs;
	String author;
	Time date;
	String msg;
	int revision;
	void Load(String& log);
	void Store();
	void Clear();
	String AffectedPath();
	String ToString() const;
	SvnLog(){ Clear(); };
};

Time XmlToTime(const String& text) {
	Time var;
	if(text.GetCount() > 15) {
		var.year = ScanInt(text.Left(4));
		var.month = ScanInt(text.Mid(5, 2));
		var.day = ScanInt(text.Mid(8, 2));
		var.hour = ScanInt(text.Mid(11, 2));
		var.minute = ScanInt(text.Mid(14, 2));
		var.second = ScanInt(text.Mid(17,2));
		if(var.IsValid())
			return var;
	}
	var = Null;
}

void SvnLog::Load(String& log) {
	Clear();
	XmlParser p(log);
	while(!p.End()){
		if(p.Tag("logentry")) {
			revision=p.Int("revision");
		} else if (p.Tag("author")){
			author = p.ReadText();
			p.SkipEnd();
		} else if (p.Tag("date")){
			date=XmlToTime(p.ReadText());
			p.SkipEnd();
		} else if (p.Tag("paths")){
			while(p.Tag("path")){
				String file = p.ReadText();
				dirs.Add(GetFileDirectory(file));
				p.SkipEnd();
			}
			p.SkipEnd();
		} else if (p.Tag("msg")){
			msg = p.ReadText();
			if(IsNull(msg))
				msg = "*** no commit message ***";
			p.SkipEnd();
		} else {
			p.Skip();
		}
	}
}

void SvnLog::Store() {
	if(IsNull(date))
		date=Time(0,0,0);
	SQL * Insert(WORK)(REVISION,revision)
	                  (DT,date)
	                  (AUTHOR,author)
	                  (MSG, msg)
	                  (PATH, AffectedPath());
	SQL.Commit();
	SQL.Begin();
}

void SvnLog::Clear() {
	author = "unknown";
	msg = "*** no commit message ***";
	date = Null;
	dirs.Clear();
	revision = -1;
}

String SvnLog::AffectedPath() {
	for(int i = 0; i < dirs.GetCount(); i++){
		for(int j = i+1; j < dirs.GetCount(); j++){
			while(!dirs[j].StartsWith(dirs[i])){
				dirs[i] = GetFileDirectory(dirs[i].Left(dirs[i].GetCount()-1));
				if (dirs.IsEmpty())
					return "/";
			}
			dirs[j] = dirs[i];
		}
	}
	return dirs.GetCount()?dirs[0]:"/";
}

String SvnLog::ToString() const {
	String s;
	return s.Cat()<<date<<" "<<author<<": "<<msg;
}

void UpdateLogs(){
	String cmd = "svn log --xml --verbose --incremental --revision " + IntStr(lastrev()+1) + " " + Ini::svn;
	String xml;
	SvnLog svnlog;
	DUMP(cmd);
	while(Sys(cmd, xml) == 0){
		lastrev()++;
		DUMP(xml);
		if(xml!="") {
			svnlog.Load(xml);
			DUMP(svnlog);
			svnlog.Store();
		}
		svnlog.Clear();
		cmd = "svn log --xml --verbose --incremental --revision " + IntStr(lastrev()+1) + " " + Ini::svn;
	}
}

void CleanResults(){
	SQL * Delete(RESULT)
	       .Where(STATUS==WD_INPROGRESS && START < GetSysTime()-int(Ini::max_test_time));
}

void CleanAuth(){
	SQL * Delete(AUTH).Where(VALID < GetSysTime()-600);
}

VectorMap<String,int> Paging(Http& http){
	int count = 3;
	int pagesize = max(min(Nvl(http.Int("cnt"), Nvl(http.Int(".cnt"), 10)),100),1);
	http.SessionSet("cnt",pagesize);
	int last = lastrev();
	int current = Nvl(http.Int("rev"), last);

	ValueArray va;
	ValueMap vm;
	for(int i = min(current+count*pagesize, last); i > current+pagesize-1; i-=pagesize){
		vm.Set("REV", i);
		vm.Set("TEXT", Format("[%i-%i]", min(last, i), i-pagesize+1));
		va.Add(vm);
	}
	if(current < last){
		vm.Set("REV", current + pagesize);
		vm.Set("TEXT", "< Newer");
		va.Add(vm);
	}
	if(current > pagesize){
		vm.Set("REV", current - pagesize);
		vm.Set("TEXT", "Older >");
		va.Add(vm);
	}
	for(int i = current - pagesize; i > max(current-(count+1)*pagesize, 0); i-=pagesize){
		vm.Set("REV", i);
		vm.Set("TEXT", Format("[%i-%i]", i, max(i-pagesize+1,0)));
		va.Add(vm);
	}
	http("PAGING", va);
//	http("cnt", pagesize);
	VectorMap<String,int> result;
	result.Add("min", current-pagesize+1);
	result.Add("max", current);
	result.Add("offfset", current-pagesize);
	result.Add("pagesize", pagesize);
	result.Add("current", current);
	return result;
}

bool CheckLocal(Http& http){
	if(http.GetHeader("host").StartsWith("localhost")
	 ||http.GetHeader("host").StartsWith("127.0.0.1"))
		return true;
	http.Response(403, "Forbiden");
	return false;
}

int& lastrev(){
	static Time last(Null);
	static int rev(0);
	if(GetSysTime() - last > 60){
		Sql sql;
		sql * Select(REVISION).From(WORK).OrderBy(Descending(REVISION)).Limit(1);
		if(sql.Fetch()){
			rev = sql[0];
			last = GetSysTime();
		} else {
			rev = 0;
			last = Null;
		}
	}
	return rev;
};

bool CheckAuth(Http& http, Sql& sql){
	String nonce = http.GetHeader("wd-nonce");
	sql * Delete(AUTH).Where(NONCE==nonce);
	if(sql.GetRowsProcessed() == 0){
		http << "Auth FAIL";
		http.Response(403,"Auth FAIL (nonce)");
		return false;
	}
	sql * Select(PASSWORD)
	      .From(CLIENT).Where(ID == http.Int("client_id"));
	String pwd;
	sql.Fetch(pwd);
	if (http.GetHeader("wd-auth")!=MD5String(nonce+pwd)) {
		http << "Auth FAIL";
		http.Response(403,"Auth FAIL (auth)");
		return false;
	}
	return true;
}

bool CheckAuth2(Http& http, Sql& sql, int client, const String& action){
	if(http.Int("client_id")!=client && http.Int("client_id")!=0){
		http << "Permission denied";
		http.Response(403,"Permission denied");
		return false;
	}
	if(http["wd_action"] != action) {
		http << "Auth FAIL (action)";
		http.Response(403,"Permission denied");
		return false;
	}
	String nonce = http["wd_nonce"];
	String auth = http["wd_auth"];
	sql * Delete(AUTH).Where(NONCE==nonce);
	if(sql.GetRowsProcessed() == 0){
		http << "Auth FAIL (nonce)";
		http.Response(403,"Permission denied");
		return false;
	}
	sql * Select(PASSWORD)
	      .From(CLIENT).Where(ID == http.Int("client_id"));
	String pwd;
	sql.Fetch(pwd);
	if (auth!=MD5String(nonce+String(http["wd_action"])+pwd)) {
		http << "Auth FAIL (auth)";
		http.Response(403,"Permission denied");
		return false;
	}
	return true;
}

void SendEmails(const Vector<String>& to, const Vector<String>& tokens, const String& subject, const String& text, const String& html){
	RLOG("Sending emails");
	Smtp mail;

	mail.Host(Ini::smtp_host)
	    .Port(Ini::smtp_port)
	    .SSL(Ini::smtp_use_ssl);
	if(!IsEmpty(Ini::smtp_user))
	   mail.Auth(Ini::smtp_user, Ini::smtp_password);
	String body, htmlbody;
	for(int i = 0; i < to.GetCount(); ++i){
		body = text;
		body.Replace("@token@",tokens[i]);
		mail.From(Ini::smtp_sender, Ini::smtp_from)
		    .To(to[i])
		    .Subject(subject)
		    .Body(body);
		if(!IsEmpty(html)){
			htmlbody = html;
			htmlbody.Replace("@token@",tokens[i]);
			mail.Body(htmlbody, "text/html");
		}
		if(mail.Send())
		    RLOG("Email successfully sent to " << to[i]);
		else
		    RLOG("Email sending failed: " << mail.GetError());
	}
}
void SendEmail(const String& to, const String& token, const String& subject, const String& text, const String& html){
	Vector<String> v1;
	v1.Add(to);
	Vector<String> v2;
	v2.Add(token);
	SendEmails(v1, v2, subject, text, html);
}

ValueArray ParseFilter(const String& filter){
	Vector<String> v = Split(filter,"&");
	ValueArray res;
	if(v.IsEmpty()) {
		res.Add("All the results");
		return res;
	}
	for(int i = 0; i < v.GetCount(); i++){
		if(v[i].StartsWith("author=")){
			v[i].Replace("author=","Author is ");
			res.Add(v[i]);
		} else if(v[i].StartsWith("path=")){
			v[i].Replace("path=","Commit affects path ");
			res.Add(v[i]);
		} else if(v[i].StartsWith("client=")){
			v[i].Replace("client=","");
			Sql sql;
			sql * Select(NAME).From(CLIENT).Where(ID==StrInt(v[i]));
			String name;
			sql.Fetch(name);
			res.Add("Client is " + name);
		} else if(v[i].StartsWith("status=")){
			res.Add(v[i].EndsWith("=ok")?"Only successfull":"Only failed");
		}
	}
	return res;
}

bool MatchFilter(const ValueMap& m, int revision, int client, int result, const String& author, const String& path){
	Vector<String> v = Split(AsString(m["FILTER"]),"&");
	if(v.IsEmpty())
		return true;
	bool matches = true;
	for(int i = 0; i < v.GetCount(); i++){
		if(v[i].StartsWith("author=")){
			v[i].Replace("author=","");
			matches = matches && (author == v[i]);
		} else if(v[i].StartsWith("path=")){
			v[i].Replace("path=","");
			matches = matches && (v[i].StartsWith(path));
		} else if(v[i].StartsWith("client=")){
			v[i].Replace("client=","");
			matches = matches && (StrInt(v[i]) == client);
		} else if(v[i].StartsWith("status=")){
			matches = matches && ((v[i].EndsWith("=ok") && result == WD_DONE) || (v[i].EndsWith("=failed") && result != WD_DONE));
		}
	}
	return matches;
}

SqlVal SqlEmptyString(){
	static SqlVal s("''",SqlS::HIGH);
	return s;
}

Value Duration(const Vector<Value>& arg, const Renderer *)
{
	int t = arg[0];
	if (t<=0)
		return "";
	else if (t<60)
		return Format("%d`s", t);
	else if (t<3600)
		return Format("%d`m %d`s", t/60, t%60);
	else
		return Format("%d`h %d`m %d`s", t/3600, (t%3600)/60, (t%3600)%60);
}

Value Email(const Vector<Value>& arg, const Renderer *)
{
	String name;
	switch(arg.GetCount()) {
	case 1:
		name = arg[0];
		break;
	case 2:
		name = arg[1];
		break;
	case 0:
	default:
		throw Exc("email: wrong number of arguments");
	}
	String addr;
	addr.Cat() << "<a href=\"mailto:" << arg[0] << "\">" << name << "";
	RawHtmlText r;
	r.text.Cat("");
	return RawPickToValue(r);
}

Value Dbg(const Vector<Value>& arg, const Renderer *r)
{
	if(!Ini::debug)
		return Value();
	String html;
	if(r) {
		const VectorMap<String, Value>& set = r->Variables();
		html << "

ID	VALUE
";
		for(int i = 0; i < set.GetCount(); i++)
			html << "
"
			     << EscapeHtml(set.GetKey(i))
			     << "
"
			     << EscapeHtml(AsString(set[i]))
			     << "

"
			;
		html << "

";
	}
	return Raw(html);
}

INITBLOCK {
	Compiler::Register("Duration", Duration);
	Compiler::Register("email", Email);
	Compiler::Register("dbg", Dbg);
};
<|endoftext|>