Exemple #1
0
PBFParser::PBFParser(const char *fileName,
                     ExtractorCallbacks *extractor_callbacks,
                     ScriptingEnvironment &scripting_environment,
                     const bool use_elevation,
                     unsigned num_threads)
    : BaseParser(extractor_callbacks, scripting_environment, use_elevation)
{
    if (0 == num_threads)
    {
        num_parser_threads = tbb::task_scheduler_init::default_num_threads();
    }
    else
    {
        num_parser_threads = num_threads;
    }

    GOOGLE_PROTOBUF_VERIFY_VERSION;
    // TODO: What is the bottleneck here? Filling the queue or reading the stuff from disk?
    // NOTE: With Lua scripting, it is parsing the stuff. I/O is virtually for free.

    // Max 2500 items in queue, hardcoded.
    thread_data_queue = std::make_shared<ConcurrentQueue<ParserThreadData *>>(2500);
    input.open(fileName, std::ios::in | std::ios::binary);

    if (!input)
    {
        throw OSRMException("pbf file not found.");
    }

    block_count = 0;
    group_count = 0;
}
void BaseParser::ReadUseRestrictionsSetting() {
    if( 0 != luaL_dostring( lua_state, "return use_turn_restrictions\n") ) {
        throw OSRMException("ERROR occured in scripting block");
    }
    if( lua_isboolean( lua_state, -1) ) {
        use_turn_restrictions = lua_toboolean(lua_state, -1);
    }
    if( use_turn_restrictions ) {
        SimpleLogger().Write() << "Using turn restrictions";
    } else {
        SimpleLogger().Write() << "Ignoring turn restrictions";
    }
}
Exemple #3
0
PBFParser::PBFParser(const char * fileName, ExtractorCallbacks* ec, ScriptingEnvironment& se) : BaseParser( ec, se ) {
	GOOGLE_PROTOBUF_VERIFY_VERSION;
	//TODO: What is the bottleneck here? Filling the queue or reading the stuff from disk?
	//NOTE: With Lua scripting, it is parsing the stuff. I/O is virtually for free.
	threadDataQueue = boost::make_shared<ConcurrentQueue<_ThreadData*> >( 2500 ); /* Max 2500 items in queue, hardcoded. */
	input.open(fileName, std::ios::in | std::ios::binary);

	if (!input) {
		throw OSRMException("pbf file not found.");
	}

#ifndef NDEBUG
	blockCount = 0;
	groupCount = 0;
#endif
}
QueryObjectsStorage::QueryObjectsStorage(
	const std::string & hsgrPath,
	const std::string & ramIndexPath,
	const std::string & fileIndexPath,
	const std::string & nodesPath,
	const std::string & edgesPath,
	const std::string & namesPath,
	const std::string & timestampPath
) {
	if( hsgrPath.empty() ) {
		throw OSRMException("no hsgr file given in ini file");
	}
	if( ramIndexPath.empty() ) {
		throw OSRMException("no ram index file given in ini file");
	}
	if( fileIndexPath.empty() ) {
		throw OSRMException("no mem index file given in ini file");
	}
	if( nodesPath.empty() ) {
		throw OSRMException("no nodes file given in ini file");
	}
	if( edgesPath.empty() ) {
		throw OSRMException("no edges file given in ini file");
	}
	if( namesPath.empty() ) {
		throw OSRMException("no names file given in ini file");
	}

	SimpleLogger().Write() << "loading graph data";
	//Deserialize road network graph
	std::vector< QueryGraph::_StrNode> nodeList;
	std::vector< QueryGraph::_StrEdge> edgeList;
	const int n = readHSGRFromStream(
		hsgrPath,
		nodeList,
		edgeList,
		&checkSum
	);

	SimpleLogger().Write() << "Data checksum is " << checkSum;
	graph = new QueryGraph(nodeList, edgeList);
	assert(0 == nodeList.size());
	assert(0 == edgeList.size());

	if(timestampPath.length()) {
	    SimpleLogger().Write() << "Loading Timestamp";
	    std::ifstream timestampInStream(timestampPath.c_str());
	    if(!timestampInStream) {
	    	SimpleLogger().Write(logWARNING) <<  timestampPath <<  " not found";
	    }

	    getline(timestampInStream, timestamp);
	    timestampInStream.close();
	}
	if(!timestamp.length()) {
	    timestamp = "n/a";
	}
	if(25 < timestamp.length()) {
	    timestamp.resize(25);
	}

    SimpleLogger().Write() << "Loading auxiliary information";
    //Init nearest neighbor data structure
	nodeHelpDesk = new NodeInformationHelpDesk(
		ramIndexPath,
		fileIndexPath,
		nodesPath,
		edgesPath,
		n,
		checkSum
	);

	//deserialize street name list
	SimpleLogger().Write() << "Loading names index";
	boost::filesystem::path names_file(namesPath);

    if ( !boost::filesystem::exists( names_file ) ) {
        throw OSRMException("names file does not exist");
    }
    if ( 0 == boost::filesystem::file_size( names_file ) ) {
        throw OSRMException("names file is empty");
    }

	boost::filesystem::ifstream name_stream(names_file, std::ios::binary);
	unsigned size = 0;
	name_stream.read((char *)&size, sizeof(unsigned));
	BOOST_ASSERT_MSG(0 != size, "name file empty");

	char buf[1024];
	for( unsigned i = 0; i < size; ++i ) {
		unsigned size_of_string = 0;
		name_stream.read((char *)&size_of_string, sizeof(unsigned));
		buf[size_of_string] = '\0'; // instead of memset
		name_stream.read(buf, size_of_string);
		names.push_back(buf);
	}
	std::vector<std::string>(names).swap(names);
	BOOST_ASSERT_MSG(0 != names.size(), "could not load any names");
	name_stream.close();
	SimpleLogger().Write() << "All query data structures loaded";
}
void ExtractionContainers::PrepareData(const std::string &output_file_name,
                                       const std::string &restrictions_file_name)
{
    try
    {
        unsigned number_of_used_nodes = 0;
        unsigned number_of_used_edges = 0;
        std::chrono::time_point<std::chrono::steady_clock> time1 = std::chrono::steady_clock::now();

        std::cout << "[extractor] Sorting used nodes        ... " << std::flush;
        stxxl::sort(used_node_id_list.begin(), used_node_id_list.end(), Cmp(), stxxl_memory);
        std::chrono::time_point<std::chrono::steady_clock> time2 = std::chrono::steady_clock::now();
        std::chrono::duration<double> elapsed_seconds = time2 - time1;
        std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;

        time1 = std::chrono::steady_clock::now();
        std::cout << "[extractor] Erasing duplicate nodes   ... " << std::flush;
        auto new_end = std::unique(used_node_id_list.begin(), used_node_id_list.end());
        used_node_id_list.resize(new_end - used_node_id_list.begin());
        time2 = std::chrono::steady_clock::now();
        elapsed_seconds = time2 - time1;
        std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;

        time1 = std::chrono::steady_clock::now();

        std::cout << "[extractor] Sorting all nodes         ... " << std::flush;
        stxxl::sort(all_nodes_list.begin(), all_nodes_list.end(), CmpNodeByID(), stxxl_memory);
        time2 = std::chrono::steady_clock::now();
        elapsed_seconds = time2 - time1;
        std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;

        time1 = std::chrono::steady_clock::now();

        std::cout << "[extractor] Sorting used ways         ... " << std::flush;
        stxxl::sort(
            way_start_end_id_list.begin(), way_start_end_id_list.end(), CmpWayByID(), stxxl_memory);
        time2 = std::chrono::steady_clock::now();
        elapsed_seconds = time2 - time1;
        std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;

        std::cout << "[extractor] Sorting restrictions. by from... " << std::flush;
        stxxl::sort(restrictions_list.begin(),
                    restrictions_list.end(),
                    CmpRestrictionContainerByFrom(),
                    stxxl_memory);
        time2 = std::chrono::steady_clock::now();
        elapsed_seconds = time2 - time1;
        std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;

        std::cout << "[extractor] Fixing restriction starts ... " << std::flush;
        auto restrictions_iterator = restrictions_list.begin();
        auto way_start_and_end_iterator = way_start_end_id_list.begin();

        while (way_start_and_end_iterator != way_start_end_id_list.end() &&
               restrictions_iterator != restrictions_list.end())
        {
            if (way_start_and_end_iterator->wayID < restrictions_iterator->fromWay)
            {
                ++way_start_and_end_iterator;
                continue;
            }

            if (way_start_and_end_iterator->wayID > restrictions_iterator->fromWay)
            {
                ++restrictions_iterator;
                continue;
            }

            BOOST_ASSERT(way_start_and_end_iterator->wayID == restrictions_iterator->fromWay);
            const NodeID via_node_id = restrictions_iterator->restriction.viaNode;

            if (way_start_and_end_iterator->firstStart == via_node_id)
            {
                restrictions_iterator->restriction.fromNode =
                    way_start_and_end_iterator->firstTarget;
            }
            else if (way_start_and_end_iterator->firstTarget == via_node_id)
            {
                restrictions_iterator->restriction.fromNode =
                    way_start_and_end_iterator->firstStart;
            }
            else if (way_start_and_end_iterator->lastStart == via_node_id)
            {
                restrictions_iterator->restriction.fromNode =
                    way_start_and_end_iterator->lastTarget;
            }
            else if (way_start_and_end_iterator->lastTarget == via_node_id)
            {
                restrictions_iterator->restriction.fromNode = way_start_and_end_iterator->lastStart;
            }
            ++restrictions_iterator;
        }

        time2 = std::chrono::steady_clock::now();
        elapsed_seconds = time2 - time1;
        std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;

        time1 = std::chrono::steady_clock::now();

        std::cout << "[extractor] Sorting restrictions. by to  ... " << std::flush;
        stxxl::sort(restrictions_list.begin(),
                    restrictions_list.end(),
                    CmpRestrictionContainerByTo(),
                    stxxl_memory);
        time2 = std::chrono::steady_clock::now();
        elapsed_seconds = time2 - time1;
        std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;

        time1 = std::chrono::steady_clock::now();
        unsigned number_of_useable_restrictions = 0;
        std::cout << "[extractor] Fixing restriction ends   ... " << std::flush;
        restrictions_iterator = restrictions_list.begin();
        way_start_and_end_iterator = way_start_end_id_list.begin();
        while (way_start_and_end_iterator != way_start_end_id_list.end() &&
               restrictions_iterator != restrictions_list.end())
        {
            if (way_start_and_end_iterator->wayID < restrictions_iterator->toWay)
            {
                ++way_start_and_end_iterator;
                continue;
            }
            if (way_start_and_end_iterator->wayID > restrictions_iterator->toWay)
            {
                ++restrictions_iterator;
                continue;
            }
            NodeID via_node_id = restrictions_iterator->restriction.viaNode;
            if (way_start_and_end_iterator->lastStart == via_node_id)
            {
                restrictions_iterator->restriction.toNode = way_start_and_end_iterator->lastTarget;
            }
            else if (way_start_and_end_iterator->lastTarget == via_node_id)
            {
                restrictions_iterator->restriction.toNode = way_start_and_end_iterator->lastStart;
            }
            else if (way_start_and_end_iterator->firstStart == via_node_id)
            {
                restrictions_iterator->restriction.toNode = way_start_and_end_iterator->firstTarget;
            }
            else if (way_start_and_end_iterator->firstTarget == via_node_id)
            {
                restrictions_iterator->restriction.toNode = way_start_and_end_iterator->firstStart;
            }

            if (std::numeric_limits<unsigned>::max() != restrictions_iterator->restriction.fromNode &&
                std::numeric_limits<unsigned>::max() != restrictions_iterator->restriction.toNode)
            {
                ++number_of_useable_restrictions;
            }
            ++restrictions_iterator;
        }
        time2 = std::chrono::steady_clock::now();
        elapsed_seconds = time2 - time1;
        std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;

        SimpleLogger().Write() << "usable restrictions: " << number_of_useable_restrictions;
        // serialize restrictions
        std::ofstream restrictions_out_stream;
        restrictions_out_stream.open(restrictions_file_name.c_str(), std::ios::binary);
        restrictions_out_stream.write((char *)&uuid, sizeof(UUID));
        restrictions_out_stream.write((char *)&number_of_useable_restrictions, sizeof(unsigned));
        // for (restrictions_iterator = restrictions_list.begin();
        //      restrictions_iterator != restrictions_list.end();
        //      ++restrictions_iterator)
        for(const auto & restriction_container : restrictions_list)
        {
            if (std::numeric_limits<unsigned>::max() != restriction_container.restriction.fromNode &&
                std::numeric_limits<unsigned>::max() != restriction_container.restriction.toNode)
            {
                restrictions_out_stream.write((char *)&(restriction_container.restriction),
                                              sizeof(TurnRestriction));
            }
        }
        restrictions_out_stream.close();

        std::ofstream file_out_stream;
        file_out_stream.open(output_file_name.c_str(), std::ios::binary);
        file_out_stream.write((char *)&uuid, sizeof(UUID));
        file_out_stream.write((char *)&number_of_used_nodes, sizeof(unsigned));
        time1 = std::chrono::steady_clock::now();
        std::cout << "[extractor] Confirming/Writing used nodes     ... " << std::flush;

        // identify all used nodes by a merging step of two sorted lists
        auto node_iterator = all_nodes_list.begin();
        auto node_id_iterator = used_node_id_list.begin();
        while (node_id_iterator != used_node_id_list.end() && node_iterator != all_nodes_list.end())
        {
            if (*node_id_iterator < node_iterator->id)
            {
                ++node_id_iterator;
                continue;
            }
            if (*node_id_iterator > node_iterator->id)
            {
                ++node_iterator;
                continue;
            }
            BOOST_ASSERT(*node_id_iterator == node_iterator->id);

            file_out_stream.write((char *)&(*node_iterator), sizeof(ExternalMemoryNode));

            ++number_of_used_nodes;
            ++node_id_iterator;
            ++node_iterator;
        }

        time2 = std::chrono::steady_clock::now();
        elapsed_seconds = time2 - time1;
        std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;

        std::cout << "[extractor] setting number of nodes   ... " << std::flush;
        std::ios::pos_type previous_file_position = file_out_stream.tellp();
        file_out_stream.seekp(std::ios::beg + sizeof(UUID));
        file_out_stream.write((char *)&number_of_used_nodes, sizeof(unsigned));
        file_out_stream.seekp(previous_file_position);

        std::cout << "ok" << std::endl;
        time1 = std::chrono::steady_clock::now();

        // Sort edges by start.
        std::cout << "[extractor] Sorting edges by start    ... " << std::flush;
        stxxl::sort(all_edges_list.begin(), all_edges_list.end(), CmpEdgeByStartID(), stxxl_memory);
        time2 = std::chrono::steady_clock::now();
        elapsed_seconds = time2 - time1;
        std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;

        time1 = std::chrono::steady_clock::now();

        std::cout << "[extractor] Setting start coords      ... " << std::flush;
        file_out_stream.write((char *)&number_of_used_edges, sizeof(unsigned));
        // Traverse list of edges and nodes in parallel and set start coord
        node_iterator = all_nodes_list.begin();
        auto edge_iterator = all_edges_list.begin();
        while (edge_iterator != all_edges_list.end() && node_iterator != all_nodes_list.end())
        {
            if (edge_iterator->start < node_iterator->id)
            {
                ++edge_iterator;
                continue;
            }
            if (edge_iterator->start > node_iterator->id)
            {
                node_iterator++;
                continue;
            }

            BOOST_ASSERT(edge_iterator->start == node_iterator->id);
            edge_iterator->source_coordinate.lat = node_iterator->lat;
            edge_iterator->source_coordinate.lon = node_iterator->lon;
            ++edge_iterator;
        }
        time2 = std::chrono::steady_clock::now();
        elapsed_seconds = time2 - time1;
        std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;

        time1 = std::chrono::steady_clock::now();
        // Sort Edges by target
        std::cout << "[extractor] Sorting edges by target   ... " << std::flush;
        stxxl::sort(all_edges_list.begin(), all_edges_list.end(), CmpEdgeByTargetID(), stxxl_memory);
        time2 = std::chrono::steady_clock::now();
        elapsed_seconds = time2 - time1;
        std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;

        time1 = std::chrono::steady_clock::now();
        std::cout << "[extractor] Setting target coords     ... " << std::flush;
        // Traverse list of edges and nodes in parallel and set target coord
        node_iterator = all_nodes_list.begin();
        edge_iterator = all_edges_list.begin();

        while (edge_iterator != all_edges_list.end() && node_iterator != all_nodes_list.end())
        {
            if (edge_iterator->target < node_iterator->id)
            {
                ++edge_iterator;
                continue;
            }
            if (edge_iterator->target > node_iterator->id)
            {
                ++node_iterator;
                continue;
            }
            BOOST_ASSERT(edge_iterator->target == node_iterator->id);
            if (edge_iterator->source_coordinate.lat != std::numeric_limits<int>::min() &&
                edge_iterator->source_coordinate.lon != std::numeric_limits<int>::min())
            {
                BOOST_ASSERT(edge_iterator->speed != -1);
                BOOST_ASSERT(edge_iterator->type >= 0);
                edge_iterator->target_coordinate.lat = node_iterator->lat;
                edge_iterator->target_coordinate.lon = node_iterator->lon;

                const double distance = FixedPointCoordinate::ApproximateEuclideanDistance(
                    edge_iterator->source_coordinate.lat,
                    edge_iterator->source_coordinate.lon,
                    node_iterator->lat,
                    node_iterator->lon);

                const double weight = (distance * 10.) / (edge_iterator->speed / 3.6);
                int integer_weight = std::max(
                    1,
                    (int)std::floor(
                        (edge_iterator->is_duration_set ? edge_iterator->speed : weight) + .5));
                int integer_distance = std::max(1, (int)distance);
                short zero = 0;
                short one = 1;

                file_out_stream.write((char *)&edge_iterator->start, sizeof(unsigned));
                file_out_stream.write((char *)&edge_iterator->target, sizeof(unsigned));
                file_out_stream.write((char *)&integer_distance, sizeof(int));
                switch (edge_iterator->direction)
                {
                case ExtractionWay::notSure:
                    file_out_stream.write((char *)&zero, sizeof(short));
                    break;
                case ExtractionWay::oneway:
                    file_out_stream.write((char *)&one, sizeof(short));
                    break;
                case ExtractionWay::bidirectional:
                    file_out_stream.write((char *)&zero, sizeof(short));
                    break;
                case ExtractionWay::opposite:
                    file_out_stream.write((char *)&one, sizeof(short));
                    break;
                default:
                    throw OSRMException("edge has broken direction");
                }

                file_out_stream.write((char *)&integer_weight, sizeof(int));
                file_out_stream.write((char *)&edge_iterator->type, sizeof(short));
                file_out_stream.write((char *)&edge_iterator->name_id, sizeof(unsigned));
                file_out_stream.write((char *)&edge_iterator->is_roundabout, sizeof(bool));
                file_out_stream.write((char *)&edge_iterator->is_in_tiny_cc, sizeof(bool));
                file_out_stream.write((char *)&edge_iterator->is_access_restricted, sizeof(bool));
                file_out_stream.write((char *)&edge_iterator->is_contra_flow, sizeof(bool));
                file_out_stream.write((char *)&edge_iterator->is_split, sizeof(bool));
                ++number_of_used_edges;
            }
            ++edge_iterator;
        }
        time2 = std::chrono::steady_clock::now();
        elapsed_seconds = time2 - time1;
        std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;

        std::cout << "[extractor] setting number of edges   ... " << std::flush;

        file_out_stream.seekp(previous_file_position);
        file_out_stream.write((char *)&number_of_used_edges, sizeof(unsigned));
        file_out_stream.close();
        std::cout << "ok" << std::endl;
        time1 = std::chrono::steady_clock::now();

        std::cout << "[extractor] writing street name index ... " << std::flush;
        std::string name_file_streamName = (output_file_name + ".names");
        boost::filesystem::ofstream name_file_stream(name_file_streamName, std::ios::binary);

        // write number of names
        const unsigned number_of_names = name_list.size() + 1;
        name_file_stream.write((char *)&(number_of_names), sizeof(unsigned));

        // compute total number of chars
        unsigned total_number_of_chars = 0;
        for (const std::string &temp_string : name_list)
        {
            total_number_of_chars += temp_string.length();
        }
        // write total number of chars
        name_file_stream.write((char *)&(total_number_of_chars), sizeof(unsigned));
        // write prefixe sums
        unsigned name_lengths_prefix_sum = 0;
        for (const std::string &temp_string : name_list)
        {
            name_file_stream.write((char *)&(name_lengths_prefix_sum), sizeof(unsigned));
            name_lengths_prefix_sum += temp_string.length();
        }
        // duplicate on purpose!
        name_file_stream.write((char *)&(name_lengths_prefix_sum), sizeof(unsigned));

        // write all chars consecutively
        for (const std::string &temp_string : name_list)
        {
            const unsigned string_length = temp_string.length();
            name_file_stream.write(temp_string.c_str(), string_length);
        }

        name_file_stream.close();
        time2 = std::chrono::steady_clock::now();
        elapsed_seconds = time2 - time1;
        std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;

        SimpleLogger().Write() << "Processed " << number_of_used_nodes << " nodes and "
                               << number_of_used_edges << " edges";
    }
    catch (const std::exception &e) { std::cerr << "Caught Execption:" << e.what() << std::endl; }
}
Exemple #6
0
inline void PBFParser::parseNode(ParserThreadData *)
{
    throw OSRMException("Parsing of simple nodes not supported. PBF should use dense nodes");
}
int main(int argc, char *argv[])
{
    LogPolicy::GetInstance().Unmute();

    SimpleLogger().Write() << "starting up engines, " << g_GIT_DESCRIPTION << ", "
                           << "compiled at " << __DATE__ << ", " __TIME__;

#ifdef __FreeBSD__
    SimpleLogger().Write() << "Not supported on FreeBSD";
    return 0;
#endif
#ifdef WIN32
    SimpleLogger().Write() << "Not supported on Windows";
    return 0;
#else


    if (1 == argc)
    {
        SimpleLogger().Write(logWARNING) << "usage: " << argv[0] << " /path/on/device";
        return -1;
    }

    boost::filesystem::path test_path = boost::filesystem::path(argv[1]);
    test_path /= "osrm.tst";
    SimpleLogger().Write(logDEBUG) << "temporary file: " << test_path.string();

    try
    {
        // create files for testing
        if (2 == argc)
        {
            // create file to test
            if (boost::filesystem::exists(test_path))
            {
                throw OSRMException("Data file already exists");
            }

            int *random_array = new int[number_of_elements];
            std::generate(random_array, random_array + number_of_elements, std::rand);
#ifdef __APPLE__
            FILE *fd = fopen(test_path.string().c_str(), "w");
            fcntl(fileno(fd), F_NOCACHE, 1);
            fcntl(fileno(fd), F_RDAHEAD, 0);
            TIMER_START(write_1gb);
            write(fileno(fd), (char *)random_array, number_of_elements * sizeof(unsigned));
            TIMER_STOP(write_1gb);
            fclose(fd);
#endif
#ifdef __linux__
            int f =
                open(test_path.string().c_str(), O_CREAT | O_TRUNC | O_WRONLY | O_SYNC, S_IRWXU);
            if (-1 == f)
            {
                throw OSRMException("Could not open random data file");
            }
            TIMER_START(write_1gb);
            int ret = write(f, random_array, number_of_elements * sizeof(unsigned));
            if (0 > ret)
            {
                throw OSRMException("could not write random data file");
            }
            TIMER_STOP(write_1gb);
            close(f);
#endif
            delete[] random_array;
            SimpleLogger().Write(logDEBUG) << "writing raw 1GB took " << TIMER_SEC(write_1gb)
                                           << "s";
            SimpleLogger().Write() << "raw write performance: " << std::setprecision(5)
                                   << std::fixed << 1024 * 1024 / TIMER_SEC(write_1gb)
                                   << "MB/sec";

            SimpleLogger().Write(logDEBUG)
                << "finished creation of random data. Flush disk cache now!";
        }
        else
        {
            // Run Non-Cached I/O benchmarks
            if (!boost::filesystem::exists(test_path))
            {
                throw OSRMException("data file does not exist");
            }

            // volatiles do not get optimized
            Statistics stats;

#ifdef __APPLE__
            volatile unsigned single_block[1024];
            char *raw_array = new char[number_of_elements * sizeof(unsigned)];
            FILE *fd = fopen(test_path.string().c_str(), "r");
            fcntl(fileno(fd), F_NOCACHE, 1);
            fcntl(fileno(fd), F_RDAHEAD, 0);
#endif
#ifdef __linux__
            char *single_block = (char *)memalign(512, 1024 * sizeof(unsigned));

            int f = open(test_path.string().c_str(), O_RDONLY | O_DIRECT | O_SYNC);
            if (-1 == f)
            {
                SimpleLogger().Write(logDEBUG) << "opened, error: " << strerror(errno);
                return -1;
            }
            char *raw_array = (char *)memalign(512, number_of_elements * sizeof(unsigned));
#endif
            TIMER_START(read_1gb);
#ifdef __APPLE__
            read(fileno(fd), raw_array, number_of_elements * sizeof(unsigned));
            close(fileno(fd));
            fd = fopen(test_path.string().c_str(), "r");
#endif
#ifdef __linux__
            int ret = read(f, raw_array, number_of_elements * sizeof(unsigned));
            SimpleLogger().Write(logDEBUG) << "read " << ret
                                           << " bytes, error: " << strerror(errno);
            close(f);
            f = open(test_path.string().c_str(), O_RDONLY | O_DIRECT | O_SYNC);
            SimpleLogger().Write(logDEBUG) << "opened, error: " << strerror(errno);
#endif
            TIMER_STOP(read_1gb);

            SimpleLogger().Write(logDEBUG) << "reading raw 1GB took " << TIMER_SEC(read_1gb)
                                           << "s";
            SimpleLogger().Write() << "raw read performance: " << std::setprecision(5) << std::fixed
                                   << 1024 * 1024 / TIMER_SEC(read_1gb) << "MB/sec";

            std::vector<double> timing_results_raw_random;
            SimpleLogger().Write(logDEBUG) << "running 1000 random I/Os of 4KB";

#ifdef __APPLE__
            fseek(fd, 0, SEEK_SET);
#endif
#ifdef __linux__
            lseek(f, 0, SEEK_SET);
#endif
            // make 1000 random access, time each I/O seperately
            unsigned number_of_blocks = (number_of_elements * sizeof(unsigned) - 1) / 4096;
            for (unsigned i = 0; i < 1000; ++i)
            {
                unsigned block_to_read = std::rand() % number_of_blocks;
                off_t current_offset = block_to_read * 4096;
                TIMER_START(random_access);
#ifdef __APPLE__
                int ret1 = fseek(fd, current_offset, SEEK_SET);
                int ret2 = read(fileno(fd), (char *)&single_block[0], 4096);
#endif

#ifdef __FreeBSD__
                int ret1 = 0;
                int ret2 = 0;
#endif

#ifdef __linux__
                int ret1 = lseek(f, current_offset, SEEK_SET);
                int ret2 = read(f, (char *)single_block, 4096);
#endif
                TIMER_STOP(random_access);
                if (((off_t) - 1) == ret1)
                {
                    SimpleLogger().Write(logWARNING) << "offset: " << current_offset;
                    SimpleLogger().Write(logWARNING) << "seek error " << strerror(errno);
                    throw OSRMException("seek error");
                }
                if (-1 == ret2)
                {
                    SimpleLogger().Write(logWARNING) << "offset: " << current_offset;
                    SimpleLogger().Write(logWARNING) << "read error " << strerror(errno);
                    throw OSRMException("read error");
                }
                timing_results_raw_random.push_back(TIMER_SEC(random_access));
            }

            // Do statistics
            SimpleLogger().Write(logDEBUG) << "running raw random I/O statistics";
            std::ofstream random_csv("random.csv", std::ios::trunc);
            for (unsigned i = 0; i < timing_results_raw_random.size(); ++i)
            {
                random_csv << i << ", " << timing_results_raw_random[i] << std::endl;
            }
            random_csv.close();
            RunStatistics(timing_results_raw_random, stats);

            SimpleLogger().Write() << "raw random I/O: " << std::setprecision(5) << std::fixed
                                   << "min: " << stats.min << "ms, "
                                   << "mean: " << stats.mean << "ms, "
                                   << "med: " << stats.med << "ms, "
                                   << "max: " << stats.max << "ms, "
                                   << "dev: " << stats.dev << "ms";

            std::vector<double> timing_results_raw_seq;
#ifdef __APPLE__
            fseek(fd, 0, SEEK_SET);
#endif
#ifdef __linux__
            lseek(f, 0, SEEK_SET);
#endif

            // read every 100th block
            for (unsigned i = 0; i < 1000; ++i)
            {
                off_t current_offset = i * 4096;
                TIMER_START(read_every_100);
#ifdef __APPLE__
                int ret1 = fseek(fd, current_offset, SEEK_SET);
                int ret2 = read(fileno(fd), (char *)&single_block, 4096);
#endif

#ifdef __FreeBSD__
                int ret1 = 0;
                int ret2 = 0;
#endif

#ifdef __linux__
                int ret1 = lseek(f, current_offset, SEEK_SET);

                int ret2 = read(f, (char *)single_block, 4096);
#endif
                TIMER_STOP(read_every_100);
                if (((off_t) - 1) == ret1)
                {
                    SimpleLogger().Write(logWARNING) << "offset: " << current_offset;
                    SimpleLogger().Write(logWARNING) << "seek error " << strerror(errno);
                    throw OSRMException("seek error");
                }
                if (-1 == ret2)
                {
                    SimpleLogger().Write(logWARNING) << "offset: " << current_offset;
                    SimpleLogger().Write(logWARNING) << "read error " << strerror(errno);
                    throw OSRMException("read error");
                }
                timing_results_raw_seq.push_back(TIMER_SEC(read_every_100));
            }
#ifdef __APPLE__
            fclose(fd);
            // free(single_element);
            free(raw_array);
// free(single_block);
#endif
#ifdef __linux__
            close(f);
#endif
            // Do statistics
            SimpleLogger().Write(logDEBUG) << "running sequential I/O statistics";
            // print simple statistics: min, max, median, variance
            std::ofstream seq_csv("sequential.csv", std::ios::trunc);
            for (unsigned i = 0; i < timing_results_raw_seq.size(); ++i)
            {
                seq_csv << i << ", " << timing_results_raw_seq[i] << std::endl;
            }
            seq_csv.close();
            RunStatistics(timing_results_raw_seq, stats);
            SimpleLogger().Write() << "raw sequential I/O: " << std::setprecision(5) << std::fixed
                                   << "min: " << stats.min << "ms, "
                                   << "mean: " << stats.mean << "ms, "
                                   << "med: " << stats.med << "ms, "
                                   << "max: " << stats.max << "ms, "
                                   << "dev: " << stats.dev << "ms";

            if (boost::filesystem::exists(test_path))
            {
                boost::filesystem::remove(test_path);
                SimpleLogger().Write(logDEBUG) << "removing temporary files";
            }
        }
    }
    catch (const std::exception &e)
    {
        SimpleLogger().Write(logWARNING) << "caught exception: " << e.what();
        SimpleLogger().Write(logWARNING) << "cleaning up, and exiting";
        if (boost::filesystem::exists(test_path))
        {
            boost::filesystem::remove(test_path);
            SimpleLogger().Write(logWARNING) << "removing temporary files";
        }
        return -1;
    }
    return 0;
#endif
}
Exemple #8
0
int main (int argc, char *argv[]) {
    try {
        LogPolicy::GetInstance().Unmute();
        double startup_time = get_timestamp();

        boost::filesystem::path config_file_path, input_path, profile_path;
        int requested_num_threads;

        // declare a group of options that will be allowed only on command line
        boost::program_options::options_description generic_options("Options");
        generic_options.add_options()
            ("version,v", "Show version")
            ("help,h", "Show this help message")
            ("config,c", boost::program_options::value<boost::filesystem::path>(&config_file_path)->default_value("extractor.ini"),
                  "Path to a configuration file.");

        // declare a group of options that will be allowed both on command line and in config file
        boost::program_options::options_description config_options("Configuration");
        config_options.add_options()
            ("profile,p", boost::program_options::value<boost::filesystem::path>(&profile_path)->default_value("profile.lua"),
                "Path to LUA routing profile")
            ("threads,t", boost::program_options::value<int>(&requested_num_threads)->default_value(8),
                "Number of threads to use");

        // hidden options, will be allowed both on command line and in config file, but will not be shown to the user
        boost::program_options::options_description hidden_options("Hidden options");
        hidden_options.add_options()
            ("input,i", boost::program_options::value<boost::filesystem::path>(&input_path),
                "Input file in .osm, .osm.bz2 or .osm.pbf format");

        // positional option
        boost::program_options::positional_options_description positional_options;
        positional_options.add("input", 1);

        // combine above options for parsing
        boost::program_options::options_description cmdline_options;
        cmdline_options.add(generic_options).add(config_options).add(hidden_options);

        boost::program_options::options_description config_file_options;
        config_file_options.add(config_options).add(hidden_options);

        boost::program_options::options_description visible_options(boost::filesystem::basename(argv[0]) + " <input.osm/.osm.bz2/.osm.pbf> [options]");
        visible_options.add(generic_options).add(config_options);

        // parse command line options
        boost::program_options::variables_map option_variables;
        boost::program_options::store(boost::program_options::command_line_parser(argc, argv).
            options(cmdline_options).positional(positional_options).run(), option_variables);

        if(option_variables.count("version")) {
            SimpleLogger().Write() << g_GIT_DESCRIPTION;
            return 0;
        }

        if(option_variables.count("help")) {
            SimpleLogger().Write() << visible_options;
            return 0;
        }

        boost::program_options::notify(option_variables);

        // parse config file
        if(boost::filesystem::is_regular_file(config_file_path)) {
            SimpleLogger().Write() << "Reading options from: " << config_file_path.c_str();
            std::string config_str;
            PrepareConfigFile( config_file_path.c_str(), config_str );
            std::stringstream config_stream( config_str );
            boost::program_options::store(parse_config_file(config_stream, config_file_options), option_variables);
            boost::program_options::notify(option_variables);
        }

        if(!option_variables.count("input")) {
            SimpleLogger().Write(logWARNING) << "No input file specified";
            SimpleLogger().Write() << visible_options;
            return -1;
        }

        if(1 > requested_num_threads) {
            SimpleLogger().Write(logWARNING) << "Number of threads must be 1 or larger";
            return -1;
        }

        SimpleLogger().Write() << "Input file: " << input_path.filename().string();
        SimpleLogger().Write() << "Profile: " << profile_path.filename().string();
        SimpleLogger().Write() << "Threads: " << requested_num_threads;

        /*** Setup Scripting Environment ***/
        ScriptingEnvironment scriptingEnvironment(profile_path.c_str());

        omp_set_num_threads( std::min( omp_get_num_procs(), requested_num_threads) );

        bool file_has_pbf_format(false);
        std::string output_file_name(input_path.c_str());
        std::string restrictionsFileName(input_path.c_str());
        std::string::size_type pos = output_file_name.find(".osm.bz2");
        if(pos==std::string::npos) {
            pos = output_file_name.find(".osm.pbf");
            if(pos!=std::string::npos) {
                file_has_pbf_format = true;
            }
        }
        if(pos==std::string::npos) {
            pos = output_file_name.find(".pbf");
            if(pos!=std::string::npos) {
                file_has_pbf_format = true;
            }
        }
        if(pos!=std::string::npos) {
            output_file_name.replace(pos, 8, ".osrm");
            restrictionsFileName.replace(pos, 8, ".osrm.restrictions");
        } else {
            pos=output_file_name.find(".osm");
            if(pos!=std::string::npos) {
                output_file_name.replace(pos, 5, ".osrm");
                restrictionsFileName.replace(pos, 5, ".osrm.restrictions");
            } else {
                output_file_name.append(".osrm");
                restrictionsFileName.append(".osrm.restrictions");
            }
        }

        StringMap stringMap;
        ExtractionContainers externalMemory;

        stringMap[""] = 0;
        extractCallBacks = new ExtractorCallbacks(&externalMemory, &stringMap);
        BaseParser* parser;
        if(file_has_pbf_format) {
            parser = new PBFParser(input_path.c_str(), extractCallBacks, scriptingEnvironment);
        } else {
            parser = new XMLParser(input_path.c_str(), extractCallBacks, scriptingEnvironment);
        }

        if(!parser->ReadHeader()) {
            throw OSRMException("Parser not initialized!");
        }
        SimpleLogger().Write() << "Parsing in progress..";
        double parsing_start_time = get_timestamp();
        parser->Parse();
        SimpleLogger().Write() << "Parsing finished after " <<
            (get_timestamp() - parsing_start_time) <<
            " seconds";

        if( externalMemory.all_edges_list.empty() ) {
            SimpleLogger().Write(logWARNING) << "The input data is empty, exiting.";
            return -1;
        }

        externalMemory.PrepareData(output_file_name, restrictionsFileName);

        delete parser;
        delete extractCallBacks;

        SimpleLogger().Write() <<
            "extraction finished after " << get_timestamp() - startup_time <<
            "s";

         SimpleLogger().Write() << "To prepare the data for routing, run: "
            << "./osrm-prepare " << output_file_name << std::endl;

    } catch(boost::program_options::too_many_positional_options_error& e) {
        SimpleLogger().Write(logWARNING) << "Only one input file can be specified";
        return -1;
    } catch(boost::program_options::error& e) {
        SimpleLogger().Write(logWARNING) << e.what();
        return -1;
    } catch(std::exception & e) {
        SimpleLogger().Write(logWARNING) << "Unhandled exception: " << e.what();
        return -1;
    }
    return 0;
}
int main(int argc, char *argv[])
{
    LogPolicy::GetInstance().Unmute();
    if (argc < 3)
    {
        SimpleLogger().Write(logWARNING) << "usage:\n" << argv[0] << " <osrm> <osrm.restrictions>";
        return -1;
    }

    try
    {
        SimpleLogger().Write() << "Using restrictions from file: " << argv[2];
        std::ifstream restriction_ifstream(argv[2], std::ios::binary);
        const FingerPrint fingerprint_orig;
        FingerPrint fingerprint_loaded;
        restriction_ifstream.read((char *)&fingerprint_loaded, sizeof(FingerPrint));

        if (!fingerprint_loaded.TestGraphUtil(fingerprint_orig))
        {
            SimpleLogger().Write(logWARNING) << argv[2] << " was prepared with a different build. "
                                                           "Reprocess to get rid of this warning.";
        }

        if (!restriction_ifstream.good())
        {
            throw OSRMException("Could not access <osrm-restrictions> files");
        }
        uint32_t usable_restriction_count = 0;
        restriction_ifstream.read((char *)&usable_restriction_count, sizeof(uint32_t));
        restrictions_vector.resize(usable_restriction_count);

        if (usable_restriction_count>0)
        {
            restriction_ifstream.read((char *)&(restrictions_vector[0]),
                                 usable_restriction_count * sizeof(TurnRestriction));
        }
        restriction_ifstream.close();

        std::ifstream input_stream;
        input_stream.open(argv[1], std::ifstream::in | std::ifstream::binary);

        if (!input_stream.is_open())
        {
            throw OSRMException("Cannot open osrm file");
        }

        std::vector<ImportEdge> edge_list;
        const NodeID number_of_nodes = readBinaryOSRMGraphFromStream(input_stream,
                                                                     edge_list,
                                                                     bollard_node_IDs_vector,
                                                                     traffic_light_node_IDs_vector,
                                                                     &internal_to_external_node_map,
                                                                     restrictions_vector);
        input_stream.close();

        BOOST_ASSERT_MSG(restrictions_vector.size() == usable_restriction_count,
                         "size of restrictions_vector changed");

        SimpleLogger().Write() << restrictions_vector.size() << " restrictions, "
                               << bollard_node_IDs_vector.size() << " bollard nodes, "
                               << traffic_light_node_IDs_vector.size() << " traffic lights";

        /***
         * Building an edge-expanded graph from node-based input an turn
         * restrictions
         */

        SimpleLogger().Write() << "Starting SCC graph traversal";
        std::shared_ptr<TarjanSCC> tarjan =
            std::make_shared<TarjanSCC>(number_of_nodes,
                                        edge_list,
                                        bollard_node_IDs_vector,
                                        traffic_light_node_IDs_vector,
                                        restrictions_vector,
                                        internal_to_external_node_map);
        std::vector<ImportEdge>().swap(edge_list);

        tarjan->Run();
        SimpleLogger().Write() << "finished component analysis";
    }
    catch (const std::exception &e)
    {
        SimpleLogger().Write(logWARNING) << "[exception] " << e.what();
    }
    return 0;
}
Exemple #10
0
int Extractor::Run(int argc, char *argv[])
{
    try
    {
        LogPolicy::GetInstance().Unmute();

        TIMER_START(extracting);

        if (!ParseArguments(argc, argv))
            return 0;

        if (1 > requested_num_threads)
        {
            SimpleLogger().Write(logWARNING) << "Number of threads must be 1 or larger";
            return 1;
        }

        if (!boost::filesystem::is_regular_file(input_path))
        {
            SimpleLogger().Write(logWARNING) << "Input file " << input_path.string()
                                             << " not found!";
            return 1;
        }

        if (!boost::filesystem::is_regular_file(profile_path))
        {
            SimpleLogger().Write(logWARNING) << "Profile " << profile_path.string()
                                             << " not found!";
            return 1;
        }

        const unsigned recommended_num_threads = tbb::task_scheduler_init::default_num_threads();

        SimpleLogger().Write() << "Input file: " << input_path.filename().string();
        SimpleLogger().Write() << "Profile: " << profile_path.filename().string();
        SimpleLogger().Write() << "Threads: " << requested_num_threads;
        if (recommended_num_threads != requested_num_threads)
        {
            SimpleLogger().Write(logWARNING) << "The recommended number of threads is "
                                             << recommended_num_threads
                                             << "! This setting may have performance side-effects.";
        }

        tbb::task_scheduler_init init(requested_num_threads);

        /*** Setup Scripting Environment ***/
        ScriptingEnvironment scripting_environment(profile_path.string().c_str());

        GenerateOutputFilesNames();

        std::unordered_map<std::string, NodeID> string_map;
        ExtractionContainers extraction_containers;

        string_map[""] = 0;
        auto extractor_callbacks = new ExtractorCallbacks(extraction_containers, string_map);
        BaseParser *parser;
        if (file_has_pbf_format)
        {
            parser = new PBFParser(input_path.string().c_str(),
                                   extractor_callbacks,
                                   scripting_environment,
                                   requested_num_threads);
        }
        else
        {
            parser = new XMLParser(input_path.string().c_str(),
                                   extractor_callbacks,
                                   scripting_environment);
        }

        if (!parser->ReadHeader())
        {
            throw OSRMException("Parser not initialized!");
        }

        SimpleLogger().Write() << "Parsing in progress..";
        TIMER_START(parsing);

        parser->Parse();
        delete parser;
        delete extractor_callbacks;

        TIMER_STOP(parsing);
        SimpleLogger().Write() << "Parsing finished after " << TIMER_SEC(parsing) << " seconds";

        if (extraction_containers.all_edges_list.empty())
        {
            SimpleLogger().Write(logWARNING) << "The input data is empty, exiting.";
            return 1;
        }

        extraction_containers.PrepareData(output_file_name, restriction_file_name);

        TIMER_STOP(extracting);
        SimpleLogger().Write() << "extraction finished after " << TIMER_SEC(extracting) << "s";
        SimpleLogger().Write() << "To prepare the data for routing, run: "
                               << "./osrm-prepare " << output_file_name << std::endl;
    }
    catch (boost::program_options::too_many_positional_options_error &)
    {
        SimpleLogger().Write(logWARNING) << "Only one input file can be specified";
        return 1;
    }
    catch (std::exception &e)
    {
        SimpleLogger().Write(logWARNING) << e.what();
        return 1;
    }
    return 0;
}
ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
	SimpleLogger().Write() << "Using script " << fileName;

    // Create a new lua state
    for(int i = 0; i < omp_get_max_threads(); ++i) {
        luaStateVector.push_back(luaL_newstate());
    }

    // Connect LuaBind to this lua state for all threads
#pragma omp parallel
    {
        lua_State * myLuaState = getLuaStateForThreadID(omp_get_thread_num());
        luabind::open(myLuaState);
        //open utility libraries string library;
        luaL_openlibs(myLuaState);

        luaAddScriptFolderToLoadPath( myLuaState, fileName );

        // Add our function to the state's global scope
        luabind::module(myLuaState) [
            luabind::def("print", LUA_print<std::string>),
            luabind::def("parseMaxspeed", parseMaxspeed),
            luabind::def("durationIsValid", durationIsValid),
            luabind::def("parseDuration", parseDuration)
        ];

        luabind::module(myLuaState) [
            luabind::class_<HashTable<std::string, std::string> >("keyVals")
            .def("Add", &HashTable<std::string, std::string>::Add)
            .def("Find", &HashTable<std::string, std::string>::Find)
            .def("Holds", &HashTable<std::string, std::string>::Holds)
        ];

        luabind::module(myLuaState) [
            luabind::class_<ImportNode>("Node")
            .def(luabind::constructor<>())
            .def_readwrite("lat", &ImportNode::lat)
            .def_readwrite("lon", &ImportNode::lon)
            .def_readwrite("id", &ImportNode::id)
            .def_readwrite("bollard", &ImportNode::bollard)
            .def_readwrite("traffic_light", &ImportNode::trafficLight)
            .def_readwrite("tags", &ImportNode::keyVals)
        ];

        luabind::module(myLuaState) [
            luabind::class_<ExtractionWay>("Way")
            .def(luabind::constructor<>())
            .def_readwrite("name", &ExtractionWay::name)
            .def_readwrite("speed", &ExtractionWay::speed)
            .def_readwrite("backward_speed", &ExtractionWay::backward_speed)
            .def_readwrite("duration", &ExtractionWay::duration)
            .def_readwrite("type", &ExtractionWay::type)
            .def_readwrite("access", &ExtractionWay::access)
            .def_readwrite("roundabout", &ExtractionWay::roundabout)
            .def_readwrite("is_access_restricted", &ExtractionWay::isAccessRestricted)
            .def_readwrite("ignore_in_grid", &ExtractionWay::ignoreInGrid)
            .def_readwrite("tags", &ExtractionWay::keyVals)
            .def_readwrite("direction", &ExtractionWay::direction)
            .enum_("constants") [
				  luabind::value("notSure", 0),
				  luabind::value("oneway", 1),
				  luabind::value("bidirectional", 2),
				  luabind::value("opposite", 3)
			]
    	];

        luabind::module(myLuaState) [
            luabind::class_<std::vector<std::string> >("vector")
            .def("Add", &std::vector<std::string>::push_back)
        ];

        if(0 != luaL_dofile(myLuaState, fileName) ) {
            throw OSRMException("ERROR occured in scripting block");
        }
    }
}