Skip to content
Snippets Groups Projects
TMSSBridge.cc 4.92 KiB
Newer Older
//  TMSSBridge.cc: Implementation of the TMSS Bridge, interface between MAC Scheduler and TMSS
//
//  Copyright (C) 2020
//  ASTRON (Netherlands Foundation for Research in Astronomy)
//  P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, softwaresupport@astron.nl
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
//
//  This program 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 General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  $Id$
#include "TMSSBridge.h"


#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include <boost/beast/version.hpp>
#include <boost/asio/connect.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <cstdlib>
#include <iostream>
#include <string>

namespace beast = boost::beast;     // from <boost/beast.hpp>
namespace http = beast::http;       // from <boost/beast/http.hpp>
namespace net = boost::asio;        // from <boost/asio.hpp>
using tcp = net::ip::tcp;           // from <boost/asio/ip/tcp.hpp>
namespace pt = boost::property_tree;
using namespace std;


namespace LOFAR {
	namespace MainCU {

//
// TMSSBridge Constructor
//
TMSSBridge::TMSSBridge():
	itsUser		  ("test"),
	itsPassword	  ("test"),
	itsHost		  ("http://127.0.0.1"), // just to start with maybe user and password need
	itsPort       (8000)
{

}


//
// TMSSBridge Destructor
//
TMSSBridge::~TMSSBridge()
{

}


//
// get all subTaskIDS that should run within three minutes (ordered in time if multiple are found)
// for given cluster
//
vector<int> TMSSBridge::getSubTaskIDStartingInThreeMinutes(ptime currentTime, string clusterName)
{
    currentTimeStr = std::string to_iso_extended_string(currentTime);
    queryStr = "/api/?start_time__lt=" + currentTimeStr + "&cluster__name==" + clusterName;
    string result = httpGET(itsHost, itsPort, queryStr);
    vector<string> urlList = translateHttpResultToSortedUrlList(result);
//
// Translate the HTTP result to json format and parse the json format
//     How to handle json structure in C++?
//     Need to check respons status code of http (200)?
//     Get the number of taskIDs like python
//     json_response = response.json()
//     json_response.get('count'))
//     ... and results[idx].items('url)
//     if multiple found sort on startTime !
vector<string> urlList = translateHttpResultToSortedUrlList(string result);
{
    // Create a root
    pt::ptree root;
    // Load json
    pt::read_json(result, root);
    // Read values
    int nbrSubTasksFound = root.get<int>("count", 0);

    string msg = root.get<string>("some.complex.path");

}


//
// Performs an HTTP GET and return response
// Example:
//    httpGET("http://127.0.0.1", 8000, "/api/subtask/?start_time__lt=2020-03-04T12:03:00"
//    results in a json string output
//
string TMSSBridge::httpGET(auto const host, auto const port, auto const target)
{
    try
    {
        // The io_context is required for all I/O
        net::io_context ioc;

        // These objects perform our I/O
        tcp::resolver resolver(ioc);
        beast::tcp_stream stream(ioc);

        // Look up the domain name
        auto const results = resolver.resolve(host, port);

        // Make the connection on the IP address we get from a lookup
        stream.connect(results);

        // Set up an HTTP GET request message, HTTP version: 1.1(default)
        http::request<http::string_body> req{http::verb::get, target, "1.1"};
        req.set(http::field::host, host);
        req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);

        // Send the HTTP request to the remote host
        http::write(stream, req);

        // This buffer is used for reading and must be persisted
        beast::flat_buffer buffer;

        // Declare a container to hold the response
        http::response<http::dynamic_body> res;

        // Receive the HTTP response
        http::read(stream, buffer, res);

        // Gracefully close the socket
        beast::error_code ec;
        stream.socket().shutdown(tcp::socket::shutdown_both, ec);

        // not_connected happens sometimes
        // so don't bother reporting it.
        //
        if(ec && ec != beast::errc::not_connected)
            throw beast::system_error{ec};

        // If we get here then the connection is closed gracefully
    }
    catch(std::exception const& e)
    {
        std::cerr << "Error: " << e.what() << std::endl;
        return EXIT_FAILURE;
    }
    return res;
}



  };//MainCU
};//LOFAR