Skip to content

Commit

Permalink
Merge pull request #232 from mmd-osm/patch/settings
Browse files Browse the repository at this point in the history
Make MAX_NODES and MAX_AREA values configurable (2)
  • Loading branch information
mmd-osm authored Jun 19, 2020
2 parents dcb2351 + c4787de commit 1b2ef28
Show file tree
Hide file tree
Showing 21 changed files with 396 additions and 76 deletions.
5 changes: 3 additions & 2 deletions include/cgimap/api06/changeset_upload/way.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define WAY_HPP

#include "osmobject.hpp"
#include "cgimap/options.hpp"

#include <string>
#include <vector>
Expand Down Expand Up @@ -55,12 +56,12 @@ class Way : public OSMObject {
.str());
}

if (m_way_nodes.size() > WAY_MAX_NODES) {
if (m_way_nodes.size() > global_settings::get_way_max_nodes()) {
throw http::bad_request(
(boost::format(
"You tried to add %1% nodes to way %2%, however only "
"%3% are allowed") %
m_way_nodes.size() % (has_id() ? id() : 0) % WAY_MAX_NODES)
m_way_nodes.size() % (has_id() ? id() : 0) % global_settings::get_way_max_nodes())
.str());
}

Expand Down
2 changes: 0 additions & 2 deletions include/cgimap/backend/apidb/apidb.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@

#include <memory>

#define SCALE (10000000)

std::shared_ptr<backend> make_apidb_backend();

#endif /* APIDB_BACKEND_HPP */
2 changes: 0 additions & 2 deletions include/cgimap/backend/staticxml/staticxml.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@

#include <memory>

#define SCALE (10000000)

std::shared_ptr<backend> make_staticxml_backend();

#endif /* STATICXML_BACKEND_HPP */
170 changes: 170 additions & 0 deletions include/cgimap/options.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
#ifndef OPTIONS_HPP
#define OPTIONS_HPP

#include <memory>
#include <regex>
#include <boost/program_options.hpp>

namespace po = boost::program_options;

class global_settings_base {

public:
virtual ~global_settings_base();

virtual long get_payload_max_size() const = 0;
virtual int get_map_max_nodes() const = 0;
virtual double get_map_area_max() const = 0;
virtual std::string get_changeset_timeout_open_max() const = 0;
virtual std::string get_changeset_timeout_idle() const = 0;
virtual int get_changeset_max_elements() const = 0;
virtual int get_way_max_nodes() const = 0;
virtual long get_scale() const = 0;
};

class global_settings_default : public global_settings_base {

public:
long get_payload_max_size() const override {
return 50000000L;
}

int get_map_max_nodes() const override {
return 50000;
}

double get_map_area_max() const override {
return 0.25;
}

std::string get_changeset_timeout_open_max() const override {
return "1 day";
}

std::string get_changeset_timeout_idle() const override {
return "1 hour";
}

int get_changeset_max_elements() const override {
return 10000;
}

int get_way_max_nodes() const override {
return 2000;
}

long get_scale() const override {
return 10000000L;
}
};

class global_settings_via_options : public global_settings_base {

public:
global_settings_via_options() = delete;

global_settings_via_options(const po::variables_map & options) {

init_fallback_values(global_settings_default{}); // use default values as fallback
set_new_options(options);
}

global_settings_via_options(const po::variables_map & options,
const global_settings_base & fallback) {

init_fallback_values(fallback);
set_new_options(options);
}

long get_payload_max_size() const override {
return m_payload_max_size;
}

int get_map_max_nodes() const override {
return m_map_max_nodes;
}

double get_map_area_max() const override {
return m_map_area_max;
}

std::string get_changeset_timeout_open_max() const override {
return m_changeset_timeout_open_max;
}

std::string get_changeset_timeout_idle() const override {
return m_changeset_timeout_idle;
}

int get_changeset_max_elements() const override {
return m_changeset_max_elements;
}

int get_way_max_nodes() const override {
return m_way_max_nodes;
}

long get_scale() const override {
return m_scale;
}

private:
void init_fallback_values(const global_settings_base & def);
void set_new_options(const po::variables_map & options);
void set_payload_max_size(const po::variables_map & options);
void set_map_max_nodes(const po::variables_map & options);
void set_map_area_max(const po::variables_map & options);
void set_changeset_timeout_open_max(const po::variables_map & options);
void set_changeset_timeout_idle(const po::variables_map & options);
void set_changeset_max_elements(const po::variables_map & options);
void set_way_max_nodes(const po::variables_map & options);
void set_scale(const po::variables_map & options);
bool validate_timeout(const std::string &timeout) const;

long m_payload_max_size;
int m_map_max_nodes;
double m_map_area_max;
std::string m_changeset_timeout_open_max;
std::string m_changeset_timeout_idle;
int m_changeset_max_elements;
int m_way_max_nodes;
long m_scale;
};

class global_settings final {

public:
global_settings() = delete;

static void set_configuration(std::unique_ptr<global_settings_base> && b) { settings = std::move(b); }

// Maximum Size of HTTP body payload accepted by uploads, after decompression
static long get_payload_max_size() { return settings->get_payload_max_size(); }

// Maximum number of nodes returned by the /map endpoint
static int get_map_max_nodes() { return settings->get_map_max_nodes(); }

// Maximum permitted area for /map endpoint
static double get_map_area_max() { return settings->get_map_area_max(); }

// Maximum permitted open time period for a changeset
static std::string get_changeset_timeout_open_max() { return settings->get_changeset_timeout_open_max(); }

// Time period that a changeset will remain open after the last edit
static std::string get_changeset_timeout_idle() { return settings->get_changeset_timeout_idle(); }

// Maximum number of elements permitted in one changeset
static int get_changeset_max_elements() { return settings->get_changeset_max_elements(); }

// Maximum number of nodes permitted in a way
static int get_way_max_nodes() { return settings->get_way_max_nodes(); }

// Conversion factor from double lat/lon format to internal int format used for db persistence
static long get_scale() { return settings->get_scale(); }

private:
static std::unique_ptr<global_settings_base> settings; // gets initialized with global_settings_default instance
};

#endif

21 changes: 9 additions & 12 deletions include/cgimap/util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "infix_ostream_iterator.hpp"
#include "cgimap/http.hpp"
#include "cgimap/logger.hpp"
#include "cgimap/options.hpp"

#include <algorithm>
#include <clocale>
Expand All @@ -16,16 +17,6 @@
#include <string>



const int CHANGESET_MAX_ELEMENTS = 10000;
const int WAY_MAX_NODES = 2000;
const long SCALE = 10000000;

const std::string MAX_TIME_OPEN = "1 day";
const std::string IDLE_TIMEOUT = "1 hour";



inline size_t unicode_strlen(const std::string & s)
{
const char* mbstr = s.c_str();
Expand Down Expand Up @@ -92,10 +83,16 @@ class bbox_t {
long maxlat;
long maxlon;

bbox_t() : minlat(200 * SCALE), minlon(200 * SCALE), maxlat(-200 * SCALE), maxlon(-200 * SCALE) {};
bbox_t() : minlat(200 * global_settings::get_scale()),
minlon(200 * global_settings::get_scale()),
maxlat(-200 * global_settings::get_scale()),
maxlon(-200 * global_settings::get_scale()) {};

bbox_t(double _minlat, double _minlon, double _maxlat, double _maxlon) :
minlat(_minlat * SCALE), minlon(_minlon * SCALE), maxlat(_maxlat * SCALE), maxlon(_maxlon * SCALE) {};
minlat(_minlat * global_settings::get_scale()),
minlon(_minlon * global_settings::get_scale()),
maxlat(_maxlat * global_settings::get_scale()),
maxlon(_maxlon * global_settings::get_scale()) {};

void expand(const bbox_t& bbox)
{
Expand Down
3 changes: 3 additions & 0 deletions openstreetmap-cgimap.1
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ Write pid to \fIPIDFILE\fR.
.BR \-\-logfile =\fILOGFILE\fR
File to write log messages to.
.TP
.BR \-\-configfile =\fICONFIGFILE\fR
File to read configuration values from.
.TP
.BR \-\-memcache =\fISPEC\fR
Memcache server specification.
.TP
Expand Down
1 change: 1 addition & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ libcgimap_core_la_SOURCES=\
mime_types.cpp \
basicauth.cpp \
oauth.cpp \
options.cpp \
osm_responder.cpp \
osm_current_responder.cpp \
osm_diffresult_responder.cpp \
Expand Down
16 changes: 7 additions & 9 deletions src/api06/map_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#include "cgimap/http.hpp"
#include "cgimap/request_helpers.hpp"
#include "cgimap/logger.hpp"
#include "cgimap/options.hpp"

#include <boost/format.hpp>
#include <map>

Expand All @@ -12,23 +14,20 @@ using std::map;
using std::pair;
using std::vector;

constexpr double MAX_AREA = 0.25;
constexpr int MAX_NODES = 50000;

namespace api06 {

map_responder::map_responder(mime::type mt, bbox b, data_selection_ptr &x)
: osm_current_responder(mt, x, boost::optional<bbox>(b)) {
// create temporary tables of nodes, ways and relations which
// are in or used by elements in the bbox
int num_nodes = sel->select_nodes_from_bbox(b, MAX_NODES);
int num_nodes = sel->select_nodes_from_bbox(b, global_settings::get_map_max_nodes());

// TODO: make configurable parameter?
if (num_nodes > MAX_NODES) {
if (num_nodes > global_settings::get_map_max_nodes()) {
throw http::bad_request(
(format("You requested too many nodes (limit is %1%). "
"Either request a smaller area, or use planet.osm") %
MAX_NODES).str());
global_settings::get_map_max_nodes()).str());
}
// Short-circuit empty areas
if (num_nodes > 0) {
Expand Down Expand Up @@ -102,13 +101,12 @@ bbox map_handler::validate_request(request &req) {
"minima must be less than the maxima.");
}

// TODO: make configurable parameter?
if (bounds.area() > MAX_AREA) {
if (bounds.area() > global_settings::get_map_area_max()) {
throw http::bad_request(
(boost::format("The maximum bbox size is %1%, and your request "
"was too large. Either request a smaller area, or use "
"planet.osm") %
MAX_AREA).str());
global_settings::get_map_area_max()).str());
}

return bounds;
Expand Down
12 changes: 6 additions & 6 deletions src/api07/map_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "cgimap/http.hpp"
#include "cgimap/request_helpers.hpp"
#include "cgimap/logger.hpp"
#include "cgimap/options.hpp"
#include <boost/format.hpp>
#include <map>

Expand All @@ -19,14 +20,13 @@ map_responder::map_responder(mime::type mt, bbox b, data_selection_ptr &x)
: osm_current_responder(mt, x, boost::optional<bbox>(b)) {
// create temporary tables of nodes, ways and relations which
// are in or used by elements in the bbox
int num_nodes = sel->select_nodes_from_bbox(b, MAX_NODES);
int num_nodes = sel->select_nodes_from_bbox(b, global_settings::get_map_max_nodes());

// TODO: make configurable parameter?
if (num_nodes > MAX_NODES) {
if (num_nodes > global_settings::get_map_max_nodes()) {
throw http::bad_request(
(format("You requested too many nodes (limit is %1%). "
"Either request a smaller area, or use planet.osm") %
MAX_NODES).str());
global_settings::get_map_max_nodes()).str());
}
// Short-circuit empty areas
if (num_nodes > 0) {
Expand Down Expand Up @@ -89,12 +89,12 @@ bbox map_handler::validate_request(request &req) {
}

// TODO: make configurable parameter?
if (bounds.area() > MAX_AREA) {
if (bounds.area() > global_settings::get_map_area_max()) {
throw http::bad_request(
(boost::format("The maximum bbox size is %1%, and your request "
"was too large. Either request a smaller area, or use "
"planet.osm") %
MAX_AREA).str());
global_settings::get_map_area_max()).str());
}

return bounds;
Expand Down
4 changes: 2 additions & 2 deletions src/backend/apidb/apidb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "cgimap/backend/apidb/pgsql_update.hpp"
#include "cgimap/backend/apidb/oauth_store.hpp"
#include "cgimap/backend.hpp"
#include "cgimap/options.hpp"

#include <memory>
#include <sstream>
Expand All @@ -11,7 +12,6 @@ namespace po = boost::program_options;
using std::shared_ptr;
using std::string;

#define CACHE_SIZE 100000

namespace {
struct apidb_backend : public backend {
Expand All @@ -26,7 +26,7 @@ struct apidb_backend : public backend {
"database character set")
("readonly", "(obsolete parameter, read only backend is always assumed)")
("disable-api-write", "disable API write operations")
("cachesize", po::value<size_t>()->default_value(CACHE_SIZE),
("cachesize", po::value<size_t>()->default_value(100000),
"maximum size of changeset cache")
("dbport", po::value<string>(),
"database port number or UNIX socket file name")
Expand Down
Loading

0 comments on commit 1b2ef28

Please # to comment.