<commit_before>/********************************************************************
* Description: emctask.cc
*   Mode and state management for EMC_TASK class
*
*   Derived from a work by Fred Proctor & Will Shackleford
*
* Author:
* License: GPL Version 2
* System: Linux
*
* Copyright (c) 2004 All rights reserved.
*
* Last change:
* $Revision$
* $Author$
* $Date$
********************************************************************/

#include <stdlib.h>
#include <string.h>		// strncpy()
#include <sys/stat.h>		// struct stat
#include <unistd.h>		// stat()

#include "rcs.hh"		// INIFILE
#include "emc.hh"		// EMC NML
#include "emcglb.h"		// EMC_INIFILE
#include "interpl.hh"		// NML_INTERP_LIST, interp_list
#include "canon.hh"		// CANON_VECTOR, GET_PROGRAM_ORIGIN()
#include "rs274ngc.hh"		// the interpreter
#include "rs274ngc_return.hh"	// NCE_FILE_NOT_OPEN

/* flag for how we want to interpret traj coord mode, as mdi or auto */
static int mdiOrAuto = EMC_TASK_MODE_AUTO;

Interp interp;

// EMC_TASK interface

/*
  format string for user-defined programs, e.g., "programs/M1%02d" means
  user-defined programs are in the programs/ directory and are named
  M1XX, where XX is a two-digit string.
*/

static char user_defined_fmt[EMC_SYSTEM_CMD_LEN] = "nc_files/M1%02d";

static void user_defined_add_m_code(int num, double arg1, double arg2)
{
  char fmt[EMC_SYSTEM_CMD_LEN];
  EMC_SYSTEM_CMD system_cmd;

  strcpy(fmt, user_defined_fmt);
  strcat(fmt, " %f %f");
  sprintf(system_cmd.string, fmt, num, arg1, arg2);
  interp_list.append(system_cmd);
}

int emcTaskInit()
{
  int index;
  char path[EMC_SYSTEM_CMD_LEN];
  struct stat buf;
  INIFILE inifile;
  const char * inistring;

  // read out directory where programs are located
  inifile.open(EMC_INIFILE);
  inistring = inifile.find("PROGRAM_PREFIX", "DISPLAY");
  inifile.close();

  // if we have a program prefix, override the default user_defined_fmt
  // string with program prefix, then "M1%02d", e.g.
  // nc_files/M101, where the %%02d means 2 digits after the M code
  // and we need two % to get the literal %
  if (NULL != inistring) {
    sprintf(user_defined_fmt, "%sM1%%02d", inistring);
  }

  /* check for programs named programs/M100 .. programs/M199 and add
     any to the user defined functions list */
  for (index = 0; index < USER_DEFINED_FUNCTION_NUM; index++) {
    sprintf(path, user_defined_fmt, index);
    if (0 == stat(path, &buf)) {
      if (buf.st_mode & S_IXUSR) {
	USER_DEFINED_FUNCTION_ADD(user_defined_add_m_code, index);
	if (EMC_DEBUG & EMC_DEBUG_CONFIG) {
	  rcs_print("emcTaskInit: adding user-defined function %s\n", path);
	}
      } else {
	if (EMC_DEBUG & EMC_DEBUG_CONFIG) {
	  rcs_print("emcTaskInit: user-defined function %s found, but not executable, so ignoring\n", path);
	}
      }
    }
  }

  return 0;
}

int emcTaskHalt()
{
    return 0;
}

int emcTaskAbort()
{
    emcMotionAbort();
    emcIoAbort();

    return 0;
}

int emcTaskSetMode(int mode)
{
    int retval = 0;

    switch (mode) {
    case EMC_TASK_MODE_MANUAL:
	// go to manual mode
	emcTrajSetMode(EMC_TRAJ_MODE_FREE);
	mdiOrAuto = EMC_TASK_MODE_AUTO;	// we'll default back to here
	break;

    case EMC_TASK_MODE_MDI:
	// go to mdi mode
	emcTrajSetMode(EMC_TRAJ_MODE_COORD);
	emcTaskPlanSynch();
	mdiOrAuto = EMC_TASK_MODE_MDI;
	break;

    case EMC_TASK_MODE_AUTO:
	// go to auto mode
	emcTrajSetMode(EMC_TRAJ_MODE_COORD);
	emcTaskPlanSynch();
	mdiOrAuto = EMC_TASK_MODE_AUTO;
	break;

    default:
	retval = -1;
	break;
    }

    return retval;
}

int emcTaskSetState(int state)
{
    int t;
    int retval = 0;

    switch (state) {
    case EMC_TASK_STATE_OFF:
	// turn the machine servos off-- go into ESTOP_RESET state
	for (t = 0; t < emcStatus->motion.traj.axes; t++) {
	    emcAxisDisable(t);
	}
	emcTrajDisable();
	emcLubeOff();
	break;

    case EMC_TASK_STATE_ON:
	// turn the machine servos on
	emcTrajEnable();
	for (t = 0; t < emcStatus->motion.traj.axes; t++) {
	    emcAxisEnable(t);
	}
	emcLubeOn();
	break;

    case EMC_TASK_STATE_ESTOP_RESET:
	// reset the estop
	if (emcStatus->io.aux.estopIn) {
	    rcs_print
		("Can't come out of estop while the estop button is in.");
	}
	emcAuxEstopOff();
	emcLubeOff();
	break;

    case EMC_TASK_STATE_ESTOP:
	// go into estop-- do both IO estop and machine servos off
	emcAuxEstopOn();
	for (t = 0; t < emcStatus->motion.traj.axes; t++) {
	    emcAxisDisable(t);
	}
	emcTrajDisable();
	emcLubeOff();
	break;

    default:
	retval = -1;
	break;
    }

    return retval;
}

// WM access functions

/*
  determineMode()

  Looks at mode of subsystems, and returns associated mode

  Depends on traj mode, and mdiOrAuto flag

  traj mode   mdiOrAuto     mode
  ---------   ---------     ----
  FREE        XXX           MANUAL
  COORD       MDI           MDI
  COORD       AUTO          AUTO
  */
static int determineMode()
{
    // if traj is in free mode, then we're in manual mode
    if (emcStatus->motion.traj.mode == EMC_TRAJ_MODE_FREE ||
	emcStatus->motion.traj.mode == EMC_TRAJ_MODE_TELEOP) {
	return EMC_TASK_MODE_MANUAL;
    }
    // else traj is in coord mode-- we can be in either mdi or auto
    return mdiOrAuto;
}

/*
  determineState()

  Looks at state of subsystems, and returns associated state

  Depends on traj enabled, io estop, and desired task state

  traj enabled   io estop      state
  ------------   --------      -----
  DISABLED       ESTOP         ESTOP
  ENABLED        ESTOP         ESTOP
  DISABLED       OUT OF ESTOP  ESTOP_RESET
  ENABLED        OUT OF ESTOP  ON
  */
static int determineState()
{
    if (emcStatus->io.aux.estop) {
	return EMC_TASK_STATE_ESTOP;
    }

    if (!emcStatus->motion.traj.enabled) {
	return EMC_TASK_STATE_ESTOP_RESET;
    }

    return EMC_TASK_STATE_ON;
}

static int waitFlag = 0;

static char rs274ngc_error_text_buf[LINELEN];
static char rs274ngc_stack_buf[LINELEN];

static void print_rs274ngc_error(int retval)
{
    int index = 0;
    if (retval == 0) {
	return;
    }

    if (0 != emcStatus) {
	emcStatus->task.interpreter_errcode = retval;
    }

    rs274ngc_error_text_buf[0] = 0;
    interp.error_text(retval, rs274ngc_error_text_buf, LINELEN);
    if (0 != rs274ngc_error_text_buf[0]) {
	rcs_print_error("rs274ngc_error: %s\n", rs274ngc_error_text_buf);
    }
    emcOperatorError(0, rs274ngc_error_text_buf);
    index = 0;
    if (EMC_DEBUG & EMC_DEBUG_INTERP) {
	rcs_print("rs274ngc_stack: \t");
	while (index < 5) {
	    rs274ngc_stack_buf[0] = 0;
	    interp.stack_name(index, rs274ngc_stack_buf, LINELEN);
	    if (0 == rs274ngc_stack_buf[0]) {
		break;
	    }
	    rcs_print(" - %s ", rs274ngc_stack_buf);
	    index++;
	}
	rcs_print("\n");
    }
}

int emcTaskPlanInit()
{
    interp.ini_load(EMC_INIFILE);
    waitFlag = 0;

    int retval = interp.init();
    if (retval > RS274NGC_MIN_ERROR) {
	print_rs274ngc_error(retval);
    } else {
	if (0 != RS274NGC_STARTUP_CODE[0]) {
	    retval = interp.execute(RS274NGC_STARTUP_CODE);
	    if (retval > RS274NGC_MIN_ERROR) {
		print_rs274ngc_error(retval);
	    }
	}
    }
    return retval;
}

int emcTaskPlanSetWait()
{
    waitFlag = 1;

    return 0;
}

int emcTaskPlanIsWait()
{
    return waitFlag;
}

int emcTaskPlanClearWait()
{
    waitFlag = 0;

    return 0;
}

int emcTaskPlanSynch()
{
    return interp.synch();
}

int emcTaskPlanExit()
{
    return interp.exit();
}

int emcTaskPlanOpen(const char *file)
{
    if (emcStatus != 0) {
	emcStatus->task.motionLine = 0;
	emcStatus->task.currentLine = 0;
	emcStatus->task.readLine = 0;
    }

    int retval = interp.open(file);
    if (retval > RS274NGC_MIN_ERROR) {
	print_rs274ngc_error(retval);
	return retval;
    }
    taskplanopen = 1;
    return retval;
}

int emcTaskPlanRead()
{
    int retval = interp.read();
    if (retval == NCE_FILE_NOT_OPEN) {
	if (emcStatus->task.file[0] != 0) {
	    retval = interp.open(emcStatus->task.file);
	    if (retval > RS274NGC_MIN_ERROR) {
		print_rs274ngc_error(retval);
	    }
	    retval = interp.read();
	}
    }
    if (retval > RS274NGC_MIN_ERROR) {
	print_rs274ngc_error(retval);
    }
    return retval;
}

int emcTaskPlanExecute(const char *command)
{
    int inpos = emcStatus->motion.traj.inpos; // 1 if in position, 0 if not.

    if(command != 0){ // Command is 0 if in AUTO mode, non-null if in MDI mode.
        // Don't sync if not in position.
        if ((*command != 0)  && (inpos)){
            interp.synch();
        }
    }
    int retval = interp.execute(command);
    if (retval > RS274NGC_MIN_ERROR) {
	print_rs274ngc_error(retval);
    }
    return retval;
}

int emcTaskPlanClose()
{
    int retval = interp.close();
    if (retval > RS274NGC_MIN_ERROR) {
	print_rs274ngc_error(retval);
    }

    taskplanopen = 0;
    return retval;
}

int emcTaskPlanLine()
{
    return interp.line();
}

int emcTaskPlanCommand(char *cmd)
{
    char buf[LINELEN];

    strcpy(cmd, interp.command(buf, LINELEN));
    return 0;
}

int emcTaskUpdate(EMC_TASK_STAT * stat)
{
    stat->mode = (enum EMC_TASK_MODE_ENUM) determineMode();
    stat->state = (enum EMC_TASK_STATE_ENUM) determineState();

    // execState set in main
    // interpState set in main
    if (emcStatus->motion.traj.id > 0) {
	stat->motionLine = emcStatus->motion.traj.id;
    }
    // currentLine set in main
    // readLine set in main

    char buf[LINELEN];
    strcpy(stat->file, interp.file(buf, LINELEN));
    // command set in main

    // update active G and M codes
    interp.active_g_codes(&stat->activeGCodes[0]);
    interp.active_m_codes(&stat->activeMCodes[0]);
    interp.active_settings(&stat->activeSettings[0]);

    stat->heartbeat++;

    return 0;
}

/*
  Modification history:

  $Log$
  Revision 1.9  2005/06/12 21:46:35  paul_c
  Lost the rs274ngc_ prefix from all the public interpreter calls - This will allow canterp & other (as yet unwritten) interpreters to use a common API.

  Revision 1.8  2005/05/23 01:54:51  paul_c
  Missed a few files in the last effort....

  Revision 1.7  2005/05/23 00:29:13  paul_c
  Remove any last trace of those M$ line terminators

  Revision 1.6  2005/05/18 22:48:59  rumley
  Fix for Bug 1171692, Odd behavoir in MDI mode.
  Caused by rs274ngc_synch call when axis not 'inpos'

  Revision 1.5  2005/05/04 04:50:38  jmkasunich
  Merged Pauls work from the lathe_fork branch.  Compiles cleanly but completely untested.  Changes include: G33 parsing, breaking interp into smaller files, using a C++ class for the interp, using LINELEN instead of many #defines for buffer lengths, and more

  Revision 1.4  2005/04/27 20:05:47  proctor
  Added user-defined M codes, from BDI-4

*/
<commit_msg>Convert rs274ngc error printing to a more generic form.<commit_after>/********************************************************************
* Description: emctask.cc
*   Mode and state management for EMC_TASK class
*
*   Derived from a work by Fred Proctor & Will Shackleford
*
* Author:
* License: GPL Version 2
* System: Linux
*
* Copyright (c) 2004 All rights reserved.
*
* Last change:
* $Revision$
* $Author$
* $Date$
********************************************************************/

#include <stdlib.h>
#include <string.h>		// strncpy()
#include <sys/stat.h>		// struct stat
#include <unistd.h>		// stat()

#include "rcs.hh"		// INIFILE
#include "emc.hh"		// EMC NML
#include "emcglb.h"		// EMC_INIFILE
#include "interpl.hh"		// NML_INTERP_LIST, interp_list
#include "canon.hh"		// CANON_VECTOR, GET_PROGRAM_ORIGIN()
#include "rs274ngc.hh"		// the interpreter
#include "rs274ngc_return.hh"	// NCE_FILE_NOT_OPEN

/* flag for how we want to interpret traj coord mode, as mdi or auto */
static int mdiOrAuto = EMC_TASK_MODE_AUTO;

Interp interp;

// EMC_TASK interface

/*
  format string for user-defined programs, e.g., "programs/M1%02d" means
  user-defined programs are in the programs/ directory and are named
  M1XX, where XX is a two-digit string.
*/

static char user_defined_fmt[EMC_SYSTEM_CMD_LEN] = "nc_files/M1%02d";

static void user_defined_add_m_code(int num, double arg1, double arg2)
{
  char fmt[EMC_SYSTEM_CMD_LEN];
  EMC_SYSTEM_CMD system_cmd;

  strcpy(fmt, user_defined_fmt);
  strcat(fmt, " %f %f");
  sprintf(system_cmd.string, fmt, num, arg1, arg2);
  interp_list.append(system_cmd);
}

int emcTaskInit()
{
  int index;
  char path[EMC_SYSTEM_CMD_LEN];
  struct stat buf;
  INIFILE inifile;
  const char * inistring;

  // read out directory where programs are located
  inifile.open(EMC_INIFILE);
  inistring = inifile.find("PROGRAM_PREFIX", "DISPLAY");
  inifile.close();

  // if we have a program prefix, override the default user_defined_fmt
  // string with program prefix, then "M1%02d", e.g.
  // nc_files/M101, where the %%02d means 2 digits after the M code
  // and we need two % to get the literal %
  if (NULL != inistring) {
    sprintf(user_defined_fmt, "%sM1%%02d", inistring);
  }

  /* check for programs named programs/M100 .. programs/M199 and add
     any to the user defined functions list */
  for (index = 0; index < USER_DEFINED_FUNCTION_NUM; index++) {
    sprintf(path, user_defined_fmt, index);
    if (0 == stat(path, &buf)) {
      if (buf.st_mode & S_IXUSR) {
	USER_DEFINED_FUNCTION_ADD(user_defined_add_m_code, index);
	if (EMC_DEBUG & EMC_DEBUG_CONFIG) {
	  rcs_print("emcTaskInit: adding user-defined function %s\n", path);
	}
      } else {
	if (EMC_DEBUG & EMC_DEBUG_CONFIG) {
	  rcs_print("emcTaskInit: user-defined function %s found, but not executable, so ignoring\n", path);
	}
      }
    }
  }

  return 0;
}

int emcTaskHalt()
{
    return 0;
}

int emcTaskAbort()
{
    emcMotionAbort();
    emcIoAbort();

    return 0;
}

int emcTaskSetMode(int mode)
{
    int retval = 0;

    switch (mode) {
    case EMC_TASK_MODE_MANUAL:
	// go to manual mode
	emcTrajSetMode(EMC_TRAJ_MODE_FREE);
	mdiOrAuto = EMC_TASK_MODE_AUTO;	// we'll default back to here
	break;

    case EMC_TASK_MODE_MDI:
	// go to mdi mode
	emcTrajSetMode(EMC_TRAJ_MODE_COORD);
	emcTaskPlanSynch();
	mdiOrAuto = EMC_TASK_MODE_MDI;
	break;

    case EMC_TASK_MODE_AUTO:
	// go to auto mode
	emcTrajSetMode(EMC_TRAJ_MODE_COORD);
	emcTaskPlanSynch();
	mdiOrAuto = EMC_TASK_MODE_AUTO;
	break;

    default:
	retval = -1;
	break;
    }

    return retval;
}

int emcTaskSetState(int state)
{
    int t;
    int retval = 0;

    switch (state) {
    case EMC_TASK_STATE_OFF:
	// turn the machine servos off-- go into ESTOP_RESET state
	for (t = 0; t < emcStatus->motion.traj.axes; t++) {
	    emcAxisDisable(t);
	}
	emcTrajDisable();
	emcLubeOff();
	break;

    case EMC_TASK_STATE_ON:
	// turn the machine servos on
	emcTrajEnable();
	for (t = 0; t < emcStatus->motion.traj.axes; t++) {
	    emcAxisEnable(t);
	}
	emcLubeOn();
	break;

    case EMC_TASK_STATE_ESTOP_RESET:
	// reset the estop
	if (emcStatus->io.aux.estopIn) {
	    rcs_print
		("Can't come out of estop while the estop button is in.");
	}
	emcAuxEstopOff();
	emcLubeOff();
	break;

    case EMC_TASK_STATE_ESTOP:
	// go into estop-- do both IO estop and machine servos off
	emcAuxEstopOn();
	for (t = 0; t < emcStatus->motion.traj.axes; t++) {
	    emcAxisDisable(t);
	}
	emcTrajDisable();
	emcLubeOff();
	break;

    default:
	retval = -1;
	break;
    }

    return retval;
}

// WM access functions

/*
  determineMode()

  Looks at mode of subsystems, and returns associated mode

  Depends on traj mode, and mdiOrAuto flag

  traj mode   mdiOrAuto     mode
  ---------   ---------     ----
  FREE        XXX           MANUAL
  COORD       MDI           MDI
  COORD       AUTO          AUTO
  */
static int determineMode()
{
    // if traj is in free mode, then we're in manual mode
    if (emcStatus->motion.traj.mode == EMC_TRAJ_MODE_FREE ||
	emcStatus->motion.traj.mode == EMC_TRAJ_MODE_TELEOP) {
	return EMC_TASK_MODE_MANUAL;
    }
    // else traj is in coord mode-- we can be in either mdi or auto
    return mdiOrAuto;
}

/*
  determineState()

  Looks at state of subsystems, and returns associated state

  Depends on traj enabled, io estop, and desired task state

  traj enabled   io estop      state
  ------------   --------      -----
  DISABLED       ESTOP         ESTOP
  ENABLED        ESTOP         ESTOP
  DISABLED       OUT OF ESTOP  ESTOP_RESET
  ENABLED        OUT OF ESTOP  ON
  */
static int determineState()
{
    if (emcStatus->io.aux.estop) {
	return EMC_TASK_STATE_ESTOP;
    }

    if (!emcStatus->motion.traj.enabled) {
	return EMC_TASK_STATE_ESTOP_RESET;
    }

    return EMC_TASK_STATE_ON;
}

static int waitFlag = 0;

static char interp_error_text_buf[LINELEN];
static char interp_stack_buf[LINELEN];

static void print_interp_error(int retval)
{
    int index = 0;
    if (retval == 0) {
	return;
    }

    if (0 != emcStatus) {
	emcStatus->task.interpreter_errcode = retval;
    }

    interp_error_text_buf[0] = 0;
    interp.error_text(retval, interp_error_text_buf, LINELEN);
    if (0 != interp_error_text_buf[0]) {
	rcs_print_error("interp_error: %s\n", interp_error_text_buf);
    }
    emcOperatorError(0, interp_error_text_buf);
    index = 0;
    if (EMC_DEBUG & EMC_DEBUG_INTERP) {
	rcs_print("Interpreter stack: \t");
	while (index < 5) {
	    interp_stack_buf[0] = 0;
	    interp.stack_name(index, interp_stack_buf, LINELEN);
	    if (0 == interp_stack_buf[0]) {
		break;
	    }
	    rcs_print(" - %s ", interp_stack_buf);
	    index++;
	}
	rcs_print("\n");
    }
}

int emcTaskPlanInit()
{
    interp.ini_load(EMC_INIFILE);
    waitFlag = 0;

    int retval = interp.init();
    if (retval > RS274NGC_MIN_ERROR) {
	print_interp_error(retval);
    } else {
	if (0 != RS274NGC_STARTUP_CODE[0]) {
	    retval = interp.execute(RS274NGC_STARTUP_CODE);
	    if (retval > RS274NGC_MIN_ERROR) {
		print_interp_error(retval);
	    }
	}
    }
    return retval;
}

int emcTaskPlanSetWait()
{
    waitFlag = 1;

    return 0;
}

int emcTaskPlanIsWait()
{
    return waitFlag;
}

int emcTaskPlanClearWait()
{
    waitFlag = 0;

    return 0;
}

int emcTaskPlanSynch()
{
    return interp.synch();
}

int emcTaskPlanExit()
{
    return interp.exit();
}

int emcTaskPlanOpen(const char *file)
{
    if (emcStatus != 0) {
	emcStatus->task.motionLine = 0;
	emcStatus->task.currentLine = 0;
	emcStatus->task.readLine = 0;
    }

    int retval = interp.open(file);
    if (retval > RS274NGC_MIN_ERROR) {
	print_interp_error(retval);
	return retval;
    }
    taskplanopen = 1;
    return retval;
}

int emcTaskPlanRead()
{
    int retval = interp.read();
    if (retval == NCE_FILE_NOT_OPEN) {
	if (emcStatus->task.file[0] != 0) {
	    retval = interp.open(emcStatus->task.file);
	    if (retval > RS274NGC_MIN_ERROR) {
		print_interp_error(retval);
	    }
	    retval = interp.read();
	}
    }
    if (retval > RS274NGC_MIN_ERROR) {
	print_interp_error(retval);
    }
    return retval;
}

int emcTaskPlanExecute(const char *command)
{
    int inpos = emcStatus->motion.traj.inpos; // 1 if in position, 0 if not.

    if(command != 0){ // Command is 0 if in AUTO mode, non-null if in MDI mode.
        // Don't sync if not in position.
        if ((*command != 0)  && (inpos)){
            interp.synch();
        }
    }
    int retval = interp.execute(command);
    if (retval > RS274NGC_MIN_ERROR) {
	print_interp_error(retval);
    }
    return retval;
}

int emcTaskPlanClose()
{
    int retval = interp.close();
    if (retval > RS274NGC_MIN_ERROR) {
	print_interp_error(retval);
    }

    taskplanopen = 0;
    return retval;
}

int emcTaskPlanLine()
{
    return interp.line();
}

int emcTaskPlanCommand(char *cmd)
{
    char buf[LINELEN];

    strcpy(cmd, interp.command(buf, LINELEN));
    return 0;
}

int emcTaskUpdate(EMC_TASK_STAT * stat)
{
    stat->mode = (enum EMC_TASK_MODE_ENUM) determineMode();
    stat->state = (enum EMC_TASK_STATE_ENUM) determineState();

    // execState set in main
    // interpState set in main
    if (emcStatus->motion.traj.id > 0) {
	stat->motionLine = emcStatus->motion.traj.id;
    }
    // currentLine set in main
    // readLine set in main

    char buf[LINELEN];
    strcpy(stat->file, interp.file(buf, LINELEN));
    // command set in main

    // update active G and M codes
    interp.active_g_codes(&stat->activeGCodes[0]);
    interp.active_m_codes(&stat->activeMCodes[0]);
    interp.active_settings(&stat->activeSettings[0]);

    stat->heartbeat++;

    return 0;
}

/*
  Modification history:

  $Log$
  Revision 1.10  2005/06/12 22:07:56  paul_c
  Convert rs274ngc error printing to a more generic form.

  Revision 1.9  2005/06/12 21:46:35  paul_c
  Lost the rs274ngc_ prefix from all the public interpreter calls - This will allow canterp & other (as yet unwritten) interpreters to use a common API.

  Revision 1.8  2005/05/23 01:54:51  paul_c
  Missed a few files in the last effort....

  Revision 1.7  2005/05/23 00:29:13  paul_c
  Remove any last trace of those M$ line terminators

  Revision 1.6  2005/05/18 22:48:59  rumley
  Fix for Bug 1171692, Odd behavoir in MDI mode.
  Caused by rs274ngc_synch call when axis not 'inpos'

  Revision 1.5  2005/05/04 04:50:38  jmkasunich
  Merged Pauls work from the lathe_fork branch.  Compiles cleanly but completely untested.  Changes include: G33 parsing, breaking interp into smaller files, using a C++ class for the interp, using LINELEN instead of many #defines for buffer lengths, and more

  Revision 1.4  2005/04/27 20:05:47  proctor
  Added user-defined M codes, from BDI-4

*/
<|endoftext|>


<commit_before>// ***************************************************************************
//
//   Generated automatically by genwrapper.
//   Please DO NOT EDIT this file!
//
// ***************************************************************************

#include <osgIntrospection/ReflectionMacros>
#include <osgIntrospection/TypedMethodInfo>
#include <osgIntrospection/StaticMethodInfo>
#include <osgIntrospection/Attributes>

#include <osg/CoordinateSystemNode>
#include <osg/CopyOp>
#include <osg/Object>
#include <osg/Vec3d>
#include <osgTerrain/Locator>

// Must undefine IN and OUT macros defined in Windows headers
#ifdef IN
#undef IN
#endif
#ifdef OUT
#undef OUT
#endif

BEGIN_OBJECT_REFLECTOR(osgTerrain::EllipsoidLocator)
	I_BaseType(osgTerrain::Locator);
	I_ConstructorWithDefaults5(IN, double, longitude, , IN, double, latitude, , IN, double, deltaLongitude, , IN, double, deltaLatitude, , IN, double, height, 0.0,
	                           ____EllipsoidLocator__double__double__double__double__double,
	                           "",
	                           "");
	I_MethodWithDefaults5(void, setExtents, IN, double, longitude, , IN, double, latitude, , IN, double, deltaLongitude, , IN, double, deltaLatitude, , IN, double, height, 0.0,
	                      Properties::NON_VIRTUAL,
	                      __void__setExtents__double__double__double__double__double,
	                      "",
	                      "");
	I_Method0(double, getLongitude,
	          Properties::NON_VIRTUAL,
	          __double__getLongitude,
	          "",
	          "");
	I_Method0(double, getDeltaLongitude,
	          Properties::NON_VIRTUAL,
	          __double__getDeltaLongitude,
	          "",
	          "");
	I_Method0(double, getLatitude,
	          Properties::NON_VIRTUAL,
	          __double__getLatitude,
	          "",
	          "");
	I_Method0(double, getDeltaLatitude,
	          Properties::NON_VIRTUAL,
	          __double__getDeltaLatitude,
	          "",
	          "");
	I_Method0(double, getHeight,
	          Properties::NON_VIRTUAL,
	          __double__getHeight,
	          "",
	          "");
	I_Method0(osg::EllipsoidModel *, getEllipsoidModel,
	          Properties::NON_VIRTUAL,
	          __osg_EllipsoidModel_P1__getEllipsoidModel,
	          "",
	          "");
	I_Method0(const osg::EllipsoidModel *, getEllipsoidModel,
	          Properties::NON_VIRTUAL,
	          __C5_osg_EllipsoidModel_P1__getEllipsoidModel,
	          "",
	          "");
	I_Method2(bool, convertLocalToModel, IN, const osg::Vec3d &, local, IN, osg::Vec3d &, world,
	          Properties::VIRTUAL,
	          __bool__convertLocalToModel__C5_osg_Vec3d_R1__osg_Vec3d_R1,
	          "",
	          "");
	I_Method2(bool, convertModelToWorld, IN, const osg::Vec3d &, world, IN, osg::Vec3d &, local,
	          Properties::VIRTUAL,
	          __bool__convertModelToWorld__C5_osg_Vec3d_R1__osg_Vec3d_R1,
	          "",
	          "");
	I_SimpleProperty(double, DeltaLatitude,
	                 __double__getDeltaLatitude,
	                 0);
	I_SimpleProperty(double, DeltaLongitude,
	                 __double__getDeltaLongitude,
	                 0);
	I_SimpleProperty(osg::EllipsoidModel *, EllipsoidModel,
	                 __osg_EllipsoidModel_P1__getEllipsoidModel,
	                 0);
	I_SimpleProperty(double, Height,
	                 __double__getHeight,
	                 0);
	I_SimpleProperty(double, Latitude,
	                 __double__getLatitude,
	                 0);
	I_SimpleProperty(double, Longitude,
	                 __double__getLongitude,
	                 0);
END_REFLECTOR

BEGIN_OBJECT_REFLECTOR(osgTerrain::Locator)
	I_BaseType(osg::Object);
	I_Constructor0(____Locator,
	               "",
	               "");
	I_ConstructorWithDefaults2(IN, const osgTerrain::Locator &, x, , IN, const osg::CopyOp &, copyop, osg::CopyOp::SHALLOW_COPY,
	                           ____Locator__C5_Locator_R1__C5_osg_CopyOp_R1,
	                           "Copy constructor using CopyOp to manage deep vs shallow copy. ",
	                           "");
	I_Method0(osg::Object *, cloneType,
	          Properties::VIRTUAL,
	          __osg_Object_P1__cloneType,
	          "Clone the type of an object, with Object* return type. ",
	          "Must be defined by derived classes. ");
	I_Method1(osg::Object *, clone, IN, const osg::CopyOp &, copyop,
	          Properties::VIRTUAL,
	          __osg_Object_P1__clone__C5_osg_CopyOp_R1,
	          "Clone an object, with Object* return type. ",
	          "Must be defined by derived classes. ");
	I_Method1(bool, isSameKindAs, IN, const osg::Object *, obj,
	          Properties::VIRTUAL,
	          __bool__isSameKindAs__C5_osg_Object_P1,
	          "",
	          "");
	I_Method0(const char *, libraryName,
	          Properties::VIRTUAL,
	          __C5_char_P1__libraryName,
	          "return the name of the object's library. ",
	          "Must be defined by derived classes. The OpenSceneGraph convention is that the namespace of a library is the same as the library name. ");
	I_Method0(const char *, className,
	          Properties::VIRTUAL,
	          __C5_char_P1__className,
	          "return the name of the object's class type. ",
	          "Must be defined by derived classes. ");
	I_Method2(bool, convertLocalToModel, IN, const osg::Vec3d &, x, IN, osg::Vec3d &, x,
	          Properties::VIRTUAL,
	          __bool__convertLocalToModel__C5_osg_Vec3d_R1__osg_Vec3d_R1,
	          "",
	          "");
	I_Method2(bool, convertModelToWorld, IN, const osg::Vec3d &, x, IN, osg::Vec3d &, x,
	          Properties::VIRTUAL,
	          __bool__convertModelToWorld__C5_osg_Vec3d_R1__osg_Vec3d_R1,
	          "",
	          "");
END_REFLECTOR

<commit_msg>Updated wrappers<commit_after>// ***************************************************************************
//
//   Generated automatically by genwrapper.
//   Please DO NOT EDIT this file!
//
// ***************************************************************************

#include <osgIntrospection/ReflectionMacros>
#include <osgIntrospection/TypedMethodInfo>
#include <osgIntrospection/StaticMethodInfo>
#include <osgIntrospection/Attributes>

#include <osg/CoordinateSystemNode>
#include <osg/CopyOp>
#include <osg/Object>
#include <osg/Vec3d>
#include <osgTerrain/Locator>

// Must undefine IN and OUT macros defined in Windows headers
#ifdef IN
#undef IN
#endif
#ifdef OUT
#undef OUT
#endif

BEGIN_OBJECT_REFLECTOR(osgTerrain::EllipsoidLocator)
	I_BaseType(osgTerrain::Locator);
	I_ConstructorWithDefaults5(IN, double, longitude, , IN, double, latitude, , IN, double, deltaLongitude, , IN, double, deltaLatitude, , IN, double, height, 0.0,
	                           ____EllipsoidLocator__double__double__double__double__double,
	                           "",
	                           "");
	I_MethodWithDefaults5(void, setExtents, IN, double, longitude, , IN, double, latitude, , IN, double, deltaLongitude, , IN, double, deltaLatitude, , IN, double, height, 0.0,
	                      Properties::NON_VIRTUAL,
	                      __void__setExtents__double__double__double__double__double,
	                      "",
	                      "");
	I_Method0(double, getLongitude,
	          Properties::NON_VIRTUAL,
	          __double__getLongitude,
	          "",
	          "");
	I_Method0(double, getDeltaLongitude,
	          Properties::NON_VIRTUAL,
	          __double__getDeltaLongitude,
	          "",
	          "");
	I_Method0(double, getLatitude,
	          Properties::NON_VIRTUAL,
	          __double__getLatitude,
	          "",
	          "");
	I_Method0(double, getDeltaLatitude,
	          Properties::NON_VIRTUAL,
	          __double__getDeltaLatitude,
	          "",
	          "");
	I_Method0(double, getHeight,
	          Properties::NON_VIRTUAL,
	          __double__getHeight,
	          "",
	          "");
	I_Method0(osg::EllipsoidModel *, getEllipsoidModel,
	          Properties::NON_VIRTUAL,
	          __osg_EllipsoidModel_P1__getEllipsoidModel,
	          "",
	          "");
	I_Method0(const osg::EllipsoidModel *, getEllipsoidModel,
	          Properties::NON_VIRTUAL,
	          __C5_osg_EllipsoidModel_P1__getEllipsoidModel,
	          "",
	          "");
	I_Method2(bool, convertLocalToModel, IN, const osg::Vec3d &, local, IN, osg::Vec3d &, world,
	          Properties::VIRTUAL,
	          __bool__convertLocalToModel__C5_osg_Vec3d_R1__osg_Vec3d_R1,
	          "",
	          "");
	I_Method2(bool, convertModelToLocal, IN, const osg::Vec3d &, world, IN, osg::Vec3d &, local,
	          Properties::VIRTUAL,
	          __bool__convertModelToLocal__C5_osg_Vec3d_R1__osg_Vec3d_R1,
	          "",
	          "");
	I_SimpleProperty(double, DeltaLatitude,
	                 __double__getDeltaLatitude,
	                 0);
	I_SimpleProperty(double, DeltaLongitude,
	                 __double__getDeltaLongitude,
	                 0);
	I_SimpleProperty(osg::EllipsoidModel *, EllipsoidModel,
	                 __osg_EllipsoidModel_P1__getEllipsoidModel,
	                 0);
	I_SimpleProperty(double, Height,
	                 __double__getHeight,
	                 0);
	I_SimpleProperty(double, Latitude,
	                 __double__getLatitude,
	                 0);
	I_SimpleProperty(double, Longitude,
	                 __double__getLongitude,
	                 0);
END_REFLECTOR

BEGIN_OBJECT_REFLECTOR(osgTerrain::Locator)
	I_BaseType(osg::Object);
	I_Constructor0(____Locator,
	               "",
	               "");
	I_ConstructorWithDefaults2(IN, const osgTerrain::Locator &, x, , IN, const osg::CopyOp &, copyop, osg::CopyOp::SHALLOW_COPY,
	                           ____Locator__C5_Locator_R1__C5_osg_CopyOp_R1,
	                           "Copy constructor using CopyOp to manage deep vs shallow copy. ",
	                           "");
	I_Method0(osg::Object *, cloneType,
	          Properties::VIRTUAL,
	          __osg_Object_P1__cloneType,
	          "Clone the type of an object, with Object* return type. ",
	          "Must be defined by derived classes. ");
	I_Method1(osg::Object *, clone, IN, const osg::CopyOp &, copyop,
	          Properties::VIRTUAL,
	          __osg_Object_P1__clone__C5_osg_CopyOp_R1,
	          "Clone an object, with Object* return type. ",
	          "Must be defined by derived classes. ");
	I_Method1(bool, isSameKindAs, IN, const osg::Object *, obj,
	          Properties::VIRTUAL,
	          __bool__isSameKindAs__C5_osg_Object_P1,
	          "",
	          "");
	I_Method0(const char *, libraryName,
	          Properties::VIRTUAL,
	          __C5_char_P1__libraryName,
	          "return the name of the object's library. ",
	          "Must be defined by derived classes. The OpenSceneGraph convention is that the namespace of a library is the same as the library name. ");
	I_Method0(const char *, className,
	          Properties::VIRTUAL,
	          __C5_char_P1__className,
	          "return the name of the object's class type. ",
	          "Must be defined by derived classes. ");
	I_Method2(bool, convertLocalToModel, IN, const osg::Vec3d &, x, IN, osg::Vec3d &, x,
	          Properties::VIRTUAL,
	          __bool__convertLocalToModel__C5_osg_Vec3d_R1__osg_Vec3d_R1,
	          "",
	          "");
	I_Method2(bool, convertModelToLocal, IN, const osg::Vec3d &, x, IN, osg::Vec3d &, x,
	          Properties::VIRTUAL,
	          __bool__convertModelToLocal__C5_osg_Vec3d_R1__osg_Vec3d_R1,
	          "",
	          "");
	I_Method3(bool, computeLocalBounds, IN, osgTerrain::Locator &, source, IN, osg::Vec3d &, bottomLeft, IN, osg::Vec3d &, topRight,
	          Properties::NON_VIRTUAL,
	          __bool__computeLocalBounds__Locator_R1__osg_Vec3d_R1__osg_Vec3d_R1,
	          "",
	          "");
	I_StaticMethod4(bool, convertLocalCoordBetween, IN, const osgTerrain::Locator &, source, IN, const osg::Vec3d &, sourceNDC, IN, const osgTerrain::Locator &, destination, IN, osg::Vec3d &, destinationNDC,
	                __bool__convertLocalCoordBetween__C5_Locator_R1__C5_osg_Vec3d_R1__C5_Locator_R1__osg_Vec3d_R1_S,
	                "",
	                "");
END_REFLECTOR

<|endoftext|>


<commit_before>/** Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Roland Olbricht et al.
 *
 * This file is part of Overpass_API.
 *
 * Overpass_API is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * Overpass_API 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 General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Overpass_API.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#undef VERSION
#endif

#ifdef HAVE_FASTCGI
#include "fcgio.h"
#endif

#include "resource_manager.h"
#include "scripting_core.h"
#include "../frontend/web_output.h"
#include "../frontend/user_interface.h"
#include "../statements/osm_script.h"
#include "../statements/statement.h"
#include "../../expat/expat_justparse_interface.h"
#include "../../template_db/dispatcher.h"

#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

// Maximum bytes
const unsigned long STDIN_MAX = 1000000;

int handle_request(const std::string & content, bool is_cgi, Index_Cache* ic)
{
  Parsed_Query global_settings;
  Web_Output error_output(Error_Output::ASSISTING);
  Statement::set_error_output(&error_output);

  try
  {
    global_settings.set_input_params(
	get_xml_cgi(content, &error_output, 16*1024*1024,
	error_output.http_method, error_output.allow_headers, error_output.has_origin, is_cgi));

    if (error_output.display_encoding_errors())
      return 0;

    Statement::Factory stmt_factory(global_settings);
    if (!parse_and_validate(stmt_factory, global_settings, global_settings.get_input_params().find("data")->second,
        &error_output, parser_execute))
      return 0;

    error_output.set_output_handler(global_settings.get_output_handler());

    Osm_Script_Statement* osm_script = 0;
    if (!get_statement_stack()->empty())
      osm_script = dynamic_cast< Osm_Script_Statement* >(get_statement_stack()->front());

    uint32 max_allowed_time = 0;
    uint64 max_allowed_space = 0;
    if (osm_script)
    {
      max_allowed_time = osm_script->get_max_allowed_time();
      max_allowed_space = osm_script->get_max_allowed_space();
    }
    else
    {
      Osm_Script_Statement temp(0, std::map< std::string, std::string >(), global_settings);
      max_allowed_time = temp.get_max_allowed_time();
      max_allowed_space = temp.get_max_allowed_space();
    }

    if (error_output.http_method == http_options
        || error_output.http_method == http_head)
      error_output.write_payload_header("", "", "", true);
    else
    {
      // open read transaction and log this.
      int area_level = determine_area_level(&error_output, 0);
      Dispatcher_Stub dispatcher("", &error_output, global_settings.get_input_params().find("data")->second,
			         get_uses_meta_data(), area_level,
				 max_allowed_time, max_allowed_space, global_settings, ic);
      if (osm_script && osm_script->get_desired_timestamp())
        dispatcher.resource_manager().set_desired_timestamp(osm_script->get_desired_timestamp());

      error_output.write_payload_header(dispatcher.get_db_dir(), dispatcher.get_timestamp(),
 	  area_level > 0 ? dispatcher.get_area_timestamp() : "", true);

      Cpu_Timer cpu_timer(dispatcher.resource_manager(), 0);
      for (std::vector< Statement* >::const_iterator it(get_statement_stack()->begin());
	   it != get_statement_stack()->end(); ++it)
        (*it)->execute(dispatcher.resource_manager());

    //TODO
//       if (osm_script && osm_script->get_type() == "popup")
//       {
//         error_output.write_html_header
//             (dispatcher.get_timestamp(),
// 	     area_level > 0 ? dispatcher.get_area_timestamp() : "", 200,
// 	     osm_script->template_contains_js(), false);
//         osm_script->write_output();
//         error_output.write_footer();
//       }
//       else
//         error_output.write_footer();
    }
  }
  catch(File_Error e)
  {
    std::ostringstream temp;
    if (e.origin.substr(e.origin.size()-9) == "::timeout")
    {
      error_output.write_html_header("", "", 504, false);
      if (error_output.http_method == http_get
          || error_output.http_method == http_post)
        temp<<"open64: "<<e.error_number<<' '<<strerror(e.error_number)<<' '<<e.filename<<' '<<e.origin
            <<". The server is probably too busy to handle your request.\n";
    }
    else if (e.origin.substr(e.origin.size()-14) == "::rate_limited")
    {
      error_output.write_html_header("", "", 429, false);
      if (error_output.http_method == http_get
          || error_output.http_method == http_post)
        temp<<"open64: "<<e.error_number<<' '<<strerror(e.error_number)<<' '<<e.filename<<' '<<e.origin
            <<". Please check /api/status for the quota of your IP address.\n";
    }
    else
      temp<<"open64: "<<e.error_number<<' '<<strerror(e.error_number)<<' '<<e.filename<<' '<<e.origin;
    error_output.runtime_error(temp.str());
  }
  catch(Resource_Error e)
  {
    std::ostringstream temp;
    if (e.timed_out)
      temp<<"Query timed out in \""<<e.stmt_name<<"\" at line "<<e.line_number
          <<" after "<<e.runtime<<" seconds.";
    else
      temp<<"Query ran out of memory in \""<<e.stmt_name<<"\" at line "
          <<e.line_number<<". It would need at least "<<e.size/(1024*1024)<<" MB of RAM to continue.";
    error_output.runtime_error(temp.str());
  }
  catch(std::bad_alloc& e)
  {
    rlimit limit;
    getrlimit(RLIMIT_AS, &limit);
    std::ostringstream temp;
    temp<<"Query run out of memory using about "<<limit.rlim_cur/(1024*1024)<<" MB of RAM.";
    error_output.runtime_error(temp.str());
  }
  catch(std::exception& e)
  {
    error_output.runtime_error(std::string("Query failed with the exception: ") + e.what());
  }
  catch(Exit_Error e) {}

  return 0;
}

#ifdef HAVE_FASTCGI
std::string get_request_content(const FCGX_Request & request) {
    char * content_length_str = FCGX_GetParam("CONTENT_LENGTH", request.envp);
    unsigned long content_length = STDIN_MAX;

    if (content_length_str) {
        content_length = strtol(content_length_str, &content_length_str, 10);
        if (*content_length_str) {
          std::cerr << "Can't Parse 'CONTENT_LENGTH='"
                 << FCGX_GetParam("CONTENT_LENGTH", request.envp)
                 << "'. Consuming stdin up to " << STDIN_MAX << std::endl;
        }

        if (content_length > STDIN_MAX) {
            content_length = STDIN_MAX;
        }
    } else {
        // Do not read from stdin if CONTENT_LENGTH is missing
        content_length = 0;
    }

    char * content_buffer = new char[content_length];
    std::cin.read(content_buffer, content_length);
    content_length = std::cin.gcount();

    // Chew up any remaining stdin - this shouldn't be necessary
    // but is because mod_fastcgi doesn't handle it correctly.

    // ignore() doesn't set the eof bit in some versions of glibc++
    // so use gcount() instead of eof()...
    do std::cin.ignore(1024); while (std::cin.gcount() == 1024);

    std::string content(content_buffer, content_length);
    delete [] content_buffer;
    return content;
}
#endif

int main(int argc, char *argv[])
{
  Index_Cache ic;

#ifdef HAVE_FASTCGI

  if (FCGX_IsCGI())
  {

#endif

    int ret = handle_request("", true, &ic);
    return (ret);

#ifdef HAVE_FASTCGI

  }
  else
  {
    int request_counter = 0;
    time_t start_time = time(0);

    // Backup the stdio streambuffers
    std::streambuf * cin_streambuf  = std::cin.rdbuf();
    std::streambuf * cout_streambuf = std::cout.rdbuf();
    std::streambuf * cerr_streambuf = std::cerr.rdbuf();

    FCGX_Request request;

    FCGX_Init();
    FCGX_InitRequest(&request, 0, 0);

    while (FCGX_Accept_r(&request) == 0) {
      fcgi_streambuf cin_fcgi_streambuf(request.in);
      fcgi_streambuf cout_fcgi_streambuf(request.out);
      fcgi_streambuf cerr_fcgi_streambuf(request.err);

      std::cin.rdbuf(&cin_fcgi_streambuf);
      std::cout.rdbuf(&cout_fcgi_streambuf);
      std::cerr.rdbuf(&cerr_fcgi_streambuf);

      std::string content = get_request_content(request);

      char* request_method = FCGX_GetParam("REQUEST_METHOD", request.envp);
      char* access_control_headers = FCGX_GetParam("HTTP_ACCESS_CONTROL_REQUEST_HEADERS", request.envp);
      char* http_origin = FCGX_GetParam("HTTP_ORIGIN", request.envp);
      char* remote_addr = FCGX_GetParam("REMOTE_ADDR", request.envp);
      char* query_string = FCGX_GetParam("QUERY_STRING", request.envp);

      setenv("REQUEST_METHOD", request_method != NULL ? request_method : "", true);
      setenv("HTTP_ACCESS_CONTROL_REQUEST_HEADERS", access_control_headers != NULL ? access_control_headers : "" , true);
      setenv("HTTP_ORIGIN", http_origin != NULL ? http_origin : "", true);
      setenv("REMOTE_ADDR", remote_addr != NULL ? remote_addr : "", true);
      setenv("QUERY_STRING", query_string != NULL ? query_string : "", true);

      initialize();

      int ret = handle_request(content, FCGX_IsCGI(), &ic);

      std::cout << std::flush;
      std::cerr << std::flush;

      // Restart process after error or a certain number of time / requests
      time_t elapsed_time = time(NULL) - start_time;
      if (ret < 0 || ++request_counter > 1000 || elapsed_time > 900)       //TODO: add configuration option
      {
        FCGX_Finish_r(&request);
        break;
      }
    }

    // restore stdio streambuffers
    std::cin.rdbuf(cin_streambuf);
    std::cout.rdbuf(cout_streambuf);
    std::cerr.rdbuf(cerr_streambuf);

  }
#endif

  return 0;
}

<commit_msg>Add environment variables to control FCGI restart OVERPASS_FCGI_MAX_REQUESTS, OVERPASS_FCGI_MAX_ELAPSED_TIME<commit_after>/** Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Roland Olbricht et al.
 *
 * This file is part of Overpass_API.
 *
 * Overpass_API is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * Overpass_API 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 General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Overpass_API.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#undef VERSION
#endif

#ifdef HAVE_FASTCGI
#include "fcgio.h"
#endif

#include "resource_manager.h"
#include "scripting_core.h"
#include "../frontend/web_output.h"
#include "../frontend/user_interface.h"
#include "../statements/osm_script.h"
#include "../statements/statement.h"
#include "../../expat/expat_justparse_interface.h"
#include "../../template_db/dispatcher.h"

#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

// Maximum bytes
const unsigned long STDIN_MAX = 1000000;

int handle_request(const std::string & content, bool is_cgi, Index_Cache* ic)
{
  Parsed_Query global_settings;
  Web_Output error_output(Error_Output::ASSISTING);
  Statement::set_error_output(&error_output);

  try
  {
    global_settings.set_input_params(
	get_xml_cgi(content, &error_output, 16*1024*1024,
	error_output.http_method, error_output.allow_headers, error_output.has_origin, is_cgi));

    if (error_output.display_encoding_errors())
      return 0;

    Statement::Factory stmt_factory(global_settings);
    if (!parse_and_validate(stmt_factory, global_settings, global_settings.get_input_params().find("data")->second,
        &error_output, parser_execute))
      return 0;

    error_output.set_output_handler(global_settings.get_output_handler());

    Osm_Script_Statement* osm_script = 0;
    if (!get_statement_stack()->empty())
      osm_script = dynamic_cast< Osm_Script_Statement* >(get_statement_stack()->front());

    uint32 max_allowed_time = 0;
    uint64 max_allowed_space = 0;
    if (osm_script)
    {
      max_allowed_time = osm_script->get_max_allowed_time();
      max_allowed_space = osm_script->get_max_allowed_space();
    }
    else
    {
      Osm_Script_Statement temp(0, std::map< std::string, std::string >(), global_settings);
      max_allowed_time = temp.get_max_allowed_time();
      max_allowed_space = temp.get_max_allowed_space();
    }

    if (error_output.http_method == http_options
        || error_output.http_method == http_head)
      error_output.write_payload_header("", "", "", true);
    else
    {
      // open read transaction and log this.
      int area_level = determine_area_level(&error_output, 0);
      Dispatcher_Stub dispatcher("", &error_output, global_settings.get_input_params().find("data")->second,
			         get_uses_meta_data(), area_level,
				 max_allowed_time, max_allowed_space, global_settings, ic);
      if (osm_script && osm_script->get_desired_timestamp())
        dispatcher.resource_manager().set_desired_timestamp(osm_script->get_desired_timestamp());

      error_output.write_payload_header(dispatcher.get_db_dir(), dispatcher.get_timestamp(),
 	  area_level > 0 ? dispatcher.get_area_timestamp() : "", true);

      Cpu_Timer cpu_timer(dispatcher.resource_manager(), 0);
      for (std::vector< Statement* >::const_iterator it(get_statement_stack()->begin());
	   it != get_statement_stack()->end(); ++it)
        (*it)->execute(dispatcher.resource_manager());

    //TODO
//       if (osm_script && osm_script->get_type() == "popup")
//       {
//         error_output.write_html_header
//             (dispatcher.get_timestamp(),
// 	     area_level > 0 ? dispatcher.get_area_timestamp() : "", 200,
// 	     osm_script->template_contains_js(), false);
//         osm_script->write_output();
//         error_output.write_footer();
//       }
//       else
//         error_output.write_footer();
    }
  }
  catch(File_Error e)
  {
    std::ostringstream temp;
    if (e.origin.substr(e.origin.size()-9) == "::timeout")
    {
      error_output.write_html_header("", "", 504, false);
      if (error_output.http_method == http_get
          || error_output.http_method == http_post)
        temp<<"open64: "<<e.error_number<<' '<<strerror(e.error_number)<<' '<<e.filename<<' '<<e.origin
            <<". The server is probably too busy to handle your request.\n";
    }
    else if (e.origin.substr(e.origin.size()-14) == "::rate_limited")
    {
      error_output.write_html_header("", "", 429, false);
      if (error_output.http_method == http_get
          || error_output.http_method == http_post)
        temp<<"open64: "<<e.error_number<<' '<<strerror(e.error_number)<<' '<<e.filename<<' '<<e.origin
            <<". Please check /api/status for the quota of your IP address.\n";
    }
    else
      temp<<"open64: "<<e.error_number<<' '<<strerror(e.error_number)<<' '<<e.filename<<' '<<e.origin;
    error_output.runtime_error(temp.str());
  }
  catch(Resource_Error e)
  {
    std::ostringstream temp;
    if (e.timed_out)
      temp<<"Query timed out in \""<<e.stmt_name<<"\" at line "<<e.line_number
          <<" after "<<e.runtime<<" seconds.";
    else
      temp<<"Query ran out of memory in \""<<e.stmt_name<<"\" at line "
          <<e.line_number<<". It would need at least "<<e.size/(1024*1024)<<" MB of RAM to continue.";
    error_output.runtime_error(temp.str());
  }
  catch(std::bad_alloc& e)
  {
    rlimit limit;
    getrlimit(RLIMIT_AS, &limit);
    std::ostringstream temp;
    temp<<"Query run out of memory using about "<<limit.rlim_cur/(1024*1024)<<" MB of RAM.";
    error_output.runtime_error(temp.str());
  }
  catch(std::exception& e)
  {
    error_output.runtime_error(std::string("Query failed with the exception: ") + e.what());
  }
  catch(Exit_Error e) {}

  return 0;
}

#ifdef HAVE_FASTCGI
std::string get_request_content(const FCGX_Request & request) {
    char * content_length_str = FCGX_GetParam("CONTENT_LENGTH", request.envp);
    unsigned long content_length = STDIN_MAX;

    if (content_length_str) {
        content_length = strtol(content_length_str, &content_length_str, 10);
        if (*content_length_str) {
          std::cerr << "Can't Parse 'CONTENT_LENGTH='"
                 << FCGX_GetParam("CONTENT_LENGTH", request.envp)
                 << "'. Consuming stdin up to " << STDIN_MAX << std::endl;
        }

        if (content_length > STDIN_MAX) {
            content_length = STDIN_MAX;
        }
    } else {
        // Do not read from stdin if CONTENT_LENGTH is missing
        content_length = 0;
    }

    char * content_buffer = new char[content_length];
    std::cin.read(content_buffer, content_length);
    content_length = std::cin.gcount();

    // Chew up any remaining stdin - this shouldn't be necessary
    // but is because mod_fastcgi doesn't handle it correctly.

    // ignore() doesn't set the eof bit in some versions of glibc++
    // so use gcount() instead of eof()...
    do std::cin.ignore(1024); while (std::cin.gcount() == 1024);

    std::string content(content_buffer, content_length);
    delete [] content_buffer;
    return content;
}
#endif

int main(int argc, char *argv[])
{
  Index_Cache ic;

#ifdef HAVE_FASTCGI

  if (FCGX_IsCGI())
  {

#endif

    int ret = handle_request("", true, &ic);
    return (ret);

#ifdef HAVE_FASTCGI

  }
  else
  {
    int request_counter = 0;
    time_t start_time = time(0);

    char const* max_requests_c = std::getenv("OVERPASS_FCGI_MAX_REQUESTS");
    char const* max_elapsed_time_c = std::getenv("OVERPASS_FCGI_MAX_ELAPSED_TIME");

    int max_requests = (max_requests_c == NULL) ? 0 : atoi(max_requests_c);
    int max_elapsed_time = (max_elapsed_time_c == NULL) ? 0 : atoi(max_elapsed_time_c);

    if (max_requests < 0) max_requests = 0;
    if (max_elapsed_time < 0) max_elapsed_time = 0;

    // Backup the stdio streambuffers
    std::streambuf * cin_streambuf  = std::cin.rdbuf();
    std::streambuf * cout_streambuf = std::cout.rdbuf();
    std::streambuf * cerr_streambuf = std::cerr.rdbuf();

    FCGX_Request request;

    FCGX_Init();
    FCGX_InitRequest(&request, 0, 0);

    while (FCGX_Accept_r(&request) == 0) {
      fcgi_streambuf cin_fcgi_streambuf(request.in);
      fcgi_streambuf cout_fcgi_streambuf(request.out);
      fcgi_streambuf cerr_fcgi_streambuf(request.err);

      std::cin.rdbuf(&cin_fcgi_streambuf);
      std::cout.rdbuf(&cout_fcgi_streambuf);
      std::cerr.rdbuf(&cerr_fcgi_streambuf);

      std::string content = get_request_content(request);

      char* request_method = FCGX_GetParam("REQUEST_METHOD", request.envp);
      char* access_control_headers = FCGX_GetParam("HTTP_ACCESS_CONTROL_REQUEST_HEADERS", request.envp);
      char* http_origin = FCGX_GetParam("HTTP_ORIGIN", request.envp);
      char* remote_addr = FCGX_GetParam("REMOTE_ADDR", request.envp);
      char* query_string = FCGX_GetParam("QUERY_STRING", request.envp);

      setenv("REQUEST_METHOD", request_method != NULL ? request_method : "", true);
      setenv("HTTP_ACCESS_CONTROL_REQUEST_HEADERS", access_control_headers != NULL ? access_control_headers : "" , true);
      setenv("HTTP_ORIGIN", http_origin != NULL ? http_origin : "", true);
      setenv("REMOTE_ADDR", remote_addr != NULL ? remote_addr : "", true);
      setenv("QUERY_STRING", query_string != NULL ? query_string : "", true);

      initialize();

      int ret = handle_request(content, FCGX_IsCGI(), &ic);

      // Restart process after error or a certain number of time / requests
      time_t elapsed_time = time(NULL) - start_time;
      if (ret < 0 ||
          (max_requests > 0 && ++request_counter > max_requests) ||
          (max_elapsed_time > 0 && elapsed_time > max_elapsed_time))
      {
        FCGX_Finish_r(&request);
        break;
      }
    }

    // restore stdio streambuffers
    std::cin.rdbuf(cin_streambuf);
    std::cout.rdbuf(cout_streambuf);
    std::cerr.rdbuf(cerr_streambuf);

  }
#endif

  return 0;
}

<|endoftext|>


<commit_before>#include "pbfParser.h"
#include "platform.h"

void PbfParser::extractGeometry(const protobuf::message& _in, int _tileExtent, std::vector<Line>& _out, const MapTile& _tile) {

    pbfGeomCmd cmd = pbfGeomCmd::moveTo;
    uint32_t cmdRepeat = 0;
    protobuf::message geomItr = _in;

    double invTileExtent = (1.0/(double)_tileExtent);

    std::vector<Point> line;

    int x = 0.0f;
    int y = 0.0f;

    uint64_t xZigZag = 0;
    uint64_t yZigZag = 0;

    while(geomItr.getData() < geomItr.getEnd()) {

        if(cmdRepeat == 0) { // get new command, lengh and parameters..
            uint32_t cmdData = static_cast<uint32_t>(geomItr.varint());
            cmd = static_cast<pbfGeomCmd>(cmdData & 0x7); //first 3 bits of the cmdData
            cmdRepeat = cmdData >> 3; //last 5 bits
        }

        if(cmd == pbfGeomCmd::moveTo || cmd == pbfGeomCmd::lineTo) { // get parameters/points
            // if cmd is move then move to a new line/set of points and save this line
            if(cmd == pbfGeomCmd::moveTo) {
                if(line.size() > 0) {
                    _out.emplace_back(line);
                }
                line.clear();
            }

            // Decode zig-zag encoded paramters

            xZigZag += geomItr.svarint();
            yZigZag += geomItr.svarint();

            x = int((xZigZag << 1) ^ (xZigZag >> 31));
            y = int((yZigZag << 1) ^ (yZigZag >> 31));

            // bring the points in -1 to 1 space
            Point p;
            p.x = invTileExtent * (double)(x - _tileExtent);
            p.y = invTileExtent * (double)(_tileExtent - y);

            line.emplace_back(p);
        } else if( cmd == pbfGeomCmd::closePath) { // end of a polygon, push first point in this line as last and push line to poly
            line.push_back(line[0]);
            _out.emplace_back(line);
            line.clear();
        }

        cmdRepeat--;
    }

    // Enter the last line
    if(line.size() > 0) {
        _out.emplace_back(line);
    }

}

void PbfParser::extractFeature(const protobuf::message& _in, Feature& _out, const MapTile& _tile, std::vector<std::string>& _keys, std::unordered_map<int, float>& _numericValues, std::unordered_map<int, std::string>& _stringValues, int _tileExtent) {

    //Iterate through this feature
    std::vector<Line> geometryLines;
    protobuf::message featureItr = _in;
    protobuf::message geometry; // By default data_ and end_ are nullptr

    while(featureItr.next()) {
        switch(featureItr.tag) {
            // Feature ID
            case 1:
                // ignored for now, also not used in json parsing
                featureItr.skip();
                break;
            // Feature tags (properties)
            case 2:
            {
                // extract tags message
                protobuf::message tagsMsg = featureItr.getMessage();

                while(tagsMsg) {
                    std::size_t tagKey = tagsMsg.varint();

                    if(_keys.size() <= tagKey) {
                        logMsg("ERROR: accessing out of bound key\n");
                    }

                    if(tagsMsg) {
                        std::size_t valueKey = tagsMsg.varint();

                        if( (_numericValues.size() + _stringValues.size()) <= valueKey ) {
                            logMsg("ERROR: accessing out of bound values\n");
                        }

                        if(_numericValues.find(valueKey) != _numericValues.end()) {

                            // height and minheight need to be handled separately so that their dimensions are normalized
                            if(_keys[tagKey].compare("height") == 0 || _keys[tagKey].compare("min_height") == 0) {
                                _out.props.numericProps[_keys[tagKey]] = _numericValues[valueKey] * _tile.getInverseScale();
                            } else {
                                _out.props.numericProps[_keys[tagKey]] = _numericValues[valueKey];
                            }

                        } else if(_stringValues.find(valueKey) != _stringValues.end()) {
                            _out.props.stringProps[_keys[tagKey]] = _stringValues[valueKey];
                        } else {
                            logMsg("ERROR: Tag is missing, should not be!!");
                        }
                    } else {
                        logMsg("uneven number of feature tag ids");
                        throw std::runtime_error("uneven number of feature tag ids");
                    }
                }
            }
                break;
            // Feature Type
            case 3:
                _out.geometryType = (GeometryType)featureItr.varint();
                break;
            // Actual geometry data
            case 4:
                geometry = featureItr.getMessage();
                extractGeometry(geometry, _tileExtent, geometryLines, _tile);
                break;
            // None.. skip
            default:
                featureItr.skip();
                break;
        }
    }

    switch(_out.geometryType) {
        case GeometryType::POINTS:
            for(auto& line : geometryLines) {
                for(auto& point : line) {
                    _out.points.emplace_back(point);
                }
            }
            break;
        case GeometryType::LINES:
            for(auto& line : geometryLines) {
                _out.lines.emplace_back(line);
            }
            break;
        case GeometryType::POLYGONS:
            _out.polygons.emplace_back(geometryLines);
            break;
        case GeometryType::UNKNOWN:
            break;
        default:
            break;
    }

}

void PbfParser::extractLayer(const protobuf::message& _in, Layer& _out, const MapTile& _tile) {

    protobuf::message layerItr = _in;

    std::vector<std::string> keys;
    std::unordered_map<int, float> numericValues;
    std::unordered_map<int, std::string> stringValues;
    std::vector<protobuf::message> featureMsgs;
    int tileExtent = 0;

    //iterate layer to populate featureMsgs, keys and values
    int valueCount = 0;
    while(layerItr.next()) {
        switch(layerItr.tag) {
            case 2: // features
            {
                protobuf::message featureMsg = layerItr.getMessage();
                featureMsgs.emplace_back(featureMsg);
                break;
            }

            case 3: // key string
                keys.emplace_back(layerItr.string());
                break;

            case 4: // values
            {
                protobuf::message valueMsg = layerItr.getMessage();
                protobuf::message valueItr = valueMsg;

                while (valueItr.next()) {
                    switch (valueItr.tag) {
                        case 1: // string value
                            stringValues[valueCount] = valueItr.string();
                            break;
                        case 2: // float value
                            numericValues[valueCount] = valueItr.float32();
                            break;
                        case 3: // double value
                            numericValues[valueCount] = valueItr.float64();
                            break;
                        case 4: // int value
                            numericValues[valueCount] = valueItr.int64();
                            break;
                        case 5: // uint value
                            numericValues[valueCount] = valueItr.varint();
                            break;
                        case 6: // sint value
                            numericValues[valueCount] = valueItr.int64();
                            break;
                        case 7: // bool value
                            numericValues[valueCount] = valueItr.boolean();
                            break;
                        default:
                            valueItr.skip();
                            break;
                    }
                }
                valueCount++;
                break;
            }

            case 5: //extent
                tileExtent = static_cast<int>(layerItr.int64());
                break;

            default: // skip
                layerItr.skip();
                break;

        }
    }

    for(auto& featureMsg : featureMsgs) {
        _out.features.emplace_back();
        extractFeature(featureMsg, _out.features.back(), _tile, keys, numericValues, stringValues, tileExtent);
    }
}
<commit_msg>Reduce [] operations on maps in PBF parsing<commit_after>#include "pbfParser.h"
#include "platform.h"

void PbfParser::extractGeometry(const protobuf::message& _in, int _tileExtent, std::vector<Line>& _out, const MapTile& _tile) {

    pbfGeomCmd cmd = pbfGeomCmd::moveTo;
    uint32_t cmdRepeat = 0;
    protobuf::message geomItr = _in;

    double invTileExtent = (1.0/(double)_tileExtent);

    std::vector<Point> line;

    int x = 0.0f;
    int y = 0.0f;

    uint64_t xZigZag = 0;
    uint64_t yZigZag = 0;

    while(geomItr.getData() < geomItr.getEnd()) {

        if(cmdRepeat == 0) { // get new command, lengh and parameters..
            uint32_t cmdData = static_cast<uint32_t>(geomItr.varint());
            cmd = static_cast<pbfGeomCmd>(cmdData & 0x7); //first 3 bits of the cmdData
            cmdRepeat = cmdData >> 3; //last 5 bits
        }

        if(cmd == pbfGeomCmd::moveTo || cmd == pbfGeomCmd::lineTo) { // get parameters/points
            // if cmd is move then move to a new line/set of points and save this line
            if(cmd == pbfGeomCmd::moveTo) {
                if(line.size() > 0) {
                    _out.emplace_back(line);
                }
                line.clear();
            }

            // Decode zig-zag encoded paramters

            xZigZag += geomItr.svarint();
            yZigZag += geomItr.svarint();

            x = int((xZigZag << 1) ^ (xZigZag >> 31));
            y = int((yZigZag << 1) ^ (yZigZag >> 31));

            // bring the points in -1 to 1 space
            Point p;
            p.x = invTileExtent * (double)(x - _tileExtent);
            p.y = invTileExtent * (double)(_tileExtent - y);

            line.emplace_back(p);
        } else if( cmd == pbfGeomCmd::closePath) { // end of a polygon, push first point in this line as last and push line to poly
            line.push_back(line[0]);
            _out.emplace_back(line);
            line.clear();
        }

        cmdRepeat--;
    }

    // Enter the last line
    if(line.size() > 0) {
        _out.emplace_back(line);
    }

}

void PbfParser::extractFeature(const protobuf::message& _in, Feature& _out, const MapTile& _tile, std::vector<std::string>& _keys, std::unordered_map<int, float>& _numericValues, std::unordered_map<int, std::string>& _stringValues, int _tileExtent) {

    //Iterate through this feature
    std::vector<Line> geometryLines;
    protobuf::message featureItr = _in;
    protobuf::message geometry; // By default data_ and end_ are nullptr

    while(featureItr.next()) {
        switch(featureItr.tag) {
            // Feature ID
            case 1:
                // ignored for now, also not used in json parsing
                featureItr.skip();
                break;
            // Feature tags (properties)
            case 2:
            {
                // extract tags message
                protobuf::message tagsMsg = featureItr.getMessage();

                while(tagsMsg) {
                    std::size_t tagKey = tagsMsg.varint();

                    if(_keys.size() <= tagKey) {
                        logMsg("ERROR: accessing out of bound key\n");
                    }

                    if(tagsMsg) {
                        std::size_t valueKey = tagsMsg.varint();

                        if( (_numericValues.size() + _stringValues.size()) <= valueKey ) {
                            logMsg("ERROR: accessing out of bound values\n");
                        }

                        const auto& key = _keys[tagKey];
                        const auto& numVal = _numericValues.find(valueKey);

                        if(numVal != _numericValues.end()) {

                            // height and minheight need to be handled separately so that their dimensions are normalized
                            if(key.compare("height") == 0 || key.compare("min_height") == 0) {
                                _out.props.numericProps[key] = numVal->second * _tile.getInverseScale();
                            } else {
                                _out.props.numericProps[key] = numVal->second;
                            }

                        } else {

                            const auto& strVal = _stringValues.find(valueKey);
                            if(strVal != _stringValues.end()) {

                                _out.props.stringProps[key] = strVal->second;

                            } else {
                                logMsg("ERROR: Tag is missing, should not be!!");
                            }

                        }
                    } else {
                        logMsg("uneven number of feature tag ids");
                        throw std::runtime_error("uneven number of feature tag ids");
                    }
                }
            }
                break;
            // Feature Type
            case 3:
                _out.geometryType = (GeometryType)featureItr.varint();
                break;
            // Actual geometry data
            case 4:
                geometry = featureItr.getMessage();
                extractGeometry(geometry, _tileExtent, geometryLines, _tile);
                break;
            // None.. skip
            default:
                featureItr.skip();
                break;
        }
    }

    switch(_out.geometryType) {
        case GeometryType::POINTS:
            for(auto& line : geometryLines) {
                for(auto& point : line) {
                    _out.points.emplace_back(point);
                }
            }
            break;
        case GeometryType::LINES:
            for(auto& line : geometryLines) {
                _out.lines.emplace_back(line);
            }
            break;
        case GeometryType::POLYGONS:
            _out.polygons.emplace_back(geometryLines);
            break;
        case GeometryType::UNKNOWN:
            break;
        default:
            break;
    }

}

void PbfParser::extractLayer(const protobuf::message& _in, Layer& _out, const MapTile& _tile) {

    protobuf::message layerItr = _in;

    std::vector<std::string> keys;
    std::unordered_map<int, float> numericValues;
    std::unordered_map<int, std::string> stringValues;
    std::vector<protobuf::message> featureMsgs;
    int tileExtent = 0;

    //iterate layer to populate featureMsgs, keys and values
    int valueCount = 0;
    while(layerItr.next()) {
        switch(layerItr.tag) {
            case 2: // features
            {
                protobuf::message featureMsg = layerItr.getMessage();
                featureMsgs.emplace_back(featureMsg);
                break;
            }

            case 3: // key string
                keys.emplace_back(layerItr.string());
                break;

            case 4: // values
            {
                protobuf::message valueMsg = layerItr.getMessage();
                protobuf::message valueItr = valueMsg;

                while (valueItr.next()) {
                    switch (valueItr.tag) {
                        case 1: // string value
                            stringValues[valueCount] = valueItr.string();
                            break;
                        case 2: // float value
                            numericValues[valueCount] = valueItr.float32();
                            break;
                        case 3: // double value
                            numericValues[valueCount] = valueItr.float64();
                            break;
                        case 4: // int value
                            numericValues[valueCount] = valueItr.int64();
                            break;
                        case 5: // uint value
                            numericValues[valueCount] = valueItr.varint();
                            break;
                        case 6: // sint value
                            numericValues[valueCount] = valueItr.int64();
                            break;
                        case 7: // bool value
                            numericValues[valueCount] = valueItr.boolean();
                            break;
                        default:
                            valueItr.skip();
                            break;
                    }
                }
                valueCount++;
                break;
            }

            case 5: //extent
                tileExtent = static_cast<int>(layerItr.int64());
                break;

            default: // skip
                layerItr.skip();
                break;

        }
    }

    for(auto& featureMsg : featureMsgs) {
        _out.features.emplace_back();
        extractFeature(featureMsg, _out.features.back(), _tile, keys, numericValues, stringValues, tileExtent);
    }
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <memory>

#include "absl/debugging/failure_signal_handler.h"
#include "absl/debugging/symbolize.h"
#include "test/test_main_lib.h"

int main(int argc, char* argv[]) {
  // Initialize the symbolizer to get a human-readable stack trace
  absl::InitializeSymbolizer(argv[0]);

  absl::FailureSignalHandlerOptions options;
  absl::InstallFailureSignalHandler(options);

  std::unique_ptr<webrtc::TestMain> main = webrtc::TestMain::Create();
  int err_code = main->Init(&argc, argv);
  if (err_code != 0) {
    return err_code;
  }
  return main->Run(argc, argv);
}
<commit_msg>Revert "Re-enable absl FailureSignalHandler in tests."<commit_after>/*
 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <memory>

#include "absl/debugging/failure_signal_handler.h"
#include "absl/debugging/symbolize.h"
#include "test/test_main_lib.h"

int main(int argc, char* argv[]) {
  // Initialize the symbolizer to get a human-readable stack trace
  // TODO(crbug.com/1050976): Breaks iossim tests, re-enable when fixed.
  // absl::InitializeSymbolizer(argv[0]);

  // absl::FailureSignalHandlerOptions options;
  // absl::InstallFailureSignalHandler(options);

  std::unique_ptr<webrtc::TestMain> main = webrtc::TestMain::Create();
  int err_code = main->Init(&argc, argv);
  if (err_code != 0) {
    return err_code;
  }
  return main->Run(argc, argv);
}
<|endoftext|>


<commit_before>#include "com_libmailcore_IndexSet.h"

#include "TypesUtils.h"
#include "JavaHandle.h"
#include "MCDefines.h"
#include "MCIndexSet.h"

using namespace mailcore;

#define nativeType IndexSet
#define javaType nativeType

JNIEXPORT jobject JNICALL Java_com_libmailcore_IndexSet_indexSet
  (JNIEnv * env, jclass cls)
{
    MC_POOL_BEGIN;
    jobject result = MC_TO_JAVA(IndexSet::indexSet());
    MC_POOL_END;
    return result;
}

JNIEXPORT jobject JNICALL Java_com_libmailcore_IndexSet_indexSetWithRange
  (JNIEnv * env, jclass cls, jobject range)
{
    MC_POOL_BEGIN;
    Range mcRange = rangeFromJava(env, range);
    jobject result = MC_TO_JAVA(IndexSet::indexSetWithRange(mcRange));
    MC_POOL_END;
    return result;
}

JNIEXPORT jobject JNICALL Java_com_libmailcore_IndexSet_indexSetWithIndex
  (JNIEnv * env, jclass cls, jlong idx)
{
    MC_POOL_BEGIN;
    jobject result = MC_TO_JAVA(IndexSet::indexSetWithIndex((uint64_t) idx));
    MC_POOL_END;
    return result;
}

JNIEXPORT jint JNICALL Java_com_libmailcore_IndexSet_count
  (JNIEnv * env, jobject obj)
{
    MC_POOL_BEGIN;
    jint result = MC_JAVA_BRIDGE_GET_SCALAR(jint, count);
    MC_POOL_END;
    return result;
}

JNIEXPORT void JNICALL Java_com_libmailcore_IndexSet_addIndex
  (JNIEnv * env, jobject obj, jlong idx)
{
    MC_POOL_BEGIN;
    MC_JAVA_NATIVE_INSTANCE->addIndex((uint64_t) idx);
    MC_POOL_END;
}

JNIEXPORT void JNICALL Java_com_libmailcore_IndexSet_removeIndex
  (JNIEnv * env, jobject obj, jlong idx)
{
    MC_POOL_BEGIN;
    MC_JAVA_NATIVE_INSTANCE->removeIndex((uint64_t) idx);
    MC_POOL_END;
}

JNIEXPORT jboolean JNICALL Java_com_libmailcore_IndexSet_containsIndex
  (JNIEnv * env, jobject obj, jlong idx)
{
    MC_POOL_BEGIN;
    jboolean result = (jboolean) MC_JAVA_NATIVE_INSTANCE->containsIndex((uint64_t) idx);
    MC_POOL_END;
    return result;
}

JNIEXPORT void JNICALL Java_com_libmailcore_IndexSet_addRange
  (JNIEnv * env, jobject obj, jobject range)
{
    MC_POOL_BEGIN;
    Range mcRange = rangeFromJava(env, range);
    MC_JAVA_NATIVE_INSTANCE->addRange(mcRange);
    MC_POOL_END;
}

JNIEXPORT void JNICALL Java_com_libmailcore_IndexSet_removeRange
  (JNIEnv * env, jobject obj, jobject range)
{
    MC_POOL_BEGIN;
    Range mcRange = rangeFromJava(env, range);
    MC_JAVA_NATIVE_INSTANCE->removeRange(mcRange);
    MC_POOL_END;
}

JNIEXPORT void JNICALL Java_com_libmailcore_IndexSet_intersectsRange
  (JNIEnv * env, jobject obj, jobject range)
{
    MC_POOL_BEGIN;
    Range mcRange = rangeFromJava(env, range);
    MC_JAVA_NATIVE_INSTANCE->intersectsRange(mcRange);
    MC_POOL_END;
}

JNIEXPORT void JNICALL Java_com_libmailcore_IndexSet_addIndexSet
  (JNIEnv * env, jobject obj, jobject otherIndexSet)
{
    MC_POOL_BEGIN;
    MC_JAVA_NATIVE_INSTANCE->addIndexSet(MC_FROM_JAVA(IndexSet, otherIndexSet));
    MC_POOL_END;
}

JNIEXPORT void JNICALL Java_com_libmailcore_IndexSet_removeIndexSet
  (JNIEnv * env, jobject obj, jobject otherIndexSet)
{
    MC_POOL_BEGIN;
    MC_JAVA_NATIVE_INSTANCE->removeIndexSet(MC_FROM_JAVA(IndexSet, otherIndexSet));
    MC_POOL_END;
}

JNIEXPORT void JNICALL Java_com_libmailcore_IndexSet_intersectsIndexSet
  (JNIEnv * env, jobject obj, jobject otherIndexSet)
{
    MC_POOL_BEGIN;
    MC_JAVA_NATIVE_INSTANCE->intersectsIndexSet(MC_FROM_JAVA(IndexSet, otherIndexSet));
    MC_POOL_END;
}

JNIEXPORT jobject JNICALL Java_com_libmailcore_IndexSet_allRanges
  (JNIEnv * env, jobject obj)
{
    MC_POOL_BEGIN;
    jclass cls = env->FindClass("java/util/Vector");
    jmethodID constructor = env->GetMethodID(cls, "<init>", "(I)V");
    unsigned int count = MC_JAVA_NATIVE_INSTANCE->rangesCount();
    jobject javaVector = env->NewObject(cls, constructor, count);
    jmethodID method = env->GetMethodID(cls, "add", "(Ljava/lang/Object;)Z");
    Range * ranges = MC_JAVA_NATIVE_INSTANCE->allRanges();
    for(unsigned int i = 0 ; i < count ; i ++) {
        jobject javaObject = rangeToJava(env, ranges[i]);
        env->CallBooleanMethod(javaVector, method, javaObject);
    }
    MC_POOL_END;
    return javaVector;
}

JNIEXPORT jint JNICALL Java_com_libmailcore_IndexSet_rangesCount
  (JNIEnv * env, jobject obj)
{
    MC_POOL_BEGIN;
    jint result = MC_JAVA_BRIDGE_GET_SCALAR(jint, rangesCount);
    MC_POOL_END;
    return result;
}

JNIEXPORT void JNICALL Java_com_libmailcore_IndexSet_removeAllIndexes
  (JNIEnv * env, jobject obj)
{
    MC_POOL_BEGIN;
    MC_JAVA_NATIVE_INSTANCE->removeAllIndexes();
    MC_POOL_END;
}

MC_JAVA_BRIDGE
<commit_msg>Fixed IndexSet#allRanges() in case lots of indexSet contains lots of ranges (fixed #1428)<commit_after>#include "com_libmailcore_IndexSet.h"

#include "TypesUtils.h"
#include "JavaHandle.h"
#include "MCDefines.h"
#include "MCIndexSet.h"

using namespace mailcore;

#define nativeType IndexSet
#define javaType nativeType

JNIEXPORT jobject JNICALL Java_com_libmailcore_IndexSet_indexSet
  (JNIEnv * env, jclass cls)
{
    MC_POOL_BEGIN;
    jobject result = MC_TO_JAVA(IndexSet::indexSet());
    MC_POOL_END;
    return result;
}

JNIEXPORT jobject JNICALL Java_com_libmailcore_IndexSet_indexSetWithRange
  (JNIEnv * env, jclass cls, jobject range)
{
    MC_POOL_BEGIN;
    Range mcRange = rangeFromJava(env, range);
    jobject result = MC_TO_JAVA(IndexSet::indexSetWithRange(mcRange));
    MC_POOL_END;
    return result;
}

JNIEXPORT jobject JNICALL Java_com_libmailcore_IndexSet_indexSetWithIndex
  (JNIEnv * env, jclass cls, jlong idx)
{
    MC_POOL_BEGIN;
    jobject result = MC_TO_JAVA(IndexSet::indexSetWithIndex((uint64_t) idx));
    MC_POOL_END;
    return result;
}

JNIEXPORT jint JNICALL Java_com_libmailcore_IndexSet_count
  (JNIEnv * env, jobject obj)
{
    MC_POOL_BEGIN;
    jint result = MC_JAVA_BRIDGE_GET_SCALAR(jint, count);
    MC_POOL_END;
    return result;
}

JNIEXPORT void JNICALL Java_com_libmailcore_IndexSet_addIndex
  (JNIEnv * env, jobject obj, jlong idx)
{
    MC_POOL_BEGIN;
    MC_JAVA_NATIVE_INSTANCE->addIndex((uint64_t) idx);
    MC_POOL_END;
}

JNIEXPORT void JNICALL Java_com_libmailcore_IndexSet_removeIndex
  (JNIEnv * env, jobject obj, jlong idx)
{
    MC_POOL_BEGIN;
    MC_JAVA_NATIVE_INSTANCE->removeIndex((uint64_t) idx);
    MC_POOL_END;
}

JNIEXPORT jboolean JNICALL Java_com_libmailcore_IndexSet_containsIndex
  (JNIEnv * env, jobject obj, jlong idx)
{
    MC_POOL_BEGIN;
    jboolean result = (jboolean) MC_JAVA_NATIVE_INSTANCE->containsIndex((uint64_t) idx);
    MC_POOL_END;
    return result;
}

JNIEXPORT void JNICALL Java_com_libmailcore_IndexSet_addRange
  (JNIEnv * env, jobject obj, jobject range)
{
    MC_POOL_BEGIN;
    Range mcRange = rangeFromJava(env, range);
    MC_JAVA_NATIVE_INSTANCE->addRange(mcRange);
    MC_POOL_END;
}

JNIEXPORT void JNICALL Java_com_libmailcore_IndexSet_removeRange
  (JNIEnv * env, jobject obj, jobject range)
{
    MC_POOL_BEGIN;
    Range mcRange = rangeFromJava(env, range);
    MC_JAVA_NATIVE_INSTANCE->removeRange(mcRange);
    MC_POOL_END;
}

JNIEXPORT void JNICALL Java_com_libmailcore_IndexSet_intersectsRange
  (JNIEnv * env, jobject obj, jobject range)
{
    MC_POOL_BEGIN;
    Range mcRange = rangeFromJava(env, range);
    MC_JAVA_NATIVE_INSTANCE->intersectsRange(mcRange);
    MC_POOL_END;
}

JNIEXPORT void JNICALL Java_com_libmailcore_IndexSet_addIndexSet
  (JNIEnv * env, jobject obj, jobject otherIndexSet)
{
    MC_POOL_BEGIN;
    MC_JAVA_NATIVE_INSTANCE->addIndexSet(MC_FROM_JAVA(IndexSet, otherIndexSet));
    MC_POOL_END;
}

JNIEXPORT void JNICALL Java_com_libmailcore_IndexSet_removeIndexSet
  (JNIEnv * env, jobject obj, jobject otherIndexSet)
{
    MC_POOL_BEGIN;
    MC_JAVA_NATIVE_INSTANCE->removeIndexSet(MC_FROM_JAVA(IndexSet, otherIndexSet));
    MC_POOL_END;
}

JNIEXPORT void JNICALL Java_com_libmailcore_IndexSet_intersectsIndexSet
  (JNIEnv * env, jobject obj, jobject otherIndexSet)
{
    MC_POOL_BEGIN;
    MC_JAVA_NATIVE_INSTANCE->intersectsIndexSet(MC_FROM_JAVA(IndexSet, otherIndexSet));
    MC_POOL_END;
}

JNIEXPORT jobject JNICALL Java_com_libmailcore_IndexSet_allRanges
  (JNIEnv * env, jobject obj)
{
    MC_POOL_BEGIN;
    jclass cls = env->FindClass("java/util/Vector");
    jmethodID constructor = env->GetMethodID(cls, "<init>", "(I)V");
    unsigned int count = MC_JAVA_NATIVE_INSTANCE->rangesCount();
    jobject javaVector = env->NewObject(cls, constructor, count);
    jmethodID method = env->GetMethodID(cls, "add", "(Ljava/lang/Object;)Z");
    Range * ranges = MC_JAVA_NATIVE_INSTANCE->allRanges();
    for(unsigned int i = 0 ; i < count ; i ++) {
        jobject javaObject = rangeToJava(env, ranges[i]);
        env->CallBooleanMethod(javaVector, method, javaObject);
        env->DeleteLocalRef(javaObject);
    }
    MC_POOL_END;
    return javaVector;
}

JNIEXPORT jint JNICALL Java_com_libmailcore_IndexSet_rangesCount
  (JNIEnv * env, jobject obj)
{
    MC_POOL_BEGIN;
    jint result = MC_JAVA_BRIDGE_GET_SCALAR(jint, rangesCount);
    MC_POOL_END;
    return result;
}

JNIEXPORT void JNICALL Java_com_libmailcore_IndexSet_removeAllIndexes
  (JNIEnv * env, jobject obj)
{
    MC_POOL_BEGIN;
    MC_JAVA_NATIVE_INSTANCE->removeAllIndexes();
    MC_POOL_END;
}

MC_JAVA_BRIDGE
<|endoftext|>


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

#include <string>
#include <vector>
#include <map>
#include <fstream>

#include <Observation.hpp>
#include <utils.hpp>

#ifndef DEDISPERSION_HPP
#define DEDISPERSION_HPP

namespace PulsarSearch {

class DedispersionConf {
public:
  DedispersionConf();
  ~DedispersionConf();

  // Get
  bool getLocalMem() const;
  unsigned int getNrSamplesPerBlock() const;
  unsigned int getNrSamplesPerThread() const;
  unsigned int getNrDMsPerBlock() const;
  unsigned int getNrDMsPerThread() const;
  unsigned int getUnroll() const;
  // Set
  void setLocalMem(bool local);
  void setNrSamplesPerBlock(unsigned int samples);
  void setNrSamplesPerThread(unsigned int samples);
  void setNrDMsPerBlock(unsigned int dms);
  void setNrDMsPerThread(unsigned int dms);
  void setUnroll(unsigned int unroll);
  // Utils
  std::string print() const;

private:
  bool local;
  unsigned int nrSamplesPerBlock;
  unsigned int nrSamplesPerThread;
  unsigned int nrDMsPerBlock;
  unsigned int nrDMsPerThread;
  unsigned int unroll;
};

typedef std::map< std::string, std::map< unsigned int, PulsarSearch::DedispersionConf > > tunedDedispersionConf;

// Sequential dedispersion
template< typename T > void dedispersion(AstroData::Observation & observation, const std::vector< T > & input, std::vector< T > & output, const std::vector< float > & shifts);
// OpenCL dedispersion algorithm
std::string * getDedispersionOpenCL(const DedispersionConf & conf, const std::string & dataType, const AstroData::Observation & observation, std::vector< float > & shifts);
// Read configuration files
void readTunedDedispersionConf(tunedDedispersionConf & tunedDedispersion, const std::string & dedispersionFilename);

// Implementations
template< typename T > void dedispersion(AstroData::Observation & observation, const std::vector< T > & input, std::vector< T > & output, const std::vector< float > & shifts) {
	for ( unsigned int dm = 0; dm < observation.getNrDMs(); dm++ ) {
		for ( unsigned int sample = 0; sample < observation.getNrSamplesPerSecond(); sample++ ) {
			T dedispersedSample = static_cast< T >(0);

			for ( unsigned int channel = 0; channel < observation.getNrChannels(); channel++ ) {
				unsigned int shift = static_cast< unsigned int >(((observation.getFirstDM() + (dm * observation.getDMStep())) * shifts[channel]) * observation.getNrSamplesPerSecond());

				dedispersedSample += input[(channel * observation.getNrSamplesPerDispersedChannel()) + (sample + shift)];
			}

			output[(dm * observation.getNrSamplesPerPaddedSecond()) + sample] = dedispersedSample;
		}
	}
}

inline bool DedispersionConf::getLocalMem() const {
  return local;
}

inline unsigned int DedispersionConf::getNrSamplesPerBlock() const {
  return nrSamplesPerBlock;
}

inline unsigned int DedispersionConf::getNrSamplesPerThread() const {
  return nrSamplesPerThread;
}

inline unsigned int DedispersionConf::getNrDMsPerBlock() const {
  return nrDMsPerBlock;
}

inline unsigned int DedispersionConf::getNrDMsPerThread() const {
  return nrDMsPerThread;
}

inline unsigned int DedispersionConf::getUnroll() const {
  return unroll;
}

inline void DedispersionConf::setLocalMem(bool local) {
  this->local = local;
}

inline void DedispersionConf::setNrSamplesPerBlock(unsigned int samples) {
  nrSamplesPerBlock = samples;
}

inline void DedispersionConf::setNrSamplesPerThread(unsigned int samples) {
  nrSamplesPerThread = samples;
}

inline void DedispersionConf::setNrDMsPerBlock(unsigned int dms) {
  nrDMsPerBlock = dms;
}

inline void DedispersionConf::setNrDMsPerThread(unsigned int dms) {
  nrDMsPerThread = dms;
}

inline void DedispersionConf::setUnroll(unsigned int unroll) {
  this->unroll = unroll;
}

} // PulsarSearch

#endif // DEDISPERSION_HPP

<commit_msg>Revert "Fixed a bug in the sequantial dedispersion. OpenCL fix (the same) coming"<commit_after>// Copyright 2014 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <string>
#include <vector>
#include <map>
#include <fstream>

#include <Observation.hpp>
#include <utils.hpp>

#ifndef DEDISPERSION_HPP
#define DEDISPERSION_HPP

namespace PulsarSearch {

class DedispersionConf {
public:
  DedispersionConf();
  ~DedispersionConf();

  // Get
  bool getLocalMem() const;
  unsigned int getNrSamplesPerBlock() const;
  unsigned int getNrSamplesPerThread() const;
  unsigned int getNrDMsPerBlock() const;
  unsigned int getNrDMsPerThread() const;
  unsigned int getUnroll() const;
  // Set
  void setLocalMem(bool local);
  void setNrSamplesPerBlock(unsigned int samples);
  void setNrSamplesPerThread(unsigned int samples);
  void setNrDMsPerBlock(unsigned int dms);
  void setNrDMsPerThread(unsigned int dms);
  void setUnroll(unsigned int unroll);
  // Utils
  std::string print() const;

private:
  bool local;
  unsigned int nrSamplesPerBlock;
  unsigned int nrSamplesPerThread;
  unsigned int nrDMsPerBlock;
  unsigned int nrDMsPerThread;
  unsigned int unroll;
};

typedef std::map< std::string, std::map< unsigned int, PulsarSearch::DedispersionConf > > tunedDedispersionConf;

// Sequential dedispersion
template< typename T > void dedispersion(AstroData::Observation & observation, const std::vector< T > & input, std::vector< T > & output, const std::vector< float > & shifts);
// OpenCL dedispersion algorithm
std::string * getDedispersionOpenCL(const DedispersionConf & conf, const std::string & dataType, const AstroData::Observation & observation, std::vector< float > & shifts);
// Read configuration files
void readTunedDedispersionConf(tunedDedispersionConf & tunedDedispersion, const std::string & dedispersionFilename);

// Implementations
template< typename T > void dedispersion(AstroData::Observation & observation, const std::vector< T > & input, std::vector< T > & output, const std::vector< float > & shifts) {
	for ( unsigned int dm = 0; dm < observation.getNrDMs(); dm++ ) {
		for ( unsigned int sample = 0; sample < observation.getNrSamplesPerSecond(); sample++ ) {
			T dedispersedSample = static_cast< T >(0);

			for ( unsigned int channel = 0; channel < observation.getNrChannels(); channel++ ) {
				unsigned int shift = static_cast< unsigned int >((observation.getFirstDM() + (dm * observation.getDMStep())) * shifts[channel]);

				dedispersedSample += input[(channel * observation.getNrSamplesPerDispersedChannel()) + (sample + shift)];
			}

			output[(dm * observation.getNrSamplesPerPaddedSecond()) + sample] = dedispersedSample;
		}
	}
}

inline bool DedispersionConf::getLocalMem() const {
  return local;
}

inline unsigned int DedispersionConf::getNrSamplesPerBlock() const {
  return nrSamplesPerBlock;
}

inline unsigned int DedispersionConf::getNrSamplesPerThread() const {
  return nrSamplesPerThread;
}

inline unsigned int DedispersionConf::getNrDMsPerBlock() const {
  return nrDMsPerBlock;
}

inline unsigned int DedispersionConf::getNrDMsPerThread() const {
  return nrDMsPerThread;
}

inline unsigned int DedispersionConf::getUnroll() const {
  return unroll;
}

inline void DedispersionConf::setLocalMem(bool local) {
  this->local = local;
}

inline void DedispersionConf::setNrSamplesPerBlock(unsigned int samples) {
  nrSamplesPerBlock = samples;
}

inline void DedispersionConf::setNrSamplesPerThread(unsigned int samples) {
  nrSamplesPerThread = samples;
}

inline void DedispersionConf::setNrDMsPerBlock(unsigned int dms) {
  nrDMsPerBlock = dms;
}

inline void DedispersionConf::setNrDMsPerThread(unsigned int dms) {
  nrDMsPerThread = dms;
}

inline void DedispersionConf::setUnroll(unsigned int unroll) {
  this->unroll = unroll;
}

} // PulsarSearch

#endif // DEDISPERSION_HPP

<|endoftext|>


<commit_before><commit_msg>mroe return value stuff<commit_after><|endoftext|>