/srv/osrm/osrm-backend/include/util
Edit: /srv/osrm/osrm-backend/include/util/geojson_debug_logger.hpp (6330B)
#ifndef OSRM_GEOJSON_DEBUG_LOGGER_HPP
#define OSRM_GEOJSON_DEBUG_LOGGER_HPP
#include
#include
#include
#include
#include "util/exception.hpp"
#include "util/json_container.hpp"
#include "util/json_renderer.hpp"
#include "util/log.hpp"
namespace osrm::util
{
// in case we want to do scenario-based logging, we can specify a dedicated logging scenario to be
// able to use multiple files for the same converter
enum class LoggingScenario
{
eDefault = 0
};
// forward declaration to become friends
template class ScopedGeojsonLoggerGuard;
// a geojson logger requires a conversion policy to transfer arbitrary input into viable geojson.
// features of the same kind are stored in the same geojson file
template
class GeojsonLogger
{
// become friends with the guard
friend class ScopedGeojsonLoggerGuard;
// having these private enforces the guard to be used to initialise/close/write
private:
// cannot lock, is tooling for locked function
static void output(bool first, const util::json::Object &object)
{
if (!first)
ofs << ",\n\t\t";
// objects are simply forwarded
util::json::render(ofs, object);
}
// cannot lock, is tooling for locked function
static void output(bool first, const util::json::Array &array)
{
for (const auto &object : array.values)
{
if (!first)
ofs << ",\n\t\t";
util::json::render(ofs, object.get());
first = false;
}
}
// writes a single feature into the Geojson file
template static bool Write(Args &&... args)
{
// make sure to syncronize logging output, our writing should be sequential
std::lock_guard guard(lock);
// if there is no logfile, we cannot write (possible reason: the guard might be out of scope
// (e.g. if it is anonymous))
if (!ofs.is_open() || (nullptr == policy))
{
throw util::exception("Trying to use the geojson printer without an open logger.");
}
// use our policy to convert the arguments into geojson, this can be done in parallel
const auto json_object = (*policy)(std::forward(args)...);
// different features are separated by `,`
// since we are not building a full json collection of features, we have to do some of the
// bookeeping ourselves. This prevens us from doing one huge json object, if we are
// processing larger results
output(first, json_object);
first = false;
return static_cast(ofs);
}
// Opening a logger, we initialize a geojson feature collection
// to be later filled with additional data
static bool Open(const std::string &logfile)
{
// if a file is open, close it off. When this function returns, there should be an open
// logfile. However, there is a brief period between closing and openen where we could miss
// out on log output. Such a sad life
if (ofs.is_open())
{
util::Log(logWARNING)
<< "Overwriting " << logfile
<< ". Is this desired behaviour? If this message occurs more than once rethink the "
"location of your Logger Guard.";
Close();
}
// make sure to syncronize logging output, cannot be locked earlier, since Close also locks
// and we don't want deadlocks
std::lock_guard guard(lock);
ofs.open(logfile, std::ios::binary);
ofs << std::setprecision(12);
// set up a feature collection
ofs << "{\n\t\"type\": \"FeatureCollection\",\n\t\"features\": [\n\t";
// remember whether we need to output a colon
first = true;
return static_cast(ofs);
}
// finalising touches on the GeoJson
static bool Close()
{
// make sure to syncronize logging output
std::lock_guard guard(lock);
// finishe the geojson feature collection and close it all off
if (ofs.is_open())
{
ofs << "\n\t]\n}";
ofs.close();
}
return static_cast(ofs);
}
static void SetPolicy(geojson_conversion_policy *new_policy) { policy = new_policy; }
private:
static bool first;
static std::mutex lock;
static std::ofstream ofs;
static geojson_conversion_policy *policy;
};
// make sure to do opening and closing of our guard
template
class ScopedGeojsonLoggerGuard
{
public:
template
ScopedGeojsonLoggerGuard(const std::string &logfile, Args &&... args)
: policy(std::forward(args)...)
{
GeojsonLogger::Open(logfile);
GeojsonLogger::SetPolicy(&policy);
}
~ScopedGeojsonLoggerGuard()
{
GeojsonLogger::Close();
GeojsonLogger::SetPolicy(nullptr);
}
template static bool Write(Args &&... args)
{
return GeojsonLogger::Write(
std::forward(args)...);
}
private:
geojson_conversion_policy policy;
};
template
bool GeojsonLogger::first;
template
std::mutex GeojsonLogger::lock;
template
std::ofstream GeojsonLogger::ofs;
template
geojson_conversion_policy *GeojsonLogger::policy;
} // namespace osrm::util
#endif /* OSRM_GEOJSON_DEBUG_LOGGER_HPP */