<commit_before>/*
 * (C) Copyright 2013 Kurento (http://kurento.org/)
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl-2.1.html
 *
 * 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.
 *
 */

#include "ZBarFilter.hpp"

#include "KmsMediaZBarFilterType_constants.h"

#include "utils/utils.hpp"
#include "KmsMediaDataType_constants.h"
#include "KmsMediaErrorCodes_constants.h"

// TODO: reuse when needed
#if 0
#include "protocol/TBinaryProtocol.h"
#include "transport/TBufferTransports.h"
#endif

#define GST_CAT_DEFAULT kurento_zbar_filter
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define GST_DEFAULT_NAME "KurentoZBarFilter"

// TODO: reuse when needed
#if 0
using apache::thrift::transport::TMemoryBuffer;
using apache::thrift::protocol::TBinaryProtocol;
#endif

namespace kurento
{

void
zbar_receive_message (GstBus *bus, GstMessage *message, gpointer zbar)
{
  ZBarFilter *filter = (ZBarFilter *) zbar;

  if (GST_MESSAGE_SRC (message) == GST_OBJECT (filter->zbar) &&
      GST_MESSAGE_TYPE (message) == GST_MESSAGE_ELEMENT) {
    const GstStructure *st;
    guint64 ts;
    gchar *type, *symbol;

    st = gst_message_get_structure (message);

    if (g_strcmp0 (gst_structure_get_name (st), "barcode") != 0)
      return;

    if (!gst_structure_get (st, "timestamp", G_TYPE_UINT64, &ts,
        "type", G_TYPE_STRING, &type, "symbol", G_TYPE_STRING, &symbol, NULL) )
      return;

    std::string symbolStr (symbol);
    std::string typeStr (type);

    g_free (type);
    g_free (symbol);

    filter->barcodeDetected (ts, typeStr, symbolStr);
  }
}

void
ZBarFilter::init (std::shared_ptr<MediaPipeline> parent)
{
  element = gst_element_factory_make ("filterelement", NULL);

  g_object_set (element, "filter-factory", "zbar", NULL);
  g_object_ref (element);
  gst_bin_add (GST_BIN (parent->pipeline), element);
  gst_element_sync_state_with_parent (element);

  GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (parent->pipeline) );
  GstElement *zbar;

  g_object_get (G_OBJECT (element), "filter", &zbar, NULL);

  this->zbar = zbar;

  bus_handler_id = g_signal_connect (bus, "message", G_CALLBACK (zbar_receive_message), this);
  g_object_unref (bus);
  // There is no need to reference zbar becase its live cycle is the same as the filter live cycle
  g_object_unref (zbar);
}

ZBarFilter::ZBarFilter (std::shared_ptr<MediaPipeline> parent, const KmsMediaParams &params)
throw (KmsMediaServerException)
  : Filter (parent, g_KmsMediaZBarFilterType_constants.TYPE_NAME)
{
  if (params == defaultKmsMediaParams ||
      g_KmsMediaDataType_constants.VOID_DATA_TYPE.compare (params.dataType) == 0) {
    init (parent);
  } else {
    throw createKmsMediaServerException (g_KmsMediaErrorCodes_constants.MEDIA_OBJECT_CONSTRUCTOR_NOT_FOUND,
        "ZBarFilter has not any constructor with params of type " + params.dataType);
  }
}

ZBarFilter::~ZBarFilter() throw ()
{
  GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (std::dynamic_pointer_cast<MediaPipeline> (parent)->pipeline) );

  g_signal_handler_disconnect (bus, bus_handler_id);
  g_object_unref (bus);

  gst_bin_remove (GST_BIN ( ( (std::shared_ptr<MediaPipeline> &) parent)->pipeline), element);
  gst_element_set_state (element, GST_STATE_NULL);
  g_object_unref (element);
}

void
ZBarFilter::raiseEvent (guint64 ts, std::string &type, std::string &symbol)
{
// TODO: reuse when needed
#if 0
  boost::shared_ptr<TMemoryBuffer> transport (new TMemoryBuffer() );
  TBinaryProtocol protocol (transport);
  MediaEvent event;
  ZBarEvent zbarEvent;

  zbarEvent.__set_type (type);
  zbarEvent.__set_value (symbol);
  zbarEvent.write (&protocol);
  std::string event_str;
  transport->appendBufferToString (event_str);
  event.__set_event (event_str);
  event.__set_source (*this);

  GST_DEBUG ("Raise event");
  GST_DEBUG ("Time stamp: %" G_GUINT64_FORMAT, ts);
  GST_DEBUG ("Type: %s", type.c_str() );
  GST_DEBUG ("Symbol: %s", symbol.c_str() );

  std::dynamic_pointer_cast<MediaPipeline> (parent)->sendEvent (event);
#endif
}

void
ZBarFilter::barcodeDetected (guint64 ts, std::string &type, std::string &symbol)
{
  if (lastSymbol != symbol || lastType != type ||
      lastTs == G_GUINT64_CONSTANT (0) || ( (ts - lastTs) >= GST_SECOND) ) {
    lastSymbol = symbol;
    lastType = type;
    lastTs = ts;
    raiseEvent (ts, type, symbol);
  }
}

ZBarFilter::StaticConstructor ZBarFilter::staticConstructor;

ZBarFilter::StaticConstructor::StaticConstructor()
{
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0,
      GST_DEFAULT_NAME);
}

} // kurento
<commit_msg>ZBarFilter: implement raiseEvent<commit_after>/*
 * (C) Copyright 2013 Kurento (http://kurento.org/)
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl-2.1.html
 *
 * 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.
 *
 */

#include "ZBarFilter.hpp"

#include "KmsMediaZBarFilterType_constants.h"

#include "utils/utils.hpp"
#include "KmsMediaDataType_constants.h"
#include "KmsMediaErrorCodes_constants.h"

#include "protocol/TBinaryProtocol.h"
#include "transport/TBufferTransports.h"

#define GST_CAT_DEFAULT kurento_zbar_filter
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define GST_DEFAULT_NAME "KurentoZBarFilter"

using apache::thrift::transport::TMemoryBuffer;
using apache::thrift::protocol::TBinaryProtocol;

namespace kurento
{

void
zbar_receive_message (GstBus *bus, GstMessage *message, gpointer zbar)
{
  ZBarFilter *filter = (ZBarFilter *) zbar;

  if (GST_MESSAGE_SRC (message) == GST_OBJECT (filter->zbar) &&
      GST_MESSAGE_TYPE (message) == GST_MESSAGE_ELEMENT) {
    const GstStructure *st;
    guint64 ts;
    gchar *type, *symbol;

    st = gst_message_get_structure (message);

    if (g_strcmp0 (gst_structure_get_name (st), "barcode") != 0)
      return;

    if (!gst_structure_get (st, "timestamp", G_TYPE_UINT64, &ts,
        "type", G_TYPE_STRING, &type, "symbol", G_TYPE_STRING, &symbol, NULL) )
      return;

    std::string symbolStr (symbol);
    std::string typeStr (type);

    g_free (type);
    g_free (symbol);

    filter->barcodeDetected (ts, typeStr, symbolStr);
  }
}

void
ZBarFilter::init (std::shared_ptr<MediaPipeline> parent)
{
  element = gst_element_factory_make ("filterelement", NULL);

  g_object_set (element, "filter-factory", "zbar", NULL);
  g_object_ref (element);
  gst_bin_add (GST_BIN (parent->pipeline), element);
  gst_element_sync_state_with_parent (element);

  GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (parent->pipeline) );
  GstElement *zbar;

  g_object_get (G_OBJECT (element), "filter", &zbar, NULL);

  this->zbar = zbar;

  bus_handler_id = g_signal_connect (bus, "message", G_CALLBACK (zbar_receive_message), this);
  g_object_unref (bus);
  // There is no need to reference zbar becase its live cycle is the same as the filter live cycle
  g_object_unref (zbar);
}

ZBarFilter::ZBarFilter (std::shared_ptr<MediaPipeline> parent, const KmsMediaParams &params)
throw (KmsMediaServerException)
  : Filter (parent, g_KmsMediaZBarFilterType_constants.TYPE_NAME)
{
  if (params == defaultKmsMediaParams ||
      g_KmsMediaDataType_constants.VOID_DATA_TYPE.compare (params.dataType) == 0) {
    init (parent);
  } else {
    throw createKmsMediaServerException (g_KmsMediaErrorCodes_constants.MEDIA_OBJECT_CONSTRUCTOR_NOT_FOUND,
        "ZBarFilter has not any constructor with params of type " + params.dataType);
  }
}

ZBarFilter::~ZBarFilter() throw ()
{
  GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (std::dynamic_pointer_cast<MediaPipeline> (parent)->pipeline) );

  g_signal_handler_disconnect (bus, bus_handler_id);
  g_object_unref (bus);

  gst_bin_remove (GST_BIN ( ( (std::shared_ptr<MediaPipeline> &) parent)->pipeline), element);
  gst_element_set_state (element, GST_STATE_NULL);
  g_object_unref (element);
}

void
ZBarFilter::raiseEvent (guint64 ts, std::string &type, std::string &symbol)
{
  KmsMediaEventData eventData;
  KmsMediaEventCodeFoundData codeFoundData;
  std::string codeFoundDataStr;

  boost::shared_ptr<TMemoryBuffer> transport (new TMemoryBuffer() );
  TBinaryProtocol protocol (transport);

  codeFoundData.__set_type (type);
  codeFoundData.__set_value (symbol);
  codeFoundData.write (&protocol);
  transport->appendBufferToString (codeFoundDataStr);

  eventData.__set_dataType (g_KmsMediaZBarFilterType_constants.EVENT_CODE_FOUND_DATA_TYPE);
  eventData.__set_data (codeFoundDataStr);

  GST_DEBUG ("Raise event");
  GST_DEBUG ("Time stamp: %" G_GUINT64_FORMAT, ts);
  GST_DEBUG ("Type: %s", type.c_str() );
  GST_DEBUG ("Symbol: %s", symbol.c_str() );

  sendEvent (g_KmsMediaZBarFilterType_constants.EVENT_CODE_FOUND, eventData);
}

void
ZBarFilter::barcodeDetected (guint64 ts, std::string &type, std::string &symbol)
{
  if (lastSymbol != symbol || lastType != type ||
      lastTs == G_GUINT64_CONSTANT (0) || ( (ts - lastTs) >= GST_SECOND) ) {
    lastSymbol = symbol;
    lastType = type;
    lastTs = ts;
    raiseEvent (ts, type, symbol);
  }
}

ZBarFilter::StaticConstructor ZBarFilter::staticConstructor;

ZBarFilter::StaticConstructor::StaticConstructor()
{
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0,
      GST_DEFAULT_NAME);
}

} // kurento
<|endoftext|>


<commit_before>/*
 * (C) Copyright 2013 Kurento (http://kurento.org/)
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl-2.1.html
 *
 * 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.
 *
 */

#include "ZBarFilter.hpp"

#include "KmsMediaZBarFilterType_constants.h"

#include "utils/utils.hpp"
#include "KmsMediaDataType_constants.h"
#include "KmsMediaErrorCodes_constants.h"

#include "protocol/TBinaryProtocol.h"
#include "transport/TBufferTransports.h"

#define GST_CAT_DEFAULT kurento_zbar_filter
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define GST_DEFAULT_NAME "KurentoZBarFilter"

using apache::thrift::transport::TMemoryBuffer;
using apache::thrift::protocol::TBinaryProtocol;

namespace kurento
{

void
zbar_receive_message (GstBus *bus, GstMessage *message, gpointer zbar)
{
  ZBarFilter *filter = (ZBarFilter *) zbar;

  if (GST_MESSAGE_SRC (message) == GST_OBJECT (filter->zbar) &&
      GST_MESSAGE_TYPE (message) == GST_MESSAGE_ELEMENT) {
    const GstStructure *st;
    guint64 ts;
    gchar *type, *symbol;

    st = gst_message_get_structure (message);

    if (g_strcmp0 (gst_structure_get_name (st), "barcode") != 0)
      return;

    if (!gst_structure_get (st, "timestamp", G_TYPE_UINT64, &ts,
                            "type", G_TYPE_STRING, &type, "symbol", G_TYPE_STRING, &symbol, NULL) )
      return;

    std::string symbolStr (symbol);
    std::string typeStr (type);

    g_free (type);
    g_free (symbol);

    filter->barcodeDetected (ts, typeStr, symbolStr);
  }
}

void
ZBarFilter::init (std::shared_ptr<MediaPipeline> parent)
{
  element = gst_element_factory_make ("filterelement", NULL);

  g_object_set (element, "filter-factory", "zbar", NULL);
  g_object_ref (element);
  gst_bin_add (GST_BIN (parent->pipeline), element);
  gst_element_sync_state_with_parent (element);

  GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (parent->pipeline) );
  GstElement *zbar;

  g_object_get (G_OBJECT (element), "filter", &zbar, NULL);

  this->zbar = zbar;

  bus_handler_id = g_signal_connect (bus, "message", G_CALLBACK (zbar_receive_message), this);
  g_object_unref (bus);
  // There is no need to reference zbar becase its live cycle is the same as the filter live cycle
  g_object_unref (zbar);
}

ZBarFilter::ZBarFilter (MediaSet &mediaSet,
                        std::shared_ptr<MediaPipeline> parent,
                        const std::map<std::string, KmsMediaParam> &params)
throw (KmsMediaServerException)
  : Filter (mediaSet, parent, g_KmsMediaZBarFilterType_constants.TYPE_NAME, params)
{
  init (parent);
}

ZBarFilter::~ZBarFilter() throw ()
{
  GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (std::dynamic_pointer_cast<MediaPipeline> (parent)->pipeline) );

  g_signal_handler_disconnect (bus, bus_handler_id);
  g_object_unref (bus);

  gst_bin_remove (GST_BIN ( ( (std::shared_ptr<MediaPipeline> &) parent)->pipeline), element);
  gst_element_set_state (element, GST_STATE_NULL);
  g_object_unref (element);
}

void
ZBarFilter::raiseEvent (guint64 ts, std::string &type, std::string &symbol)
{
  KmsMediaEventData eventData;
  KmsMediaEventCodeFoundData codeFoundData;
  std::string codeFoundDataStr;

  boost::shared_ptr<TMemoryBuffer> transport (new TMemoryBuffer() );
  TBinaryProtocol protocol (transport);

  codeFoundData.__set_type (type);
  codeFoundData.__set_value (symbol);
  codeFoundData.write (&protocol);
  transport->appendBufferToString (codeFoundDataStr);

  eventData.__set_dataType (g_KmsMediaZBarFilterType_constants.EVENT_CODE_FOUND_DATA_TYPE);
  eventData.__set_data (codeFoundDataStr);

  GST_DEBUG ("Raise event");
  GST_DEBUG ("Time stamp: %" G_GUINT64_FORMAT, ts);
  GST_DEBUG ("Type: %s", type.c_str() );
  GST_DEBUG ("Symbol: %s", symbol.c_str() );

  sendEvent (g_KmsMediaZBarFilterType_constants.EVENT_CODE_FOUND, eventData);
}

void
ZBarFilter::barcodeDetected (guint64 ts, std::string &type, std::string &symbol)
{
  if (lastSymbol != symbol || lastType != type ||
      lastTs == G_GUINT64_CONSTANT (0) || ( (ts - lastTs) >= GST_SECOND) ) {
    lastSymbol = symbol;
    lastType = type;
    lastTs = ts;
    raiseEvent (ts, type, symbol);
  }
}

void
ZBarFilter::subscribe (std::string &_return, const std::string &eventType,
                       const std::string &handlerAddress,
                       const int32_t handlerPort) throw (KmsMediaServerException)
{
  if (g_KmsMediaZBarFilterType_constants.EVENT_CODE_FOUND == eventType)
    mediaHandlerManager.addMediaHandler (_return, eventType, handlerAddress, handlerPort);
  else
    Filter::subscribe (_return, eventType, handlerAddress, handlerPort);
}

ZBarFilter::StaticConstructor ZBarFilter::staticConstructor;

ZBarFilter::StaticConstructor::StaticConstructor()
{
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0,
                           GST_DEFAULT_NAME);
}

} // kurento
<commit_msg>zbarfilter: Force scan all the frames even if computer is overloaded<commit_after>/*
 * (C) Copyright 2013 Kurento (http://kurento.org/)
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl-2.1.html
 *
 * 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.
 *
 */

#include "ZBarFilter.hpp"

#include "KmsMediaZBarFilterType_constants.h"

#include "utils/utils.hpp"
#include "KmsMediaDataType_constants.h"
#include "KmsMediaErrorCodes_constants.h"

#include "protocol/TBinaryProtocol.h"
#include "transport/TBufferTransports.h"

#define GST_CAT_DEFAULT kurento_zbar_filter
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define GST_DEFAULT_NAME "KurentoZBarFilter"

using apache::thrift::transport::TMemoryBuffer;
using apache::thrift::protocol::TBinaryProtocol;

namespace kurento
{

void
zbar_receive_message (GstBus *bus, GstMessage *message, gpointer zbar)
{
  ZBarFilter *filter = (ZBarFilter *) zbar;

  if (GST_MESSAGE_SRC (message) == GST_OBJECT (filter->zbar) &&
      GST_MESSAGE_TYPE (message) == GST_MESSAGE_ELEMENT) {
    const GstStructure *st;
    guint64 ts;
    gchar *type, *symbol;

    st = gst_message_get_structure (message);

    if (g_strcmp0 (gst_structure_get_name (st), "barcode") != 0)
      return;

    if (!gst_structure_get (st, "timestamp", G_TYPE_UINT64, &ts,
                            "type", G_TYPE_STRING, &type, "symbol", G_TYPE_STRING, &symbol, NULL) )
      return;

    std::string symbolStr (symbol);
    std::string typeStr (type);

    g_free (type);
    g_free (symbol);

    filter->barcodeDetected (ts, typeStr, symbolStr);
  }
}

void
ZBarFilter::init (std::shared_ptr<MediaPipeline> parent)
{
  element = gst_element_factory_make ("filterelement", NULL);

  g_object_set (element, "filter-factory", "zbar", NULL);
  g_object_ref (element);
  gst_bin_add (GST_BIN (parent->pipeline), element);
  gst_element_sync_state_with_parent (element);

  GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (parent->pipeline) );
  GstElement *zbar;

  g_object_get (G_OBJECT (element), "filter", &zbar, NULL);

  this->zbar = zbar;
  g_object_set (G_OBJECT (zbar), "qos", FALSE, NULL);

  bus_handler_id = g_signal_connect (bus, "message", G_CALLBACK (zbar_receive_message), this);
  g_object_unref (bus);
  // There is no need to reference zbar becase its live cycle is the same as the filter live cycle
  g_object_unref (zbar);
}

ZBarFilter::ZBarFilter (MediaSet &mediaSet,
                        std::shared_ptr<MediaPipeline> parent,
                        const std::map<std::string, KmsMediaParam> &params)
throw (KmsMediaServerException)
  : Filter (mediaSet, parent, g_KmsMediaZBarFilterType_constants.TYPE_NAME, params)
{
  init (parent);
}

ZBarFilter::~ZBarFilter() throw ()
{
  GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (std::dynamic_pointer_cast<MediaPipeline> (parent)->pipeline) );

  g_signal_handler_disconnect (bus, bus_handler_id);
  g_object_unref (bus);

  gst_bin_remove (GST_BIN ( ( (std::shared_ptr<MediaPipeline> &) parent)->pipeline), element);
  gst_element_set_state (element, GST_STATE_NULL);
  g_object_unref (element);
}

void
ZBarFilter::raiseEvent (guint64 ts, std::string &type, std::string &symbol)
{
  KmsMediaEventData eventData;
  KmsMediaEventCodeFoundData codeFoundData;
  std::string codeFoundDataStr;

  boost::shared_ptr<TMemoryBuffer> transport (new TMemoryBuffer() );
  TBinaryProtocol protocol (transport);

  codeFoundData.__set_type (type);
  codeFoundData.__set_value (symbol);
  codeFoundData.write (&protocol);
  transport->appendBufferToString (codeFoundDataStr);

  eventData.__set_dataType (g_KmsMediaZBarFilterType_constants.EVENT_CODE_FOUND_DATA_TYPE);
  eventData.__set_data (codeFoundDataStr);

  GST_DEBUG ("Raise event");
  GST_DEBUG ("Time stamp: %" G_GUINT64_FORMAT, ts);
  GST_DEBUG ("Type: %s", type.c_str() );
  GST_DEBUG ("Symbol: %s", symbol.c_str() );

  sendEvent (g_KmsMediaZBarFilterType_constants.EVENT_CODE_FOUND, eventData);
}

void
ZBarFilter::barcodeDetected (guint64 ts, std::string &type, std::string &symbol)
{
  if (lastSymbol != symbol || lastType != type ||
      lastTs == G_GUINT64_CONSTANT (0) || ( (ts - lastTs) >= GST_SECOND) ) {
    lastSymbol = symbol;
    lastType = type;
    lastTs = ts;
    raiseEvent (ts, type, symbol);
  }
}

void
ZBarFilter::subscribe (std::string &_return, const std::string &eventType,
                       const std::string &handlerAddress,
                       const int32_t handlerPort) throw (KmsMediaServerException)
{
  if (g_KmsMediaZBarFilterType_constants.EVENT_CODE_FOUND == eventType)
    mediaHandlerManager.addMediaHandler (_return, eventType, handlerAddress, handlerPort);
  else
    Filter::subscribe (_return, eventType, handlerAddress, handlerPort);
}

ZBarFilter::StaticConstructor ZBarFilter::staticConstructor;

ZBarFilter::StaticConstructor::StaticConstructor()
{
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0,
                           GST_DEFAULT_NAME);
}

} // kurento
<|endoftext|>


<commit_before>/********** tell emacs we use -*- c++ -*- style comments *******************
 $Revision: 1.1 $  $Author: trey $  $Date: 2006-06-12 18:12:47 $

 @file    testLSModelFile.cc
 @brief   No brief

 Copyright (c) 2006, Trey Smith. All rights reserved.

 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.

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

/***************************************************************************
 * INCLUDES
 ***************************************************************************/

#include <assert.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

#include <iostream>

#include "LSModelFile.h"

using namespace std;

void usage(void) {
  cerr <<
    "usage: testLSModelFile OPTIONS <foo.lifeSurvey>\n"
    "  -h or --help   Display this help\n";
  exit(EXIT_FAILURE);
}

int main(int argc, char *argv[]) {
  int argi;
  char *modelFileName = 0;
  for (argi=1; argi < argc; argi++) {
    if (0 == strcmp("-h",argv[argi]) || 0 == strcmp("--help",argv[argi])) {
      usage();
    } else if (0 == modelFileName) {
      modelFileName = argv[argi];
    } else {
      cerr << "too many arguments" << endl;
      usage();
    }
  }
  if ( 0 == modelFileName ) {
    usage();
  }

  LSModelFile m;

  // read the map in
  m.readFromFile(modelFileName);

  // modify it a bit
  m.grid.setCell(LSPos(0,0),1);
  m.grid.setCell(LSPos(3,6),1);
  m.grid.setCell(LSPos(17,0),1);
  m.grid.setCell(LSPos(20,6),1);

  // write it back out to stdout
  m.writeToFile(stdout);
}

/***************************************************************************
 * REVISION HISTORY:
 * $Log: not supported by cvs2svn $
 * Revision 1.1  2006/06/11 14:37:39  trey
 * initial check-in
 *
 *
 ***************************************************************************/
<commit_msg>now using namespace zmdp<commit_after>/********** tell emacs we use -*- c++ -*- style comments *******************
 $Revision: 1.2 $  $Author: trey $  $Date: 2006-06-29 21:38:37 $

 @file    testLSModelFile.cc
 @brief   No brief

 Copyright (c) 2006, Trey Smith. All rights reserved.

 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.

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

/***************************************************************************
 * INCLUDES
 ***************************************************************************/

#include <assert.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

#include <iostream>

#include "LSModelFile.h"

using namespace std;
using namespace zmdp;

void usage(void) {
  cerr <<
    "usage: testLSModelFile OPTIONS <foo.lifeSurvey>\n"
    "  -h or --help   Display this help\n";
  exit(EXIT_FAILURE);
}

int main(int argc, char *argv[]) {
  int argi;
  char *modelFileName = 0;
  for (argi=1; argi < argc; argi++) {
    if (0 == strcmp("-h",argv[argi]) || 0 == strcmp("--help",argv[argi])) {
      usage();
    } else if (0 == modelFileName) {
      modelFileName = argv[argi];
    } else {
      cerr << "too many arguments" << endl;
      usage();
    }
  }
  if ( 0 == modelFileName ) {
    usage();
  }

  LSModelFile m;

  // read the map in
  m.readFromFile(modelFileName);

  // modify it a bit
  m.grid.setCell(LSPos(0,0),1);
  m.grid.setCell(LSPos(3,6),1);
  m.grid.setCell(LSPos(17,0),1);
  m.grid.setCell(LSPos(20,6),1);

  // write it back out to stdout
  m.writeToFile(stdout);
}

/***************************************************************************
 * REVISION HISTORY:
 * $Log: not supported by cvs2svn $
 * Revision 1.1  2006/06/12 18:12:47  trey
 * renamed LSModel to LSModelFile; minor updates
 *
 * Revision 1.1  2006/06/11 14:37:39  trey
 * initial check-in
 *
 *
 ***************************************************************************/
<|endoftext|>


<commit_before>// webadmin.cpp : Defines the entry point for the DLL application.
//

#include "bzfsAPI.h"
#include "plugin_utils.h"
#include "plugin_HTTP.h"
#include <fstream>
#include <cstring>
#include <algorithm>

class WebAdmin : public BZFSHTTPAuth, TemplateCallbackClass
{
public:
  WebAdmin();
  virtual const char * getVDir ( void ){return "webadmin";}
  virtual const char * getDescription ( void ){return "Server Administration (Login Required)";}

  void init (const char *tDir);

  virtual bool handleAuthedRequest ( int level, const HTTPRequest &request, HTTPReply &reply );

  // from TemplateCallbackClass
  virtual void keyCallback (std::string &data, const std::string &key);
  virtual bool loopCallback (const std::string &key);
  virtual bool ifCallback (const std::string &key);

private:
  unsigned int loopPos;
  std::map<std::string,std::string> templateVars;

  typedef void (WebAdmin::*page_callback)(const HTTPRequest &);
  std::map<std::string,page_callback> controllers;
  std::vector<std::string> pagenames;

  void mainPageCallback (const HTTPRequest &request);
  void banlistPageCallback (const HTTPRequest &request);
  void groupPageCallback (const HTTPRequest &request);

  bz_APIIntList players;
  bz_APIStringList *stringList;
  int listSize;

  bool editing, checked;
};

WebAdmin *webAdmin = NULL;

BZ_GET_PLUGIN_VERSION

BZF_PLUGIN_CALL int bz_Load(const char* commandLine)
{
  if(webAdmin)
    delete(webAdmin);
  webAdmin = new WebAdmin;
  webAdmin->init(commandLine);

  bz_debugMessage(4,"webadmin plugin loaded");
  return 0;
}

BZF_PLUGIN_CALL int bz_Unload(void)
{
  if(webAdmin)
    delete(webAdmin);
  webAdmin = NULL;

  bz_debugMessage(4,"webadmin plugin unloaded");
  return 0;
}

WebAdmin::WebAdmin():BZFSHTTPAuth(),loopPos(0)
{
	registerVDir();

	// add new pages here
	controllers["main"] = &WebAdmin::mainPageCallback;
	controllers["banlist"] = &WebAdmin::banlistPageCallback;
	controllers["helpmsg"] = NULL;
	controllers["group"] = &WebAdmin::groupPageCallback;

  std::map<std::string,page_callback>::iterator pair;
  for(pair = controllers.begin(); pair != controllers.end(); pair++)
    pagenames.push_back(pair->first);
}

void WebAdmin::init(const char* cmdln)
{
  templateSystem.addSearchPath(cmdln ? cmdln : "./");

  // level one has admin perms
  addPermToLevel(1,"ADMIN");

  templateSystem.addIF("IsCurrentPage",this);
  templateSystem.addIF("Error",this);
  templateSystem.addIF("Editing",this);
  templateSystem.addIF("Checked",this);

  templateSystem.addKey("Error",this);
  templateSystem.addKey("Callsign",this);
  templateSystem.addKey("BannedUser",this);
  templateSystem.addKey("PageName",this);
  templateSystem.addKey("HelpMsgName",this);
  templateSystem.addKey("HelpMsgBody",this);
  templateSystem.addKey("GroupName",this);
  templateSystem.addKey("Permission",this);
  templateSystem.addKey("ServerVarName",this);
  templateSystem.addKey("ServerVarValue",this);

  templateSystem.addLoop("Navigation",this);
  templateSystem.addLoop("Players",this);
  templateSystem.addLoop("ServerVars",this);
  templateSystem.addLoop("IPBanList",this);
  templateSystem.addLoop("IDBanList",this);
  templateSystem.addLoop("HelpMsgs",this);
  templateSystem.addLoop("Groups",this);
  templateSystem.addLoop("Permissions", this);

  templateSystem.setPluginName("webadmin", getBaseURL().c_str());

  setupAuth();
}

// event hook for [$Something] in templates
void WebAdmin::keyCallback (std::string &data, const std::string &key)
{
  const std::map<std::string,std::string>::iterator &pair = templateVars.find(key);
  if (pair != templateVars.end())
		data = pair->second;
}

// condition check for [*START] in templates
bool WebAdmin::loopCallback (const std::string &key)
{
  if (key == "players") {
    if (!loopPos) {
      bz_getPlayerIndexList(&players);
      listSize = players.size();
    }
    if (loopPos < listSize) {
      templateVars["playerid"] = players[loopPos];
      templateVars["callsign"] = bz_getPlayerCallsign(players[loopPos++]);
      return true;
    } else players.clear();
  } else if (key == "navigation") {
    if (!loopPos) listSize = pagenames.size();
    if (loopPos < pagenames.size()) {
      templateVars["pagename"] = pagenames[loopPos++];
      return true;
    }
  } else if (key == "permissions") {
    if (!loopPos) listSize = bzu_standardPerms().size();
    if (loopPos < listSize) {
      const std::string &perm = bzu_standardPerms()[loopPos++];
      if (stringList) checked = stringList->contains(perm);
      templateVars["permission"] = perm;
      return true;
    } else delete(stringList);
  } else if (key == "helpmsgs") {
    if (!loopPos) {
      stringList = bz_getHelpTopics();
      listSize = stringList->size();
    }
    if (loopPos < listSize) {
      templateVars["helpmsgname"] = (*stringList)[loopPos++].c_str();
      return true;
    } else delete(stringList);
  } else if (key == "groups") {
    if (!loopPos) {
      stringList = bz_getGroupList();
      listSize = stringList->size();
    }
    if (loopPos < listSize) {
      templateVars["groupname"] = (*stringList)[loopPos++].c_str();
      return true;
    } else delete(stringList);
  } else if (key == "servervars") {
		if (!loopPos) {
			stringList = bz_newStringList();
			listSize = bz_getBZDBVarList(stringList);
		}
    if (loopPos < listSize) {
      const char *varname = (*stringList)[loopPos++].c_str();
      templateVars["servervarname"] = varname;
      templateVars["servervarvalue"] = bz_getBZDBString(varname).c_str();
			return true;
    } else bz_deleteStringList(stringList);
  } else return false;
  return loopPos = 0;
}

// condition check for [?IF] in templates
bool WebAdmin::ifCallback (const std::string &key)
{
  if (key == "iscurrentpage")
    return templateVars["pagename"] == templateVars["currentpage"];
  if (key == "editing")
    return editing;
  if (key == "checked")
    return checked;
  if (key == "error")
    return templateVars.find("error") != templateVars.end();
  return false;
}

bool WebAdmin::handleAuthedRequest ( int level, const HTTPRequest &request, HTTPReply &reply )
{
  std::map<std::string,page_callback>::iterator pair;
  size_t size;
  std::string action, pagename = request.resource;

  reply.returnCode = HTTPReply::e200OK;

  switch(level) {
  case 1:
  case VERIFIED:
    if (pagename.empty()) pagename = "main";
    else {
      size = pagename.size();
      if (size > 0 && pagename[size-1] == '/') pagename.erase(size-1);
    }

    pair = controllers.find(pagename);
    if (pair != controllers.end()) {
      (this->*pair->second)(request);
      if (!templateSystem.processTemplateFile(reply.body, (pagename + ".tmpl").c_str())) {
        reply.returnCode = HTTPReply::e500ServerError;
          if (!templateSystem.processTemplateFile(reply.body, "500.tmpl"))
            reply.body = format("Missing template: %s.tmpl", pagename.c_str());
      }
    } else {
      reply.returnCode = HTTPReply::e404NotFound;
      if (!templateSystem.processTemplateFile(reply.body, "404.tmpl"))
        reply.body = format("No such resource: %s", pagename.c_str());
    }
    break;
  //reply.body = format("Not authenticated(Verified) sessionID %d",request.sessionID);
  default:
    reply.body = format("Not authenticated sessionID %d, access level %d",request.sessionID,level);
  }

  reply.docType = HTTPReply::eHTML;

  templateVars.clear();
  return true;
}

void WebAdmin::mainPageCallback (const HTTPRequest &request)
{
  std::string s1, s2;
  if (request.request != ePost) return;
  std::vector<std::string> v;
  // kick/ban players
  if (request.getParam("players", v)) {
    bool notify = request.getParam("notify", s1);
    request.getParam("reason", s2);
    std::vector<std::string>::iterator i;
    if (request.getParam("kick", s1))
      for (i = v.begin(); i != v.end(); i++)
        bz_kickUser(atoi(i->c_str()), s2.c_str(), notify);
    else if (request.getParam("ipban", v)) {
      request.getParam("duration", s1);
      int duration = atoi(s1.c_str());
      for (i = v.begin(); i != v.end(); i++) {
        int playerID = atoi(i->c_str());
        bz_BasePlayerRecord *player = bz_getPlayerByIndex(playerID);
        bz_IPBanUser(playerID, bz_getPlayerIPAddress(playerID), duration, s2.c_str());
      }
    }
    else if (request.getParam("idban", v)) {
      request.getParam("duration", s1);
      int duration = atoi(s1.c_str());
      for (i = v.begin(); i != v.end(); i++) {
        int playerID = atoi(i->c_str());
        bz_BasePlayerRecord *player = bz_getPlayerByIndex(playerID);
        bz_IPBanUser(playerID, bz_getPlayerCallsign(playerID), duration, s2.c_str());
      }
    }
  }
  // update server vars
  stringList = new bz_APIStringList;
  listSize = bz_getBZDBVarList(stringList);
  for (loopPos = 0; loopPos < listSize; loopPos++) {
    s1 = "var";
    s1 += (*stringList)[loopPos].c_str();
    if (request.getParam(s1, s2))
      bz_setBZDBString((*stringList)[loopPos].c_str(), s2.c_str());
  }
}

void WebAdmin::banlistPageCallback (const HTTPRequest &request)
{
  if (request.request != ePost) return;
  std::vector<std::string> banRemovals;
  std::vector<std::string>::iterator i;
  if (request.getParam("delip", banRemovals))
    for(i = banRemovals.begin(); i != banRemovals.end(); i++)
      bz_IPUnbanUser(i->c_str());
  if (request.getParam("delid", banRemovals))
    for(i = banRemovals.begin(); i != banRemovals.end(); i++)
      bz_IDUnbanUser(i->c_str());
}

void WebAdmin::groupPageCallback (const HTTPRequest &request)
{
  std::string name;
  request.getParam("name", name);
  stringList = bz_getGroupPerms(name.c_str());
  if (!stringList) { // TODO: make a new group instead
    templateVars["error"] = std::string("No such group: ") + name;
    return;
  }
  if (request.request == eGet) {
    templateVars["groupname"] = name;
    editing = true;
  } else if (request.request == ePost) {
    delete(stringList);
    listSize = bzu_standardPerms().size();
    std::string dummy;
    for (loopPos = 0; loopPos < listSize; loopPos++) {
      if (request.getParam(std::string("perm") + bzu_standardPerms()[loopPos], dummy));
        bz_groupAllowPerm(name.c_str(), bzu_standardPerms()[loopPos].c_str());
      // TODO: else remove permission
    }
  }
}

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=2 expandtab
<commit_msg>null method pointer<commit_after>// webadmin.cpp : Defines the entry point for the DLL application.
//

#include "bzfsAPI.h"
#include "plugin_utils.h"
#include "plugin_HTTP.h"
#include <fstream>
#include <cstring>
#include <algorithm>

class WebAdmin : public BZFSHTTPAuth, TemplateCallbackClass
{
public:
  WebAdmin();
  virtual const char * getVDir ( void ){return "webadmin";}
  virtual const char * getDescription ( void ){return "Server Administration (Login Required)";}

  void init (const char *tDir);

  virtual bool handleAuthedRequest ( int level, const HTTPRequest &request, HTTPReply &reply );

  // from TemplateCallbackClass
  virtual void keyCallback (std::string &data, const std::string &key);
  virtual bool loopCallback (const std::string &key);
  virtual bool ifCallback (const std::string &key);

private:
  unsigned int loopPos;
  std::map<std::string,std::string> templateVars;

  typedef void (WebAdmin::*page_callback)(const HTTPRequest &);
  std::map<std::string,page_callback> controllers;
  std::vector<std::string> pagenames;

  void mainPageCallback (const HTTPRequest &request);
  void banlistPageCallback (const HTTPRequest &request);
  void groupPageCallback (const HTTPRequest &request);

  bz_APIIntList players;
  bz_APIStringList *stringList;
  int listSize;

  bool editing, checked;
};

WebAdmin *webAdmin = NULL;

BZ_GET_PLUGIN_VERSION

BZF_PLUGIN_CALL int bz_Load(const char* commandLine)
{
  if(webAdmin)
    delete(webAdmin);
  webAdmin = new WebAdmin;
  webAdmin->init(commandLine);

  bz_debugMessage(4,"webadmin plugin loaded");
  return 0;
}

BZF_PLUGIN_CALL int bz_Unload(void)
{
  if(webAdmin)
    delete(webAdmin);
  webAdmin = NULL;

  bz_debugMessage(4,"webadmin plugin unloaded");
  return 0;
}

WebAdmin::WebAdmin():BZFSHTTPAuth(),loopPos(0)
{
	registerVDir();

	// add new pages here
	controllers["main"] = &WebAdmin::mainPageCallback;
	controllers["banlist"] = &WebAdmin::banlistPageCallback;
	controllers["helpmsg"] = NULL;
	controllers["group"] = &WebAdmin::groupPageCallback;

  std::map<std::string,page_callback>::iterator pair;
  for(pair = controllers.begin(); pair != controllers.end(); pair++)
    pagenames.push_back(pair->first);
}

void WebAdmin::init(const char* cmdln)
{
  templateSystem.addSearchPath(cmdln ? cmdln : "./");

  // level one has admin perms
  addPermToLevel(1,"ADMIN");

  templateSystem.addIF("IsCurrentPage",this);
  templateSystem.addIF("Error",this);
  templateSystem.addIF("Editing",this);
  templateSystem.addIF("Checked",this);

  templateSystem.addKey("Error",this);
  templateSystem.addKey("Callsign",this);
  templateSystem.addKey("BannedUser",this);
  templateSystem.addKey("PageName",this);
  templateSystem.addKey("HelpMsgName",this);
  templateSystem.addKey("HelpMsgBody",this);
  templateSystem.addKey("GroupName",this);
  templateSystem.addKey("Permission",this);
  templateSystem.addKey("ServerVarName",this);
  templateSystem.addKey("ServerVarValue",this);

  templateSystem.addLoop("Navigation",this);
  templateSystem.addLoop("Players",this);
  templateSystem.addLoop("ServerVars",this);
  templateSystem.addLoop("IPBanList",this);
  templateSystem.addLoop("IDBanList",this);
  templateSystem.addLoop("HelpMsgs",this);
  templateSystem.addLoop("Groups",this);
  templateSystem.addLoop("Permissions", this);

  templateSystem.setPluginName("webadmin", getBaseURL().c_str());

  setupAuth();
}

// event hook for [$Something] in templates
void WebAdmin::keyCallback (std::string &data, const std::string &key)
{
  const std::map<std::string,std::string>::iterator &pair = templateVars.find(key);
  if (pair != templateVars.end())
		data = pair->second;
}

// condition check for [*START] in templates
bool WebAdmin::loopCallback (const std::string &key)
{
  if (key == "players") {
    if (!loopPos) {
      bz_getPlayerIndexList(&players);
      listSize = players.size();
    }
    if (loopPos < listSize) {
      templateVars["playerid"] = players[loopPos];
      templateVars["callsign"] = bz_getPlayerCallsign(players[loopPos++]);
      return true;
    } else players.clear();
  } else if (key == "navigation") {
    if (!loopPos) listSize = pagenames.size();
    if (loopPos < pagenames.size()) {
      templateVars["pagename"] = pagenames[loopPos++];
      return true;
    }
  } else if (key == "permissions") {
    if (!loopPos) listSize = bzu_standardPerms().size();
    if (loopPos < listSize) {
      const std::string &perm = bzu_standardPerms()[loopPos++];
      if (stringList) checked = stringList->contains(perm);
      templateVars["permission"] = perm;
      return true;
    } else delete(stringList);
  } else if (key == "helpmsgs") {
    if (!loopPos) {
      stringList = bz_getHelpTopics();
      listSize = stringList->size();
    }
    if (loopPos < listSize) {
      templateVars["helpmsgname"] = (*stringList)[loopPos++].c_str();
      return true;
    } else delete(stringList);
  } else if (key == "groups") {
    if (!loopPos) {
      stringList = bz_getGroupList();
      listSize = stringList->size();
    }
    if (loopPos < listSize) {
      templateVars["groupname"] = (*stringList)[loopPos++].c_str();
      return true;
    } else delete(stringList);
  } else if (key == "servervars") {
		if (!loopPos) {
			stringList = bz_newStringList();
			listSize = bz_getBZDBVarList(stringList);
		}
    if (loopPos < listSize) {
      const char *varname = (*stringList)[loopPos++].c_str();
      templateVars["servervarname"] = varname;
      templateVars["servervarvalue"] = bz_getBZDBString(varname).c_str();
			return true;
    } else bz_deleteStringList(stringList);
  } else return false;
  return loopPos = 0;
}

// condition check for [?IF] in templates
bool WebAdmin::ifCallback (const std::string &key)
{
  if (key == "iscurrentpage")
    return templateVars["pagename"] == templateVars["currentpage"];
  if (key == "editing")
    return editing;
  if (key == "checked")
    return checked;
  if (key == "error")
    return templateVars.find("error") != templateVars.end();
  return false;
}

bool WebAdmin::handleAuthedRequest ( int level, const HTTPRequest &request, HTTPReply &reply )
{
  std::map<std::string,page_callback>::iterator pair;
  size_t size;
  std::string action, pagename = request.resource;

  reply.returnCode = HTTPReply::e200OK;

  switch(level) {
  case 1:
  case VERIFIED:
    if (pagename.empty()) pagename = "main";
    else {
      size = pagename.size();
      if (size > 0 && pagename[size-1] == '/') pagename.erase(size-1);
    }

    pair = controllers.find(pagename);
    if (pair != controllers.end()) {
      if (pair->second) (this->*pair->second)(request);
      if (!templateSystem.processTemplateFile(reply.body, (pagename + ".tmpl").c_str())) {
        reply.returnCode = HTTPReply::e500ServerError;
          if (!templateSystem.processTemplateFile(reply.body, "500.tmpl"))
            reply.body = format("Missing template: %s.tmpl", pagename.c_str());
      }
    } else {
      reply.returnCode = HTTPReply::e404NotFound;
      if (!templateSystem.processTemplateFile(reply.body, "404.tmpl"))
        reply.body = format("No such resource: %s", pagename.c_str());
    }
    break;
  //reply.body = format("Not authenticated(Verified) sessionID %d",request.sessionID);
  default:
    reply.body = format("Not authenticated sessionID %d, access level %d",request.sessionID,level);
  }

  reply.docType = HTTPReply::eHTML;

  templateVars.clear();
  return true;
}

void WebAdmin::mainPageCallback (const HTTPRequest &request)
{
  std::string s1, s2;
  if (request.request != ePost) return;
  std::vector<std::string> v;
  // kick/ban players
  if (request.getParam("players", v)) {
    bool notify = request.getParam("notify", s1);
    request.getParam("reason", s2);
    std::vector<std::string>::iterator i;
    if (request.getParam("kick", s1))
      for (i = v.begin(); i != v.end(); i++)
        bz_kickUser(atoi(i->c_str()), s2.c_str(), notify);
    else if (request.getParam("ipban", v)) {
      request.getParam("duration", s1);
      int duration = atoi(s1.c_str());
      for (i = v.begin(); i != v.end(); i++) {
        int playerID = atoi(i->c_str());
        bz_BasePlayerRecord *player = bz_getPlayerByIndex(playerID);
        bz_IPBanUser(playerID, bz_getPlayerIPAddress(playerID), duration, s2.c_str());
      }
    }
    else if (request.getParam("idban", v)) {
      request.getParam("duration", s1);
      int duration = atoi(s1.c_str());
      for (i = v.begin(); i != v.end(); i++) {
        int playerID = atoi(i->c_str());
        bz_BasePlayerRecord *player = bz_getPlayerByIndex(playerID);
        bz_IPBanUser(playerID, bz_getPlayerCallsign(playerID), duration, s2.c_str());
      }
    }
  }
  // update server vars
  stringList = new bz_APIStringList;
  listSize = bz_getBZDBVarList(stringList);
  for (loopPos = 0; loopPos < listSize; loopPos++) {
    s1 = "var";
    s1 += (*stringList)[loopPos].c_str();
    if (request.getParam(s1, s2))
      bz_setBZDBString((*stringList)[loopPos].c_str(), s2.c_str());
  }
}

void WebAdmin::banlistPageCallback (const HTTPRequest &request)
{
  if (request.request != ePost) return;
  std::vector<std::string> banRemovals;
  std::vector<std::string>::iterator i;
  if (request.getParam("delip", banRemovals))
    for(i = banRemovals.begin(); i != banRemovals.end(); i++)
      bz_IPUnbanUser(i->c_str());
  if (request.getParam("delid", banRemovals))
    for(i = banRemovals.begin(); i != banRemovals.end(); i++)
      bz_IDUnbanUser(i->c_str());
}

void WebAdmin::groupPageCallback (const HTTPRequest &request)
{
  std::string name;
  request.getParam("name", name);
  stringList = bz_getGroupPerms(name.c_str());
  if (!stringList) { // TODO: make a new group instead
    templateVars["error"] = std::string("No such group: ") + name;
    return;
  }
  if (request.request == eGet) {
    templateVars["groupname"] = name;
    editing = true;
  } else if (request.request == ePost) {
    delete(stringList);
    listSize = bzu_standardPerms().size();
    std::string dummy;
    for (loopPos = 0; loopPos < listSize; loopPos++) {
      if (request.getParam(std::string("perm") + bzu_standardPerms()[loopPos], dummy));
        bz_groupAllowPerm(name.c_str(), bzu_standardPerms()[loopPos].c_str());
      // TODO: else remove permission
    }
  }
}

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


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

#include <iomanip>
#include <map>
#include <sstream>
#include <string>
#include <vector>

#include "common/build.hpp"
#include "common/foreach.hpp"
#include "common/json.hpp"
#include "common/logging.hpp"
#include "common/resources.hpp"
#include "common/result.hpp"
#include "common/strings.hpp"
#include "common/type_utils.hpp"
#include "common/utils.hpp"

#include "master/http.hpp"
#include "master/master.hpp"

using process::Future;
using process::HttpResponse;
using process::HttpRequest;

using std::map;
using std::string;
using std::vector;

namespace mesos {
namespace internal {
namespace master {

// TODO(benh): Consider moving the modeling code some place else so
// that it can be shared between slave/http.cpp and master/http.cpp.

// Returns a JSON object modeled on a Resources.
JSON::Object model(const Resources& resources)
{
  // TODO(benh): Add all of the resources.
  Value::Scalar none;
  Value::Scalar cpus = resources.get("cpus", none);
  Value::Scalar mem = resources.get("mem", none);

  JSON::Object object;
  object.values["cpus"] = cpus.value();
  object.values["mem"] = mem.value();

  return object;
}

// Returns a JSON object modeled on a Task.
JSON::Object model(const Task& task)
{
  JSON::Object object;
  object.values["id"] = task.task_id().value();
  object.values["name"] = task.name();
  object.values["framework_id"] = task.framework_id().value();
  object.values["slave_id"] = task.slave_id().value();
  object.values["state"] = TaskState_Name(task.state());
  object.values["resources"] = model(task.resources());
  return object;
}

// Returns a JSON object modeled on an Offer.
JSON::Object model(const Offer& offer)
{
  JSON::Object object;
  object.values["id"] = offer.id().value();
  object.values["framework_id"] = offer.framework_id().value();
  object.values["slave_id"] = offer.slave_id().value();
  object.values["resources"] = model(offer.resources());
  return object;
}

// Returns a JSON object modeled on a Framework.
JSON::Object model(const Framework& framework)
{
  JSON::Object object;
  object.values["id"] = framework.id.value();
  object.values["name"] = framework.info.name();
  object.values["user"] = framework.info.user();
  object.values["registered_time"] = framework.registeredTime;
  object.values["unregistered_time"] = framework.unregisteredTime;
  object.values["active"] = framework.active;
  object.values["resources"] = model(framework.resources);

  // TODO(benh): Consider making reregisteredTime an Option.
  if (framework.registeredTime != framework.reregisteredTime) {
    object.values["reregistered_time"] = framework.reregisteredTime;
  }

  // Model all of the tasks associated with a framework.
  {
    JSON::Array array;
    foreachvalue (Task* task, framework.tasks) {
      array.values.push_back(model(*task));
    }

    object.values["tasks"] = array;
  }

  // Model all of the completed tasks of a framework.
  {
    JSON::Array array;
    foreach (const Task& task, framework.completedTasks) {
      array.values.push_back(model(task));
    }

    object.values["completed_tasks"] = array;
  }

  // Model all of the offers associated with a framework.
  {
    JSON::Array array;
    foreach (Offer* offer, framework.offers) {
      array.values.push_back(model(*offer));
    }

    object.values["offers"] = array;
  }

  return object;
}

// Returns a JSON object modeled after a Slave.
JSON::Object model(const Slave& slave)
{
  JSON::Object object;
  object.values["id"] = slave.id.value();
  object.values["hostname"] = slave.info.hostname();
  object.values["webui_hostname"] = slave.info.webui_hostname();
  object.values["webui_port"] = slave.info.webui_port();
  object.values["registered_time"] = slave.registeredTime;
  object.values["resources"] = model(slave.info.resources());
  return object;
}

namespace http {

Future<HttpResponse> vars(
    const Master& master,
    const HttpRequest& request)
{
  VLOG(1) << "HTTP request for '" << request.path << "'";

  // TODO(benh): Consider separating collecting the actual vars we
  // want to display from rendering them. Trying to just create a
  // map<string, string> required a lot of calls to utils::stringify
  // (or using an std::ostringstream) and didn't actually seem to be
  // that much more clear than just rendering directly.
  std::ostringstream out;

  out <<
    "build_date " << build::DATE << "\n" <<
    "build_user " << build::USER << "\n" <<
    "build_flags " << build::FLAGS << "\n";

  // Also add the configuration values.
  foreachpair (const string& key, const string& value, master.conf.getMap()) {
    out << key << " " << value << "\n";
  }

  HttpOKResponse response;
  response.headers["Content-Type"] = "text/plain";
  response.headers["Content-Length"] = utils::stringify(out.str().size());
  response.body = out.str().data();
  return response;
}

namespace json {

Future<HttpResponse> stats(
    const Master& master,
    const HttpRequest& request)
{
  VLOG(1) << "HTTP request for '" << request.path << "'";

  JSON::Object object;
  object.values["uptime"] = Clock::now() - master.startTime;
  object.values["elected"] = master.elected; // Note: using int not bool.
  object.values["total_schedulers"] = master.frameworks.size();
  object.values["active_schedulers"] = master.getActiveFrameworks().size();
  object.values["activated_slaves"] = master.slaveHostnamePorts.size();
  object.values["connected_slaves"] = master.slaves.size();
  object.values["staged_tasks"] = master.stats.tasks[TASK_STAGING];
  object.values["started_tasks"] = master.stats.tasks[TASK_STARTING];
  object.values["finished_tasks"] = master.stats.tasks[TASK_FINISHED];
  object.values["killed_tasks"] = master.stats.tasks[TASK_KILLED];
  object.values["failed_tasks"] = master.stats.tasks[TASK_FAILED];
  object.values["lost_tasks"] = master.stats.tasks[TASK_LOST];
  object.values["valid_status_updates"] = master.stats.validStatusUpdates;
  object.values["invalid_status_updates"] = master.stats.invalidStatusUpdates;

  // Get total and used (note, not offered) resources in order to
  // compute capacity of scalar resources.
  Resources totalResources;
  Resources usedResources;
  foreach (Slave* slave, master.getActiveSlaves()) {
    totalResources += slave->info.resources();
    usedResources += slave->resourcesInUse;
  }

  foreach (const Resource& resource, totalResources) {
    if (resource.type() == Value::SCALAR) {
      CHECK(resource.has_scalar());
      double total = resource.scalar().value();
      object.values[resource.name() + "_total"] = total;
      Option<Resource> option = usedResources.get(resource);
      CHECK(!option.isSome() || option.get().has_scalar());
      double used = option.isSome() ? option.get().scalar().value() : 0.0;
      object.values[resource.name() + "_used"] = used;
      double percent = used / total;
      object.values[resource.name() + "_percent"] = percent;
    }
  }

  std::ostringstream out;

  JSON::render(out, object);

  HttpOKResponse response;
  response.headers["Content-Type"] = "application/json";
  response.headers["Content-Length"] = utils::stringify(out.str().size());
  response.body = out.str().data();
  return response;
}

Future<HttpResponse> state(
    const Master& master,
    const HttpRequest& request)
{
  VLOG(1) << "HTTP request for '" << request.path << "'";

  JSON::Object object;
  object.values["build_date"] = build::DATE;
  object.values["build_time"] = build::TIME;
  object.values["build_user"] = build::USER;
  object.values["start_time"] = master.startTime;
  object.values["id"] = master.info.id();
  object.values["pid"] = string(master.self());

  // Model all of the slaves.
  {
    JSON::Array array;
    foreachvalue (Slave* slave, master.slaves) {
      array.values.push_back(model(*slave));
    }

    object.values["slaves"] = array;
  }

  // Model all of the frameworks.
  {
    JSON::Array array;
    foreachvalue (Framework* framework, master.frameworks) {
      array.values.push_back(model(*framework));
    }

    object.values["frameworks"] = array;
  }

  // Model all of the completed frameworks.
  {
    JSON::Array array;

    foreach (const Framework& framework, master.completedFrameworks) {
      array.values.push_back(model(framework));
    }

    object.values["completed_frameworks"] = array;
  }

  std::ostringstream out;

  JSON::render(out, object);

  HttpOKResponse response;
  response.headers["Content-Type"] = "application/json";
  response.headers["Content-Length"] = utils::stringify(out.str().size());
  response.body = out.str().data();
  return response;
}

Future<HttpResponse> log(
    const Master& master,
    const HttpRequest& request)
{
  VLOG(1) << "HTTP request for '" << request.path << "'";

  map<string, vector<string> > pairs =
    strings::pairs(request.query, ";&", "=");

  off_t offset = -1;
  ssize_t length = -1;
  string level = pairs.count("level") ? pairs["level"][0] : "INFO";

  if (pairs.count("offset") > 0) {
    CHECK(pairs["offset"].size() > 0);
    Try<off_t> result = utils::numify<off_t>(pairs["offset"].back());
    if (result.isError()) {
      LOG(WARNING) << "Failed to \"numify\" the 'offset' ("
                   << pairs["offset"].back() << "): "
                   << result.error();
      return HttpInternalServerErrorResponse();
    }
    offset = result.get();
  }

  if (pairs.count("length") > 0) {
    CHECK(pairs["length"].size() > 0);
    Try<ssize_t> result = utils::numify<ssize_t>(pairs["length"].back());
    if (result.isError()) {
      LOG(WARNING) << "Failed to \"numify\" the 'length' ("
                   << pairs["length"].back() << "): "
                   << result.error();
      return HttpInternalServerErrorResponse();
    }
    length = result.get();
  }

  string directory = master.conf.get<string>("log_dir", FLAGS_log_dir);
  string path = directory + "/mesos-master." + level;

  Result<int> fd = utils::os::open(path, O_RDONLY);

  if (fd.isError()) {
    LOG(WARNING) << "Failed to open log file at "
                 << path << ": " << fd.error();
    return HttpNotFoundResponse();
  }

  off_t size = lseek(fd.get(), 0, SEEK_END);

  if (size == -1) {
    PLOG(WARNING) << "Failed to seek in the log";
    close(fd.get());
    return HttpInternalServerErrorResponse();
  }

  if (offset == -1) {
    offset = size;
  }

  if (length == -1) {
    length = size - offset;
  }

  JSON::Object object;

  if (offset < size) {
    // Seek to the offset we want to read from.
    if (lseek(fd.get(), offset, SEEK_SET) == -1) {
      PLOG(WARNING) << "Failed to seek in the log";
      close(fd.get());
      return HttpInternalServerErrorResponse();
    }

    // Read length bytes (or to EOF).
    char* temp = new char[length];

    length = ::read(fd.get(), temp, length);

    if (length == 0) {
      object.values["offset"] = offset;
      object.values["length"] = 0;
      delete[] temp;
    } else if (length == -1) {
      PLOG(WARNING) << "Failed to read from the log";
      delete[] temp;
      close(fd.get());
      return HttpInternalServerErrorResponse();
    } else {
      object.values["offset"] = offset;
      object.values["length"] = length;
      object.values["data"] = string(temp, length);
      delete[] temp;
    }
  } else {
    object.values["offset"] = size;
    object.values["length"] = 0;
  }

  close(fd.get());

  std::ostringstream out;

  JSON::render(out, object);

  HttpOKResponse response;
  response.headers["Content-Type"] = "application/json";
  response.headers["Content-Length"] = utils::stringify(out.str().size());
  response.body = out.str().data();
  return response;
}

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

#include <iomanip>
#include <map>
#include <sstream>
#include <string>
#include <vector>

#include "common/build.hpp"
#include "common/foreach.hpp"
#include "common/json.hpp"
#include "common/logging.hpp"
#include "common/resources.hpp"
#include "common/result.hpp"
#include "common/strings.hpp"
#include "common/type_utils.hpp"
#include "common/utils.hpp"

#include "master/http.hpp"
#include "master/master.hpp"

using process::Future;
using process::HttpResponse;
using process::HttpRequest;

using std::map;
using std::string;
using std::vector;

namespace mesos {
namespace internal {
namespace master {

// TODO(benh): Consider moving the modeling code some place else so
// that it can be shared between slave/http.cpp and master/http.cpp.

// Returns a JSON object modeled on a Resources.
JSON::Object model(const Resources& resources)
{
  // TODO(benh): Add all of the resources.
  Value::Scalar none;
  Value::Scalar cpus = resources.get("cpus", none);
  Value::Scalar mem = resources.get("mem", none);

  JSON::Object object;
  object.values["cpus"] = cpus.value();
  object.values["mem"] = mem.value();

  return object;
}

// Returns a JSON object modeled on a Task.
JSON::Object model(const Task& task)
{
  JSON::Object object;
  object.values["id"] = task.task_id().value();
  object.values["name"] = task.name();
  object.values["framework_id"] = task.framework_id().value();
  object.values["slave_id"] = task.slave_id().value();
  object.values["state"] = TaskState_Name(task.state());
  object.values["resources"] = model(task.resources());
  return object;
}

// Returns a JSON object modeled on an Offer.
JSON::Object model(const Offer& offer)
{
  JSON::Object object;
  object.values["id"] = offer.id().value();
  object.values["framework_id"] = offer.framework_id().value();
  object.values["slave_id"] = offer.slave_id().value();
  object.values["resources"] = model(offer.resources());
  return object;
}

// Returns a JSON object modeled on a Framework.
JSON::Object model(const Framework& framework)
{
  JSON::Object object;
  object.values["id"] = framework.id.value();
  object.values["name"] = framework.info.name();
  object.values["user"] = framework.info.user();
  object.values["registered_time"] = framework.registeredTime;
  object.values["unregistered_time"] = framework.unregisteredTime;
  object.values["active"] = framework.active;
  object.values["resources"] = model(framework.resources);

  // TODO(benh): Consider making reregisteredTime an Option.
  if (framework.registeredTime != framework.reregisteredTime) {
    object.values["reregistered_time"] = framework.reregisteredTime;
  }

  // Model all of the tasks associated with a framework.
  {
    JSON::Array array;
    foreachvalue (Task* task, framework.tasks) {
      array.values.push_back(model(*task));
    }

    object.values["tasks"] = array;
  }

  // Model all of the completed tasks of a framework.
  {
    JSON::Array array;
    foreach (const Task& task, framework.completedTasks) {
      array.values.push_back(model(task));
    }

    object.values["completed_tasks"] = array;
  }

  // Model all of the offers associated with a framework.
  {
    JSON::Array array;
    foreach (Offer* offer, framework.offers) {
      array.values.push_back(model(*offer));
    }

    object.values["offers"] = array;
  }

  return object;
}

// Returns a JSON object modeled after a Slave.
JSON::Object model(const Slave& slave)
{
  JSON::Object object;
  object.values["id"] = slave.id.value();
  object.values["hostname"] = slave.info.hostname();
  object.values["webui_hostname"] = slave.info.webui_hostname();
  object.values["webui_port"] = slave.info.webui_port();
  object.values["registered_time"] = slave.registeredTime;
  object.values["resources"] = model(slave.info.resources());
  return object;
}

namespace http {

Future<HttpResponse> vars(
    const Master& master,
    const HttpRequest& request)
{
  VLOG(1) << "HTTP request for '" << request.path << "'";

  // TODO(benh): Consider separating collecting the actual vars we
  // want to display from rendering them. Trying to just create a
  // map<string, string> required a lot of calls to utils::stringify
  // (or using an std::ostringstream) and didn't actually seem to be
  // that much more clear than just rendering directly.
  std::ostringstream out;

  out <<
    "build_date " << build::DATE << "\n" <<
    "build_user " << build::USER << "\n" <<
    "build_flags " << build::FLAGS << "\n";

  // Also add the configuration values.
  foreachpair (const string& key, const string& value, master.conf.getMap()) {
    out << key << " " << value << "\n";
  }

  HttpOKResponse response;
  response.headers["Content-Type"] = "text/plain";
  response.headers["Content-Length"] = utils::stringify(out.str().size());
  response.body = out.str().data();
  return response;
}

namespace json {

Future<HttpResponse> stats(
    const Master& master,
    const HttpRequest& request)
{
  VLOG(1) << "HTTP request for '" << request.path << "'";

  JSON::Object object;
  object.values["uptime"] = Clock::now() - master.startTime;
  object.values["elected"] = master.elected; // Note: using int not bool.
  object.values["total_schedulers"] = master.frameworks.size();
  object.values["active_schedulers"] = master.getActiveFrameworks().size();
  object.values["activated_slaves"] = master.slaveHostnamePorts.size();
  object.values["connected_slaves"] = master.slaves.size();
  object.values["staged_tasks"] = master.stats.tasks[TASK_STAGING];
  object.values["started_tasks"] = master.stats.tasks[TASK_STARTING];
  object.values["finished_tasks"] = master.stats.tasks[TASK_FINISHED];
  object.values["killed_tasks"] = master.stats.tasks[TASK_KILLED];
  object.values["failed_tasks"] = master.stats.tasks[TASK_FAILED];
  object.values["lost_tasks"] = master.stats.tasks[TASK_LOST];
  object.values["valid_status_updates"] = master.stats.validStatusUpdates;
  object.values["invalid_status_updates"] = master.stats.invalidStatusUpdates;

  // Get total and used (note, not offered) resources in order to
  // compute capacity of scalar resources.
  Resources totalResources;
  Resources usedResources;
  foreach (Slave* slave, master.getActiveSlaves()) {
    totalResources += slave->info.resources();
    usedResources += slave->resourcesInUse;
  }

  foreach (const Resource& resource, totalResources) {
    if (resource.type() == Value::SCALAR) {
      CHECK(resource.has_scalar());
      double total = resource.scalar().value();
      object.values[resource.name() + "_total"] = total;
      Option<Resource> option = usedResources.get(resource);
      CHECK(!option.isSome() || option.get().has_scalar());
      double used = option.isSome() ? option.get().scalar().value() : 0.0;
      object.values[resource.name() + "_used"] = used;
      double percent = used / total;
      object.values[resource.name() + "_percent"] = percent;
    }
  }

  std::ostringstream out;

  JSON::render(out, object);

  HttpOKResponse response;
  response.headers["Content-Type"] = "application/json";
  response.headers["Content-Length"] = utils::stringify(out.str().size());
  response.body = out.str().data();
  return response;
}

Future<HttpResponse> state(
    const Master& master,
    const HttpRequest& request)
{
  VLOG(1) << "HTTP request for '" << request.path << "'";

  JSON::Object object;
  object.values["build_date"] = build::DATE;
  object.values["build_time"] = build::TIME;
  object.values["build_user"] = build::USER;
  object.values["start_time"] = master.startTime;
  object.values["id"] = master.info.id();
  object.values["pid"] = string(master.self());

  // Model all of the slaves.
  {
    JSON::Array array;
    foreachvalue (Slave* slave, master.slaves) {
      array.values.push_back(model(*slave));
    }

    object.values["slaves"] = array;
  }

  // Model all of the frameworks.
  {
    JSON::Array array;
    foreachvalue (Framework* framework, master.frameworks) {
      array.values.push_back(model(*framework));
    }

    object.values["frameworks"] = array;
  }

  // Model all of the completed frameworks.
  {
    JSON::Array array;

    foreach (const Framework& framework, master.completedFrameworks) {
      array.values.push_back(model(framework));
    }

    object.values["completed_frameworks"] = array;
  }

  std::ostringstream out;

  JSON::render(out, object);

  HttpOKResponse response;
  response.headers["Content-Type"] = "application/json";
  response.headers["Content-Length"] = utils::stringify(out.str().size());
  response.body = out.str().data();
  return response;
}

Future<HttpResponse> log(
    const Master& master,
    const HttpRequest& request)
{
  VLOG(1) << "HTTP request for '" << request.path << "'";

  map<string, vector<string> > pairs =
    strings::pairs(request.query, ";&", "=");

  off_t offset = -1;
  ssize_t length = -1;
  string level = pairs.count("level") ? pairs["level"][0] : "INFO";

  if (pairs.count("offset") > 0) {
    CHECK(pairs["offset"].size() > 0);
    Try<off_t> result = utils::numify<off_t>(pairs["offset"].back());
    if (result.isError()) {
      LOG(WARNING) << "Failed to \"numify\" the 'offset' ("
                   << pairs["offset"].back() << "): "
                   << result.error();
      return HttpInternalServerErrorResponse();
    }
    offset = result.get();
  }

  if (pairs.count("length") > 0) {
    CHECK(pairs["length"].size() > 0);
    Try<ssize_t> result = utils::numify<ssize_t>(pairs["length"].back());
    if (result.isError()) {
      LOG(WARNING) << "Failed to \"numify\" the 'length' ("
                   << pairs["length"].back() << "): "
                   << result.error();
      return HttpInternalServerErrorResponse();
    }
    length = result.get();
  }

  string directory = master.conf.get<string>("log_dir", FLAGS_log_dir);
  string path = directory + "/mesos-master." + level;

  Try<int> fd = utils::os::open(path, O_RDONLY);

  if (fd.isError()) {
    LOG(WARNING) << "Failed to open log file at "
                 << path << ": " << fd.error();
    return HttpNotFoundResponse();
  }

  off_t size = lseek(fd.get(), 0, SEEK_END);

  if (size == -1) {
    PLOG(WARNING) << "Failed to seek in the log";
    close(fd.get());
    return HttpInternalServerErrorResponse();
  }

  if (offset == -1) {
    offset = size;
  }

  if (length == -1) {
    length = size - offset;
  }

  JSON::Object object;

  if (offset < size) {
    // Seek to the offset we want to read from.
    if (lseek(fd.get(), offset, SEEK_SET) == -1) {
      PLOG(WARNING) << "Failed to seek in the log";
      close(fd.get());
      return HttpInternalServerErrorResponse();
    }

    // Read length bytes (or to EOF).
    char* temp = new char[length];

    length = ::read(fd.get(), temp, length);

    if (length == 0) {
      object.values["offset"] = offset;
      object.values["length"] = 0;
      delete[] temp;
    } else if (length == -1) {
      PLOG(WARNING) << "Failed to read from the log";
      delete[] temp;
      close(fd.get());
      return HttpInternalServerErrorResponse();
    } else {
      object.values["offset"] = offset;
      object.values["length"] = length;
      object.values["data"] = string(temp, length);
      delete[] temp;
    }
  } else {
    object.values["offset"] = size;
    object.values["length"] = 0;
  }

  close(fd.get());

  std::ostringstream out;

  JSON::render(out, object);

  HttpOKResponse response;
  response.headers["Content-Type"] = "application/json";
  response.headers["Content-Length"] = utils::stringify(out.str().size());
  response.body = out.str().data();
  return response;
}

} // namespace json {
} // namespace http {
} // namespace master {
} // namespace internal {
} // namespace mesos {
<|endoftext|>


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

#include <iomanip>
#include <map>
#include <sstream>
#include <string>
#include <vector>

#include <stout/foreach.hpp>
#include <stout/json.hpp>
#include <stout/net.hpp>
#include <stout/numify.hpp>
#include <stout/os.hpp>
#include <stout/result.hpp>
#include <stout/strings.hpp>

#include "common/attributes.hpp"
#include "common/build.hpp"
#include "common/resources.hpp"
#include "common/type_utils.hpp"

#include "logging/logging.hpp"

#include "master/http.hpp"
#include "master/master.hpp"

namespace mesos {
namespace internal {
namespace master {

using process::Future;

using process::http::BadRequest;
using process::http::InternalServerError;
using process::http::NotFound;
using process::http::OK;
using process::http::TemporaryRedirect;
using process::http::Response;
using process::http::Request;

using std::map;
using std::string;
using std::vector;

// TODO(bmahler): Kill these in favor of automatic Proto->JSON Conversion (when
// it becomes available).

// Returns a JSON object modeled on a Resources.
JSON::Object model(const Resources& resources)
{
  JSON::Object object;

  foreach (const Resource& resource, resources) {
    switch (resource.type()) {
      case Value::SCALAR:
        object.values[resource.name()] = resource.scalar().value();
        break;
      case Value::RANGES:
        object.values[resource.name()] = stringify(resource.ranges());
        break;
      case Value::SET:
        object.values[resource.name()] = stringify(resource.set());
        break;
      default:
        LOG(FATAL) << "Unexpected Value type: " << resource.type();
        break;
    }
  }

  return object;
}

JSON::Object model(const Attributes& attributes)
{
  JSON::Object object;

  foreach (const Attribute& attribute, attributes) {
    switch (attribute.type()) {
      case Value::SCALAR:
        object.values[attribute.name()] = attribute.scalar().value();
        break;
      case Value::RANGES:
        object.values[attribute.name()] = stringify(attribute.ranges());
        break;
      case Value::SET:
        object.values[attribute.name()] = stringify(attribute.set());
        break;
      case Value::TEXT:
        object.values[attribute.name()] = attribute.text().value();
        break;
      default:
        LOG(FATAL) << "Unexpected Value type: " << attribute.type();
        break;
    }
  }

  return object;
}

// Returns a JSON object modeled on a Task.
// TODO(bmahler): Expose the executor name / source.
JSON::Object model(const Task& task)
{
  JSON::Object object;
  object.values["id"] = task.task_id().value();
  object.values["name"] = task.name();
  object.values["framework_id"] = task.framework_id().value();
  object.values["executor_id"] = task.executor_id().value();
  object.values["slave_id"] = task.slave_id().value();
  object.values["state"] = TaskState_Name(task.state());
  object.values["resources"] = model(task.resources());
  return object;
}

// Returns a JSON object modeled on an Offer.
JSON::Object model(const Offer& offer)
{
  JSON::Object object;
  object.values["id"] = offer.id().value();
  object.values["framework_id"] = offer.framework_id().value();
  object.values["slave_id"] = offer.slave_id().value();
  object.values["resources"] = model(offer.resources());
  return object;
}

// Returns a JSON object modeled on a Framework.
JSON::Object model(const Framework& framework)
{
  JSON::Object object;
  object.values["id"] = framework.id.value();
  object.values["name"] = framework.info.name();
  object.values["user"] = framework.info.user();
  object.values["registered_time"] = framework.registeredTime;
  object.values["unregistered_time"] = framework.unregisteredTime;
  object.values["active"] = framework.active;
  object.values["resources"] = model(framework.resources);

  // TODO(benh): Consider making reregisteredTime an Option.
  if (framework.registeredTime != framework.reregisteredTime) {
    object.values["reregistered_time"] = framework.reregisteredTime;
  }

  // Model all of the tasks associated with a framework.
  {
    JSON::Array array;
    foreachvalue (Task* task, framework.tasks) {
      array.values.push_back(model(*task));
    }

    object.values["tasks"] = array;
  }

  // Model all of the completed tasks of a framework.
  {
    JSON::Array array;
    foreach (const Task& task, framework.completedTasks) {
      array.values.push_back(model(task));
    }

    object.values["completed_tasks"] = array;
  }

  // Model all of the offers associated with a framework.
  {
    JSON::Array array;
    foreach (Offer* offer, framework.offers) {
      array.values.push_back(model(*offer));
    }

    object.values["offers"] = array;
  }

  return object;
}

// Returns a JSON object modeled after a Slave.
JSON::Object model(const Slave& slave)
{
  JSON::Object object;
  object.values["id"] = slave.id.value();
  object.values["pid"] = string(slave.pid);
  object.values["hostname"] = slave.info.hostname();
  object.values["registered_time"] = slave.registeredTime;
  object.values["resources"] = model(slave.info.resources());
  object.values["attributes"] = model(slave.info.attributes());
  return object;
}

namespace http {

Future<Response> vars(
    const Master& master,
    const Request& request)
{
  VLOG(1) << "HTTP request for '" << request.path << "'";

  // TODO(benh): Consider separating collecting the actual vars we
  // want to display from rendering them. Trying to just create a
  // map<string, string> required a lot of calls to stringify (or
  // using an std::ostringstream) and didn't actually seem to be that
  // much more clear than just rendering directly.
  std::ostringstream out;

  out <<
    "build_date " << build::DATE << "\n" <<
    "build_user " << build::USER << "\n" <<
    "build_flags " << build::FLAGS << "\n";

  // TODO(benh): Output flags.
  return OK(out.str(), request.query.get("jsonp"));
}

Future<Response> redirect(
    const Master& master,
    const Request& request)
{
  VLOG(1) << "HTTP request for '" << request.path << "'";

  // If there's no leader, redirect to this master's base url.
  UPID pid = master.leader != UPID() ? master.leader : master.self();

  Try<string> hostname = net::getHostname(pid.ip);
  if (hostname.isError()) {
    return InternalServerError(hostname.error());
  }

  return TemporaryRedirect(
      "http://" + hostname.get() + ":" + stringify(pid.port));
}

namespace json {

Future<Response> stats(
    const Master& master,
    const Request& request)
{
  VLOG(1) << "HTTP request for '" << request.path << "'";

  JSON::Object object;
  object.values["uptime"] = Clock::now() - master.startTime;
  object.values["elected"] = master.elected; // Note: using int not bool.
  object.values["total_schedulers"] = master.frameworks.size();
  object.values["active_schedulers"] = master.getActiveFrameworks().size();
  object.values["activated_slaves"] = master.slaveHostnamePorts.size();
  object.values["connected_slaves"] = master.slaves.size();
  object.values["staged_tasks"] = master.stats.tasks[TASK_STAGING];
  object.values["started_tasks"] = master.stats.tasks[TASK_STARTING];
  object.values["finished_tasks"] = master.stats.tasks[TASK_FINISHED];
  object.values["killed_tasks"] = master.stats.tasks[TASK_KILLED];
  object.values["failed_tasks"] = master.stats.tasks[TASK_FAILED];
  object.values["lost_tasks"] = master.stats.tasks[TASK_LOST];
  object.values["valid_status_updates"] = master.stats.validStatusUpdates;
  object.values["invalid_status_updates"] = master.stats.invalidStatusUpdates;

  // Get total and used (note, not offered) resources in order to
  // compute capacity of scalar resources.
  Resources totalResources;
  Resources usedResources;
  foreachvalue (Slave* slave, master.slaves) {
    totalResources += slave->info.resources();
    usedResources += slave->resourcesInUse;
  }

  foreach (const Resource& resource, totalResources) {
    if (resource.type() == Value::SCALAR) {
      CHECK(resource.has_scalar());
      double total = resource.scalar().value();
      object.values[resource.name() + "_total"] = total;
      Option<Resource> option = usedResources.get(resource);
      CHECK(!option.isSome() || option.get().has_scalar());
      double used = option.isSome() ? option.get().scalar().value() : 0.0;
      object.values[resource.name() + "_used"] = used;
      double percent = used / total;
      object.values[resource.name() + "_percent"] = percent;
    }
  }

  return OK(object, request.query.get("jsonp"));
}

Future<Response> state(
    const Master& master,
    const Request& request)
{
  VLOG(1) << "HTTP request for '" << request.path << "'";

  JSON::Object object;
  object.values["build_date"] = build::DATE;
  object.values["build_time"] = build::TIME;
  object.values["build_user"] = build::USER;
  object.values["start_time"] = master.startTime;
  object.values["id"] = master.info.id();
  object.values["pid"] = string(master.self());
  object.values["activated_slaves"] = master.slaveHostnamePorts.size();
  object.values["connected_slaves"] = master.slaves.size();
  object.values["staged_tasks"] = master.stats.tasks[TASK_STAGING];
  object.values["started_tasks"] = master.stats.tasks[TASK_STARTING];
  object.values["finished_tasks"] = master.stats.tasks[TASK_FINISHED];
  object.values["killed_tasks"] = master.stats.tasks[TASK_KILLED];
  object.values["failed_tasks"] = master.stats.tasks[TASK_FAILED];
  object.values["lost_tasks"] = master.stats.tasks[TASK_LOST];

  if (master.flags.cluster.isSome()) {
    object.values["cluster"] = master.flags.cluster.get();
  }

  // TODO(benh): Use an Option for the leader PID.
  if (master.leader != UPID()) {
    object.values["leader"] = string(master.leader);
  }

  if (master.flags.log_dir.isSome()) {
    object.values["log_dir"] = master.flags.log_dir.get();
  }

  // Model all of the slaves.
  {
    JSON::Array array;
    foreachvalue (Slave* slave, master.slaves) {
      array.values.push_back(model(*slave));
    }

    object.values["slaves"] = array;
  }

  // Model all of the frameworks.
  {
    JSON::Array array;
    foreachvalue (Framework* framework, master.frameworks) {
      array.values.push_back(model(*framework));
    }

    object.values["frameworks"] = array;
  }

  // Model all of the completed frameworks.
  {
    JSON::Array array;

    foreach (const std::tr1::shared_ptr<Framework>& framework,
             master.completedFrameworks) {
      array.values.push_back(model(*framework));
    }

    object.values["completed_frameworks"] = array;
  }

  return OK(object, request.query.get("jsonp"));
}

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

#include <iomanip>
#include <map>
#include <sstream>
#include <string>
#include <vector>

#include <stout/foreach.hpp>
#include <stout/json.hpp>
#include <stout/net.hpp>
#include <stout/numify.hpp>
#include <stout/os.hpp>
#include <stout/result.hpp>
#include <stout/strings.hpp>

#include "common/attributes.hpp"
#include "common/build.hpp"
#include "common/resources.hpp"
#include "common/type_utils.hpp"

#include "logging/logging.hpp"

#include "master/http.hpp"
#include "master/master.hpp"

namespace mesos {
namespace internal {
namespace master {

using process::Future;

using process::http::BadRequest;
using process::http::InternalServerError;
using process::http::NotFound;
using process::http::OK;
using process::http::TemporaryRedirect;
using process::http::Response;
using process::http::Request;

using std::map;
using std::string;
using std::vector;

// TODO(bmahler): Kill these in favor of automatic Proto->JSON Conversion (when
// it becomes available).

// Returns a JSON object modeled on a Resources.
JSON::Object model(const Resources& resources)
{
  JSON::Object object;

  foreach (const Resource& resource, resources) {
    switch (resource.type()) {
      case Value::SCALAR:
        object.values[resource.name()] = resource.scalar().value();
        break;
      case Value::RANGES:
        object.values[resource.name()] = stringify(resource.ranges());
        break;
      case Value::SET:
        object.values[resource.name()] = stringify(resource.set());
        break;
      default:
        LOG(FATAL) << "Unexpected Value type: " << resource.type();
        break;
    }
  }

  return object;
}

JSON::Object model(const Attributes& attributes)
{
  JSON::Object object;

  foreach (const Attribute& attribute, attributes) {
    switch (attribute.type()) {
      case Value::SCALAR:
        object.values[attribute.name()] = attribute.scalar().value();
        break;
      case Value::RANGES:
        object.values[attribute.name()] = stringify(attribute.ranges());
        break;
      case Value::SET:
        object.values[attribute.name()] = stringify(attribute.set());
        break;
      case Value::TEXT:
        object.values[attribute.name()] = attribute.text().value();
        break;
      default:
        LOG(FATAL) << "Unexpected Value type: " << attribute.type();
        break;
    }
  }

  return object;
}

// Returns a JSON object modeled on a Task.
// TODO(bmahler): Expose the executor name / source.
JSON::Object model(const Task& task)
{
  JSON::Object object;
  object.values["id"] = task.task_id().value();
  object.values["name"] = task.name();
  object.values["framework_id"] = task.framework_id().value();
  object.values["executor_id"] = task.executor_id().value();
  object.values["slave_id"] = task.slave_id().value();
  object.values["state"] = TaskState_Name(task.state());
  object.values["resources"] = model(task.resources());
  return object;
}

// Returns a JSON object modeled on an Offer.
JSON::Object model(const Offer& offer)
{
  JSON::Object object;
  object.values["id"] = offer.id().value();
  object.values["framework_id"] = offer.framework_id().value();
  object.values["slave_id"] = offer.slave_id().value();
  object.values["resources"] = model(offer.resources());
  return object;
}

// Returns a JSON object modeled on a Framework.
JSON::Object model(const Framework& framework)
{
  JSON::Object object;
  object.values["id"] = framework.id.value();
  object.values["name"] = framework.info.name();
  object.values["user"] = framework.info.user();
  object.values["registered_time"] = framework.registeredTime;
  object.values["unregistered_time"] = framework.unregisteredTime;
  object.values["active"] = framework.active;
  object.values["resources"] = model(framework.resources);

  // TODO(benh): Consider making reregisteredTime an Option.
  if (framework.registeredTime != framework.reregisteredTime) {
    object.values["reregistered_time"] = framework.reregisteredTime;
  }

  // Model all of the tasks associated with a framework.
  {
    JSON::Array array;
    foreachvalue (Task* task, framework.tasks) {
      array.values.push_back(model(*task));
    }

    object.values["tasks"] = array;
  }

  // Model all of the completed tasks of a framework.
  {
    JSON::Array array;
    foreach (const Task& task, framework.completedTasks) {
      array.values.push_back(model(task));
    }

    object.values["completed_tasks"] = array;
  }

  // Model all of the offers associated with a framework.
  {
    JSON::Array array;
    foreach (Offer* offer, framework.offers) {
      array.values.push_back(model(*offer));
    }

    object.values["offers"] = array;
  }

  return object;
}

// Returns a JSON object modeled after a Slave.
JSON::Object model(const Slave& slave)
{
  JSON::Object object;
  object.values["id"] = slave.id.value();
  object.values["pid"] = string(slave.pid);
  object.values["hostname"] = slave.info.hostname();
  object.values["registered_time"] = slave.registeredTime;
  object.values["resources"] = model(slave.info.resources());
  object.values["attributes"] = model(slave.info.attributes());
  return object;
}

namespace http {

Future<Response> vars(
    const Master& master,
    const Request& request)
{
  VLOG(1) << "HTTP request for '" << request.path << "'";

  // TODO(benh): Consider separating collecting the actual vars we
  // want to display from rendering them. Trying to just create a
  // map<string, string> required a lot of calls to stringify (or
  // using an std::ostringstream) and didn't actually seem to be that
  // much more clear than just rendering directly.
  std::ostringstream out;

  out <<
    "build_date " << build::DATE << "\n" <<
    "build_user " << build::USER << "\n" <<
    "build_flags " << build::FLAGS << "\n";

  // TODO(benh): Output flags.
  return OK(out.str(), request.query.get("jsonp"));
}

Future<Response> redirect(
    const Master& master,
    const Request& request)
{
  VLOG(1) << "HTTP request for '" << request.path << "'";

  // If there's no leader, redirect to this master's base url.
  UPID pid = master.leader != UPID() ? master.leader : master.self();

  Try<string> hostname = net::getHostname(pid.ip);
  if (hostname.isError()) {
    return InternalServerError(hostname.error());
  }

  return TemporaryRedirect(
      "http://" + hostname.get() + ":" + stringify(pid.port));
}

namespace json {

Future<Response> stats(
    const Master& master,
    const Request& request)
{
  VLOG(1) << "HTTP request for '" << request.path << "'";

  JSON::Object object;
  object.values["uptime"] = Clock::now() - master.startTime;
  object.values["elected"] = master.elected; // Note: using int not bool.
  object.values["total_schedulers"] = master.frameworks.size();
  object.values["active_schedulers"] = master.getActiveFrameworks().size();
  object.values["activated_slaves"] = master.slaveHostnamePorts.size();
  object.values["connected_slaves"] = master.slaves.size();
  object.values["staged_tasks"] = master.stats.tasks[TASK_STAGING];
  object.values["started_tasks"] = master.stats.tasks[TASK_STARTING];
  object.values["finished_tasks"] = master.stats.tasks[TASK_FINISHED];
  object.values["killed_tasks"] = master.stats.tasks[TASK_KILLED];
  object.values["failed_tasks"] = master.stats.tasks[TASK_FAILED];
  object.values["lost_tasks"] = master.stats.tasks[TASK_LOST];
  object.values["valid_status_updates"] = master.stats.validStatusUpdates;
  object.values["invalid_status_updates"] = master.stats.invalidStatusUpdates;
  object.values["outstanding_offers"] = master.offers.size();

  // Get total and used (note, not offered) resources in order to
  // compute capacity of scalar resources.
  Resources totalResources;
  Resources usedResources;
  foreachvalue (Slave* slave, master.slaves) {
    totalResources += slave->info.resources();
    usedResources += slave->resourcesInUse;
  }

  foreach (const Resource& resource, totalResources) {
    if (resource.type() == Value::SCALAR) {
      CHECK(resource.has_scalar());
      double total = resource.scalar().value();
      object.values[resource.name() + "_total"] = total;
      Option<Resource> option = usedResources.get(resource);
      CHECK(!option.isSome() || option.get().has_scalar());
      double used = option.isSome() ? option.get().scalar().value() : 0.0;
      object.values[resource.name() + "_used"] = used;
      double percent = used / total;
      object.values[resource.name() + "_percent"] = percent;
    }
  }

  return OK(object, request.query.get("jsonp"));
}

Future<Response> state(
    const Master& master,
    const Request& request)
{
  VLOG(1) << "HTTP request for '" << request.path << "'";

  JSON::Object object;
  object.values["build_date"] = build::DATE;
  object.values["build_time"] = build::TIME;
  object.values["build_user"] = build::USER;
  object.values["start_time"] = master.startTime;
  object.values["id"] = master.info.id();
  object.values["pid"] = string(master.self());
  object.values["activated_slaves"] = master.slaveHostnamePorts.size();
  object.values["connected_slaves"] = master.slaves.size();
  object.values["staged_tasks"] = master.stats.tasks[TASK_STAGING];
  object.values["started_tasks"] = master.stats.tasks[TASK_STARTING];
  object.values["finished_tasks"] = master.stats.tasks[TASK_FINISHED];
  object.values["killed_tasks"] = master.stats.tasks[TASK_KILLED];
  object.values["failed_tasks"] = master.stats.tasks[TASK_FAILED];
  object.values["lost_tasks"] = master.stats.tasks[TASK_LOST];

  if (master.flags.cluster.isSome()) {
    object.values["cluster"] = master.flags.cluster.get();
  }

  // TODO(benh): Use an Option for the leader PID.
  if (master.leader != UPID()) {
    object.values["leader"] = string(master.leader);
  }

  if (master.flags.log_dir.isSome()) {
    object.values["log_dir"] = master.flags.log_dir.get();
  }

  // Model all of the slaves.
  {
    JSON::Array array;
    foreachvalue (Slave* slave, master.slaves) {
      array.values.push_back(model(*slave));
    }

    object.values["slaves"] = array;
  }

  // Model all of the frameworks.
  {
    JSON::Array array;
    foreachvalue (Framework* framework, master.frameworks) {
      array.values.push_back(model(*framework));
    }

    object.values["frameworks"] = array;
  }

  // Model all of the completed frameworks.
  {
    JSON::Array array;

    foreach (const std::tr1::shared_ptr<Framework>& framework,
             master.completedFrameworks) {
      array.values.push_back(model(*framework));
    }

    object.values["completed_frameworks"] = array;
  }

  return OK(object, request.query.get("jsonp"));
}

} // namespace json {
} // namespace http {
} // namespace master {
} // namespace internal {
} // namespace mesos {
<|endoftext|>


<commit_before>#include <getopt.h>
#include <libgen.h>

#include "configuration.hpp"
#include "master.hpp"
#include "master_webui.hpp"

using std::cerr;
using std::endl;
using boost::lexical_cast;
using boost::bad_lexical_cast;

using namespace nexus::internal::master;

void usage(const char* programName, const Configuration& conf)
{
  cerr << "Usage: " << programName
       << " [--port PORT]"
       << " [--url URL]"
       << " [--allocator ALLOCATOR]"
#ifdef NEXUS_WEBUI
       << " [--webui-port PORT]"
#endif
       << " [--quiet]" << endl
       << endl
       << "URL (used for contending to be a master) may be one of:" << endl
       << "  zoo://host1:port1,host2:port2,..." << endl
       << "  zoofile://file where file contains a host:port pair per line"
       << endl << endl
       << "Option details:" << endl
       << conf.getUsage() << endl;
}

int main(int argc, char **argv)
{
  Configuration conf;
  conf.addOption<string>("url", 'u', "URL used for contending to a master");
  conf.addOption<int>("port", 'p', "Port to listen on");
  conf.addOption<bool>("quiet", 'q', "Disable logging to stderr", false);
  conf.addOption<string>("log_dir", "Where to place logs", "/tmp");
#ifdef NEXUS_WEBUI
  conf.addOption<int>("webui_port", 'w', "Web UI port", 8080);
#endif
  Master::registerOptions(&conf);

  if (argc == 2 && string("--help") == argv[1]) {
    usage(argv[0], conf);
    exit(1);
  }

  Params params;

  try {
    conf.load(argc, argv, true);
    params = conf.getParams();
  } catch (BadOptionValueException& e) {
    cerr << "Invalid value for '" << e.what() << "' option" << endl;
    exit(1);
  } catch (ConfigurationException& e) {
    cerr << "Configuration error: " << e.what() << endl;
    exit(1);
  }

  if (params.contains("port"))
    setenv("LIBPROCESS_PORT", params["port"].c_str(), 1);

  FLAGS_log_dir = params["log_dir"];
  FLAGS_logbufsecs = 1;
  google::InitGoogleLogging(argv[0]);

  bool quiet = params.get<bool>("quiet", false);
  if (!quiet)
    google::SetStderrLogging(google::INFO);

  string url = params.get("url", "");

  LOG(INFO) << "Build: " << BUILD_DATE << " by " << BUILD_USER;
  LOG(INFO) << "Starting Nexus master";

  if (chdir(dirname(argv[0])) != 0)
    fatalerror("Could not chdir into %s", dirname(argv[0]));

  Master *master = new Master(params);
  PID pid = Process::spawn(master);

  MasterDetector *detector = MasterDetector::create(url, pid, true, quiet);

#ifdef NEXUS_WEBUI
  startMasterWebUI(pid, (char*) params["webui_port"].c_str());
#endif

  Process::wait(pid);

  MasterDetector::destroy(detector);

  return 0;
}
<commit_msg>Shortened help message for master<commit_after>#include <getopt.h>
#include <libgen.h>

#include "configuration.hpp"
#include "master.hpp"
#include "master_webui.hpp"

using std::cerr;
using std::endl;
using boost::lexical_cast;
using boost::bad_lexical_cast;

using namespace nexus::internal::master;

void usage(const char* progName, const Configuration& conf)
{
  cerr << "Usage: " << progName << " [--port PORT] [--url URL] [...]" << endl
       << endl
       << "URL (used for contending to be a master) may be one of:" << endl
       << "  zoo://host1:port1,host2:port2,..." << endl
       << "  zoofile://file where file has one host:port pair per line" << endl
       << endl
       << "Supported options:" << endl
       << conf.getUsage();
}

int main(int argc, char **argv)
{
  Configuration conf;
  conf.addOption<string>("url", 'u', "URL used for contending to a master");
  conf.addOption<int>("port", 'p', "Port to listen on");
  conf.addOption<bool>("quiet", 'q', "Disable logging to stderr", false);
  conf.addOption<string>("log_dir", "Where to place logs", "/tmp");
#ifdef NEXUS_WEBUI
  conf.addOption<int>("webui_port", 'w', "Web UI port", 8080);
#endif
  Master::registerOptions(&conf);

  if (argc == 2 && string("--help") == argv[1]) {
    usage(argv[0], conf);
    exit(1);
  }

  Params params;

  try {
    conf.load(argc, argv, true);
    params = conf.getParams();
  } catch (BadOptionValueException& e) {
    cerr << "Invalid value for '" << e.what() << "' option" << endl;
    exit(1);
  } catch (ConfigurationException& e) {
    cerr << "Configuration error: " << e.what() << endl;
    exit(1);
  }

  if (params.contains("port"))
    setenv("LIBPROCESS_PORT", params["port"].c_str(), 1);

  FLAGS_log_dir = params["log_dir"];
  FLAGS_logbufsecs = 1;
  google::InitGoogleLogging(argv[0]);

  bool quiet = params.get<bool>("quiet", false);
  if (!quiet)
    google::SetStderrLogging(google::INFO);

  string url = params.get("url", "");

  LOG(INFO) << "Build: " << BUILD_DATE << " by " << BUILD_USER;
  LOG(INFO) << "Starting Nexus master";

  if (chdir(dirname(argv[0])) != 0)
    fatalerror("Could not chdir into %s", dirname(argv[0]));

  Master *master = new Master(params);
  PID pid = Process::spawn(master);

  MasterDetector *detector = MasterDetector::create(url, pid, true, quiet);

#ifdef NEXUS_WEBUI
  startMasterWebUI(pid, (char*) params["webui_port"].c_str());
#endif

  Process::wait(pid);

  MasterDetector::destroy(detector);

  return 0;
}
<|endoftext|>