Commit b7e72f8377b98b38707bac5ad60bb7dfa48368cf

Authored by Jürgen Knödlseder
1 parent 9b7e303f

Refactor code of GVOHub a bit.

ChangeLog
1   -2016-02-18 Juergen Knoedlseder <jurgen.knodlseder@irap.omp.eu>
  1 +2016-02-23 Juergen Knoedlseder <jurgen.knodlseder@irap.omp.eu>
2 2  
3 3 * Version 1.1.0 released
4 4 =========================
5 5  
  6 + Add GVOClient::publish() method to publish a FITS HDU (#1231)
6 7 Handle FITS extensions in GSkyMap load() and save() methods (#1695)
7 8 Restrict Monte Carlo simulations in GModelSpatialDiffuseConst to simulation cone (#1674)
8 9 Use default GTime in GModelSpectral eval() and eval_gradients() methods (#1672)
... ...
... ... @@ -2,7 +2,7 @@ New Features and Important Changes in GammaLib 1.1.0
2 2  
3 3 Author(s) : Juergen Knoedlseder
4 4  
5   -18 February 2016
  5 +23 February 2016
6 6  
7 7  
8 8 1. Introduction
... ... @@ -178,7 +178,9 @@ None
178 178  
179 179 15. VO module
180 180 -------------
181   -None
  181 +A GVOClient::publish() method was added that allows publishing of a FITS
  182 +image to the Hub. The FITS image will be saved into a temporary storage
  183 +location and the Hub will be informed that an image is available.
182 184  
183 185  
184 186 16. Xspec module
... ...
include/GVOClient.hpp
1 1 /***************************************************************************
2 2 * GVOClient.hpp - VO client class *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2013-2015 by Juergen Knoedlseder *
  4 + * copyright (C) 2013-2016 by Juergen Knoedlseder *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -30,9 +30,12 @@
30 30 /* __ Includes ___________________________________________________________ */
31 31 #include <string>
32 32 #include "GBase.hpp"
33   -#include "GXml.hpp"
34   -#include "GXmlNode.hpp"
35   -#include "GFits.hpp"
  33 +
  34 +/* __ Forward declarations _______________________________________________ */
  35 +class GFitsHDU;
  36 +class GXml;
  37 +class GXmlNode;
  38 +
36 39  
37 40 /***********************************************************************//**
38 41 * @class GVOClient
... ...
include/GVOHub.hpp
1 1 /***************************************************************************
2 2 * GVOHub.hpp - VO SAMP Hub class *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2014-2015 by Thierry Louge *
  4 + * copyright (C) 2014-2016 by Thierry Louge *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -34,8 +34,10 @@
34 34 #include <vector>
35 35 #include <sys/socket.h>
36 36 #include "GBase.hpp"
37   -#include "GXml.hpp"
38   -#include "GXmlNode.hpp"
  37 +
  38 +/* __ Forward declarations _______________________________________________ */
  39 +class GXml;
  40 +class GXmlNode;
39 41  
40 42  
41 43 /***********************************************************************//**
... ... @@ -73,29 +75,31 @@ protected:
73 75 void start_hub(void);
74 76 void handle_request(const socklen_t& sock);
75 77 void request_ping(const socklen_t& sock);
76   - void request_register(const GXml& xml,
  78 + void request_register(const GXml& xml,
77 79 const socklen_t& sock);
78   - void request_unregister(const GXml& xml,
  80 + void request_unregister(const GXml& xml,
79 81 const socklen_t& sock);
80   - void request_declare_metadata(const GXml& xml,
  82 + void request_declare_metadata(const GXml& xml,
81 83 const socklen_t& sock);
82   - void request_declare_subscriptions(const GXml& xml,
  84 + void request_declare_subscriptions(const GXml& xml,
83 85 const socklen_t& sock);
84   - void request_set_xml_rpc_callback(const GXml& xml,
  86 + void request_set_xml_rpc_callback(const GXml& xml,
85 87 const socklen_t& sock);
86   - void request_get_subscriptions(const GXml& xml,
  88 + void request_get_subscriptions(const GXml& xml,
87 89 const socklen_t& sock);
88   - void request_get_registered_clients(const GXml& xml,
  90 + void request_get_registered_clients(const GXml& xml,
89 91 const socklen_t& sock);
90   - void request_get_subscribed_clients(const GXml& xml,
  92 + void request_get_subscribed_clients(const GXml& xml,
91 93 const socklen_t& sock);
92   - void request_get_metadata(const GXml& xml,
  94 + void request_get_metadata(const GXml& xml,
93 95 const socklen_t& sock);
  96 + void request_notify_all(const GXml& xml,
  97 + const socklen_t& sock);
94 98 void request_shutdown(const socklen_t& sock);
95 99 std::string get_client_key(const GXml& xml) const;
96 100 int get_client_index(const GXml& xml) const;
97 101 int get_client_index(const std::string& reference) const;
98   - std::string get_response_value(const GXml& xml,
  102 + std::string get_response_value(const GXmlNode* node,
99 103 const std::string& name) const;
100 104 void get_name_value_pair(const GXmlNode* node,
101 105 std::string& name,
... ... @@ -103,24 +107,10 @@ protected:
103 107 std::vector<std::string> get_subscriptions(const GXml& xml) const;
104 108 std::string get_callback_url(const GXml& xml) const;
105 109 std::string get_hub_lockfile(void) const;
106   - void send_notifications(const std::string& method,
107   - const std::string& client);
108   - void send_notifications(const std::string& method,
109   - const std::string& client,
110   - const GXml& xml);
111   - void broadcast(const GXml& xml, const socklen_t& sock);
112 110 std::string get_mtype(const GXml& xml) const;
113 111 std::string get_destination(const GXml& xml) const;
114 112  
115   - // Low-level methods
116   - void create_samp_file(void) const;
117   - void post_samp_ok(const socklen_t& sock) const;
118   - void post_samp_void(const socklen_t& sock) const;
119   - void post_string(const std::string& content, const socklen_t& sock) const;
120   - void notify(const std::string& url, const std::string& notification) const;
121   - std::string random_string(const size_t& length) const;
122   -
123   - // Protected structure
  113 + // Client structure
124 114 struct client {
125 115 std::string name;
126 116 std::string private_key;
... ... @@ -136,6 +126,24 @@ protected:
136 126 std::vector<std::string> subscriptions;
137 127 };
138 128  
  129 + // Low-level methods
  130 + void create_samp_file(void) const;
  131 + void post_samp_ok(const socklen_t& sock) const;
  132 + void post_samp_void(const socklen_t& sock) const;
  133 + void post_string(const std::string& content,
  134 + const socklen_t& sock) const;
  135 + void notify(const std::string& url,
  136 + const std::string& notification) const;
  137 + void notify_register(const client& client,
  138 + const std::string& reference);
  139 + void notify_unregister(const client& client,
  140 + const std::string& reference);
  141 + void notify_metadata(const client& client,
  142 + const std::string& reference);
  143 + void notify_image_load(const client& client,
  144 + const GXml& xml);
  145 + std::string random_string(const size_t& length) const;
  146 +
139 147 // Protected members
140 148 std::string m_secret; //!< Secret Hub key
141 149 std::string m_hub_url; //!< The XML-RPC endpoint for communication with the hub
... ...
src/vo/GVOClient.cpp
1 1 /***************************************************************************
2 2 * GVOClient.cpp - VO client class *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2013-2015 by Juergen Knoedlseder *
  4 + * copyright (C) 2013-2016 by Juergen Knoedlseder *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -35,10 +35,13 @@
35 35 #include <netdb.h> // getaddrinfo() function
36 36 #include <sys/socket.h> // socket(), connect() functions
37 37 #include <fstream>
  38 +#include "GTools.hpp"
  39 +#include "GException.hpp"
  40 +#include "GXml.hpp"
  41 +#include "GXmlNode.hpp"
  42 +#include "GFits.hpp"
38 43 #include "GVOClient.hpp"
39 44 #include "GVOHub.hpp"
40   -#include "GException.hpp"
41   -#include "GTools.hpp"
42 45  
43 46 /* __ Method name definitions ____________________________________________ */
44 47 #define G_FIND_HUB "GVOClient::find_hub()"
... ... @@ -368,33 +371,54 @@ GXml GVOClient::execute(const std::string&amp; request) const
368 371 ***************************************************************************/
369 372 void GVOClient::publish(const GFitsHDU& hdu)
370 373 {
  374 + // Signal that client should be disconnected after sending the image
  375 + // to Hub
  376 + bool disconnected = !is_connected();
  377 +
  378 + // Make sure that the client is connected to a Hub
  379 + if (disconnected) {
  380 + connect();
  381 + }
  382 +
371 383 // Save FITS HDU into a temporary file
372 384 std::string samp_share = std::tmpnam(NULL);
373 385 GFits fits;
374 386 fits.append(hdu);
375 387 fits.saveto(samp_share, true);
376 388  
  389 + // Get FITS extension name
  390 + std::string extname = hdu.extname();
  391 + if (extname.empty()) {
  392 + extname = "FITS Image";
  393 + }
  394 +
377 395 // Compose notification to be passed to the Hub
378 396 std::string hub_command = "";
379 397 hub_command.append("<?xml version=\"1.0\"?>\n");
380   - hub_command.append("<methodCall>");
  398 + hub_command.append("<methodCall>\n");
381 399 hub_command.append(" <methodName>samp.hub.notifyAll</methodName>\n");
382 400 hub_command.append(" <params>\n");
383 401 hub_command.append(" <param><value>image.load.fits</value></param>\n");
384 402 hub_command.append(" <param><value>"+m_secret+"</value></param>\n");
385 403 hub_command.append(" <param><value><struct>\n");
386 404 hub_command.append(" <member><name>samp.params</name><value><struct>\n");
387   - hub_command.append(" <member><name>name</name><value>Gammalib_FITS_FILE</value></member>\n");
  405 + hub_command.append(" <member><name>name</name><value>"+extname+"</value></member>\n");
388 406 hub_command.append(" <member><name>url</name><value>file://localhost"+samp_share+"</value></member>\n");
389 407 hub_command.append(" <member><name>image-id</name><value>Gammalib Data</value></member>\n");
390 408 hub_command.append(" </struct></value></member>\n");
391 409 hub_command.append(" <member><name>samp.mtype</name><value>image.load.fits</value></member>\n");
392 410 hub_command.append(" </struct></value></param>\n");
393   - hub_command.append(" </params>\n</methodCall>\n");
  411 + hub_command.append(" </params>\n");
  412 + hub_command.append("</methodCall>\n");
394 413  
395 414 // Send notification
396 415 execute(hub_command);
397 416  
  417 + // Disconnect client from Hub
  418 + if (disconnected) {
  419 + disconnect();
  420 + }
  421 +
398 422 // Return
399 423 return;
400 424 }
... ...
src/vo/GVOHub.cpp
1 1 /***************************************************************************
2 2 * GVOHub.cpp - VO SAMP Hub class *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2014-2015 by Thierry Louge *
  4 + * copyright (C) 2014-2016 by Thierry Louge *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -41,9 +41,11 @@
41 41 #include <sys/socket.h> // socket(), connect() functions
42 42 #include <sys/wait.h> // waitpid() function
43 43 #include <arpa/inet.h> // inet_addr() function
44   -#include "GVOHub.hpp"
45   -#include "GException.hpp"
46 44 #include "GTools.hpp"
  45 +#include "GException.hpp"
  46 +#include "GXml.hpp"
  47 +#include "GXmlNode.hpp"
  48 +#include "GVOHub.hpp"
47 49  
48 50 /* __ Method name definitions ____________________________________________ */
49 51 #define G_START_HUB "GVOHub::start_hub()"
... ... @@ -54,6 +56,7 @@
54 56  
55 57 /* __ Debug definitions __________________________________________________ */
56 58 #define G_CONSOLE_DUMP
  59 +#define G_CONSOLE_ERRORS
57 60 #define G_SHOW_MESSAGE
58 61  
59 62  
... ... @@ -429,7 +432,7 @@ void GVOHub::handle_request(const socklen_t&amp; sock)
429 432 #endif
430 433  
431 434 // Extract response into an XML object
432   - GXml xml;
  435 + GXml xml;
433 436  
434 437 size_t start = message.find("<?xml");
435 438 if (start != std::string::npos) {
... ... @@ -446,9 +449,10 @@ void GVOHub::handle_request(const socklen_t&amp; sock)
446 449 }
447 450 }
448 451  
449   - // Dump the buffer
  452 + // Dump the method that is called
450 453 #if defined(G_CONSOLE_DUMP)
451   - std::cout << "Method called: " << method_called << std::endl;
  454 + std::cout << "GVOHub has received the message type \"";
  455 + std::cout << method_called << "\"" << std::endl;
452 456 #endif
453 457  
454 458 // Dispatch according to method
... ... @@ -489,11 +493,7 @@ void GVOHub::handle_request(const socklen_t&amp; sock)
489 493 request_ping(sock);
490 494 }
491 495 else if (method_called.compare("samp.hub.notifyAll") == 0) {
492   - #if defined(G_CONSOLE_DUMP)
493   - std::cout << "==========================================" << std::endl;
494   - std::cout << "samp.hub.notifyAll" << std::endl;
495   - #endif
496   - broadcast(xml, sock);
  496 + request_notify_all(xml, sock);
497 497 }
498 498 else if (method_called.compare("samp.hub.call") == 0) {
499 499 request_ping(sock);
... ... @@ -613,10 +613,17 @@ void GVOHub::request_register(const GXml&amp; xml, const socklen_t&amp; sock)
613 613 // Post response
614 614 post_string(response, sock);
615 615  
616   - // Send notifications
617   - send_notifications("samp.hub.event.register", voclient.reference);
  616 + // Notify all clients about the registering
  617 + for (int i = 0; i < m_clients.size(); ++i) {
  618 + for (int j = 0; j < m_clients[i].subscriptions.size(); ++j) {
  619 + if ("samp.hub.event.register" == m_clients[i].subscriptions[j]) {
  620 + notify_register(m_clients[i], voclient.reference);
  621 + break;
  622 + }
  623 + }
  624 + }
618 625  
619   - //Return
  626 + // Return
620 627 return;
621 628 }
622 629  
... ... @@ -645,9 +652,16 @@ void GVOHub::request_unregister(const GXml&amp; xml, const socklen_t&amp; sock)
645 652 // Post void message
646 653 post_samp_void(sock);
647 654  
648   - // Send notifications
649   - send_notifications("samp.hub.event.unregister",
650   - m_clients[i].reference);
  655 + // Notify all clients about the registering
  656 + for (int k = 0; k < m_clients.size(); ++k) {
  657 + if (i != k) {
  658 + for (int j = 0; j < m_clients[k].subscriptions.size(); ++j) {
  659 + if ("samp.hub.event.unregister" == m_clients[k].subscriptions[j]) {
  660 + notify_unregister(m_clients[k], m_clients[i].reference);
  661 + }
  662 + }
  663 + }
  664 + }
651 665  
652 666 // Remove client
653 667 m_clients.erase(m_clients.begin()+i);
... ... @@ -655,9 +669,11 @@ void GVOHub::request_unregister(const GXml&amp; xml, const socklen_t&amp; sock)
655 669 } // endif: valid client found
656 670  
657 671 // Signal if the client was unknown
658   - #if defined(G_CONSOLE_DUMP)
  672 + #if defined(G_CONSOLE_ERRORS)
659 673 else {
660   - std::cout << " *** ERROR: Unable to find client " << get_client_key(xml) << std::endl;
  674 + std::cout << "*** ERROR: GVOHub::request_unregister: ";
  675 + std::cout << "Unable to find client \"" << get_client_key(xml);
  676 + std::cout << "\"" << std::endl;
661 677 }
662 678 #endif
663 679  
... ... @@ -687,28 +703,41 @@ void GVOHub::request_declare_metadata(const GXml&amp; xml, const socklen_t&amp; sock)
687 703 // Continue only if index is valid
688 704 if (i != -1) {
689 705  
  706 + // Get node
  707 + const GXmlNode* node = xml.element("methodCall > params > param[1] > value > struct");
  708 +
690 709 // Store metadata
691   - m_clients[i].name = get_response_value(xml, "samp.name");;
692   - m_clients[i].description = get_response_value(xml, "samp.description.text");
693   - m_clients[i].icon = get_response_value(xml, "samp.icon.url");
694   - m_clients[i].documentation = get_response_value(xml, "samp.documentation.url");
695   - m_clients[i].affiliation = get_response_value(xml, "author.affiliation");
696   - m_clients[i].email = get_response_value(xml, "author.email");
697   - m_clients[i].author_name = get_response_value(xml, "author.name");
698   - m_clients[i].homepage = get_response_value(xml, "home.page");
  710 + m_clients[i].name = get_response_value(node, "samp.name");;
  711 + m_clients[i].description = get_response_value(node, "samp.description.text");
  712 + m_clients[i].icon = get_response_value(node, "samp.icon.url");
  713 + m_clients[i].documentation = get_response_value(node, "samp.documentation.url");
  714 + m_clients[i].affiliation = get_response_value(node, "author.affiliation");
  715 + m_clients[i].email = get_response_value(node, "author.email");
  716 + m_clients[i].author_name = get_response_value(node, "author.name");
  717 + m_clients[i].homepage = get_response_value(node, "home.page");
699 718  
700 719 // Post void message
701 720 post_samp_void(sock);
702   -
703   - // Send notifications
704   - send_notifications("samp.hub.event.metadata", m_clients[i].reference);
  721 +
  722 + // Notify all clients about the registering
  723 + for (int k = 0; k < m_clients.size(); ++k) {
  724 + if (i != k) {
  725 + for (int j = 0; j < m_clients[k].subscriptions.size(); ++j) {
  726 + if ("samp.hub.event.metadata" == m_clients[k].subscriptions[j]) {
  727 + notify_metadata(m_clients[k], m_clients[i].reference);
  728 + }
  729 + }
  730 + }
  731 + }
705 732  
706 733 } // endif: client found
707 734  
708 735 // Signal if the client was unknown
709   - #if defined(G_CONSOLE_DUMP)
  736 + #if defined(G_CONSOLE_ERRORS)
710 737 else {
711   - std::cout << " *** ERROR: Unable to find client " << get_client_key(xml) << std::endl;
  738 + std::cout << "*** ERROR: GVOHub::request_declare_metadata: ";
  739 + std::cout << "Unable to find client \"" << get_client_key(xml);
  740 + std::cout << "\"" << std::endl;
712 741 }
713 742 #endif
714 743  
... ... @@ -752,9 +781,11 @@ void GVOHub::request_declare_subscriptions(const GXml&amp; xml,const socklen_t&amp; sock
752 781 } // endif: valid client found
753 782  
754 783 // Signal if the client was unknown
755   - #if defined(G_CONSOLE_DUMP)
  784 + #if defined(G_CONSOLE_ERRORS)
756 785 else {
757   - std::cout << " *** ERROR: Unable to find client " << get_client_key(xml) << std::endl;
  786 + std::cout << "*** ERROR: GVOHub::request_declare_subscriptions: ";
  787 + std::cout << "Unable to find client \"" << get_client_key(xml);
  788 + std::cout << "\"" << std::endl;
758 789 }
759 790 #endif
760 791  
... ... @@ -797,9 +828,11 @@ void GVOHub::request_set_xml_rpc_callback(const GXml&amp; xml,
797 828 } // endif: client found
798 829  
799 830 // Signal if the client was unknown
800   - #if defined(G_CONSOLE_DUMP)
  831 + #if defined(G_CONSOLE_ERRORS)
801 832 else {
802   - std::cout << " *** ERROR: Unable to find client " << get_client_key(xml) << std::endl;
  833 + std::cout << "*** ERROR: GVOHub::request_set_xml_rpc_callback: ";
  834 + std::cout << "Unable to find client \"" << get_client_key(xml);
  835 + std::cout << "\"" << std::endl;
803 836 }
804 837 #endif
805 838  
... ... @@ -871,9 +904,11 @@ void GVOHub::request_get_subscriptions(const GXml&amp; xml, const socklen_t&amp; sock)
871 904 }
872 905  
873 906 // Signal if the client was unknown
874   - #if defined(G_CONSOLE_DUMP)
  907 + #if defined(G_CONSOLE_ERRORS)
875 908 else {
876   - std::cout << " *** ERROR: Unable to find client " << get_client_key(xml) << std::endl;
  909 + std::cout << "*** ERROR: GVOHub::request_get_subscriptions: ";
  910 + std::cout << "Unable to find client \"" << get_client_key(xml);
  911 + std::cout << "\"" << std::endl;
877 912 }
878 913 #endif
879 914  
... ... @@ -1092,6 +1127,15 @@ void GVOHub::request_get_metadata(const GXml&amp; xml, const socklen_t&amp; sock)
1092 1127 response.append(" </member>\n");
1093 1128  
1094 1129 } // endif: index was valid
  1130 +
  1131 + // Signal if the client was unknown
  1132 + #if defined(G_CONSOLE_ERRORS)
  1133 + else {
  1134 + std::cout << "*** ERROR: GVOHub::request_get_metadata: ";
  1135 + std::cout << "Unable to find client \"" << get_client_key(xml);
  1136 + std::cout << "\"" << std::endl;
  1137 + }
  1138 + #endif
1095 1139  
1096 1140 } // endelse: client was not the hub
1097 1141  
... ... @@ -1107,52 +1151,56 @@ void GVOHub::request_get_metadata(const GXml&amp; xml, const socklen_t&amp; sock)
1107 1151 return;
1108 1152 }
1109 1153  
  1154 +
1110 1155 /***********************************************************************//**
1111   - * @brief Broadcasts a message
  1156 + * @brief Handle request to notify all clients
1112 1157 *
1113 1158 * @param[in] xml XML message sent by client.
1114 1159 * @param[in] sock Socket.
1115 1160 *
1116   - * Broadcasts an image to every registered client.
  1161 + * Handles requests to notify all clients. The method will loop over all
  1162 + * clients to check the subscriptions of each client, and send a notification
  1163 + * to all clients that are subscribed to the requested message type.
1117 1164 ***************************************************************************/
1118   -void GVOHub::broadcast(const GXml& xml, const socklen_t& sock)
  1165 +void GVOHub::request_notify_all(const GXml& xml, const socklen_t& sock)
1119 1166 {
1120 1167 // Header
1121   -
1122   - // Get client index
1123   - int i = get_client_index(xml);
1124   -
1125   - // Get message mtype
1126   - std::string mtype = get_mtype(xml);
1127 1168 #if defined(G_CONSOLE_DUMP)
1128   - std::cout<<"mtype is: " +mtype + " i value: " + gammalib::str(i)<<std::endl;
  1169 + std::cout << "GVOHub::request_notify_all" << std::endl;
1129 1170 #endif
  1171 +
  1172 + // Get message type
  1173 + std::string mtype = get_mtype(xml);
  1174 +
  1175 + // Post void message
1130 1176 post_samp_void(sock);
1131 1177  
1132   - if (mtype == "image.load.fits") {
1133   - #if defined(G_CONSOLE_DUMP)
1134   - std::cout<<"notifying image.load.fits"<<std::endl;
1135   - #endif
  1178 + // Loop over all clients
  1179 + for (int i = 0; i < m_clients.size(); ++i) {
  1180 +
  1181 + // Loop over all subscriptions
  1182 + for (int j = 0; j < m_clients[i].subscriptions.size(); ++j) {
1136 1183  
1137   - // Send notifications
1138   - send_notifications("image.load.fits",m_clients[i].reference,xml);
1139   - }
  1184 + // Continue only if message type matches client's subscription
  1185 + if (mtype == m_clients[i].subscriptions[j]) {
  1186 +
  1187 + // Image loading
  1188 + if (mtype == "image.load.fits") {
  1189 + notify_image_load(m_clients[i], xml);
  1190 + }
1140 1191  
1141   - if (mtype == "table.load.votable") {
  1192 + } // endif: message type matched client subscription
1142 1193  
1143   - // Send notifications
1144   - send_notifications("table.load.votable",m_clients[i].reference,xml);
1145   - }
  1194 + } // endfor: looped over all message types
1146 1195  
1147   - #if defined(G_CONSOLE_DUMP)
1148   - std::cout<<"Returning from broadcast function"<<std::endl;
1149   - #endif
  1196 + } // endfor: looped over all clients
1150 1197  
1151 1198 // Return
1152 1199 return;
1153 1200  
1154 1201 }
1155 1202  
  1203 +
1156 1204 /***********************************************************************//**
1157 1205 * @brief Handles Hub shutdown requests
1158 1206 *
... ... @@ -1282,24 +1330,30 @@ int GVOHub::get_client_index(const std::string&amp; reference) const
1282 1330  
1283 1331  
1284 1332 /***********************************************************************//**
1285   - * @brief Returns value for a SAMP client query parameter
  1333 + * @brief Returns value for a named parameter
1286 1334 *
1287   - * @param[in] xml client query XML document.
  1335 + * @param[in] node XML node containing the response values.
1288 1336 * @param[in] name Parameter name.
1289 1337 * @return Parameter value.
1290 1338 *
1291   - * Returns value for a SAMP client query parameter. If the specified
1292   - * parameter was not found or if the response structure is not compliant,
1293   - * an empty string is returned.
  1339 + * Returns the @p value for the parameter @p name in a list of @p member
  1340 + * XML nodes with the structure
  1341 + *
  1342 + * <member>
  1343 + * <name>name</name>
  1344 + * <value>value</value>
  1345 + * </member>
  1346 + *
  1347 + * If the specified parameter @p name was not found, or the the XML @p node
  1348 + * is NULL, an empty string is returned.
1294 1349 ***************************************************************************/
1295   -std::string GVOHub::get_response_value(const GXml& xml,
  1350 +std::string GVOHub::get_response_value(const GXmlNode* node,
1296 1351 const std::string& name) const
1297 1352 {
1298   - // Declare value
  1353 + // Declare empty value
1299 1354 std::string value = "";
1300 1355  
1301   - // Get the client's private key
1302   - const GXmlNode* node = xml.element("methodCall > params > param[1] > value > struct");
  1356 + // Search for parameter name, and if found, return its value
1303 1357 if (node != NULL) {
1304 1358 int num = node->elements("member");
1305 1359 for (int i = 0; i < num; ++i) {
... ... @@ -1476,322 +1530,6 @@ std::string GVOHub::get_hub_lockfile(void) const
1476 1530  
1477 1531  
1478 1532 /***********************************************************************//**
1479   - * @brief Send notifications
1480   - *
1481   - * @param[in] method Name of the method
1482   - * @param[in] client Reference of the client
1483   - *
1484   - * Send notifications to all registered clients that request so.
1485   - ***************************************************************************/
1486   -void GVOHub::send_notifications(const std::string& method,
1487   - const std::string& client)
1488   -{
1489   - #if defined(G_CONSOLE_DUMP)
1490   - std::cout << "GVOHub::send_notifications 1st form" << std::endl;
1491   - #endif
1492   - // Loop over all clients
1493   - for (int i = 0; i < m_clients.size(); ++i) {
1494   -
1495   - // Loop over all methods
1496   - for (int j = 0; j < m_clients[i].subscriptions.size(); ++j) {
1497   -
1498   - // Continue only if method matches
1499   - if (method == m_clients[i].subscriptions[j]) {
1500   -
1501   - // Declare notification
1502   - std::string msg = "";
1503   -
1504   - // Register
1505   - if (method == "samp.hub.event.register") {
1506   -
1507   - // Set response for samp.hub.event.register
1508   - msg.append("<?xml version=\"1.0\"?>\n");
1509   - msg.append("<methodCall>\n");
1510   - msg.append("<methodName>samp.client.receiveNotification</methodName>\n");
1511   - msg.append("<params>\n");
1512   - msg.append(" <param><value>");
1513   - msg.append(m_clients[i].private_key);
1514   - msg.append("</value></param>\n");
1515   - msg.append(" <param><value>"+m_hub_id+"</value></param>\n");
1516   - msg.append(" <param><value><struct>\n");
1517   - msg.append(" <member>\n");
1518   - msg.append(" <name>samp.mtype</name>\n");
1519   - msg.append(" <value>samp.hub.event.register</value>\n");
1520   - msg.append(" </member>\n");
1521   - msg.append(" <member>\n");
1522   - msg.append(" <name>samp.params</name>\n");
1523   - msg.append(" <value><struct>\n");
1524   - msg.append(" <member>\n");
1525   - msg.append(" <name>id</name>\n");
1526   - msg.append(" <value>"+client+"</value>\n");
1527   - msg.append(" </member>\n");
1528   - msg.append(" </struct></value>\n");
1529   - msg.append(" </member>\n");
1530   - msg.append(" </struct></value></param>\n");
1531   - msg.append("</params>\n");
1532   - msg.append("</methodCall>\n");
1533   -
1534   - // Post notification
1535   - notify(m_clients[i].url, msg);
1536   -
1537   - }
1538   -
1539   - // Unregister
1540   - else if (method == "samp.hub.event.unregister") {
1541   -
1542   - // Set response for samp.hub.event.unregister
1543   - msg.append("<?xml version=\"1.0\"?>\n");
1544   - msg.append("<methodCall>\n");
1545   - msg.append("<methodName>samp.client.receiveNotification</methodName>\n");
1546   - msg.append("<params>\n");
1547   - msg.append(" <param><value>");
1548   - msg.append(m_clients[i].private_key);
1549   - msg.append("</value></param>\n");
1550   - msg.append(" <param><value>");
1551   - msg.append(m_hub_id);
1552   - msg.append("</value></param>\n");
1553   - msg.append(" <param><value><struct>\n");
1554   - msg.append(" <member>\n");
1555   - msg.append(" <name>samp.mtype</name>\n");
1556   - msg.append(" <value>samp.hub.event.unregister</value>\n");
1557   - msg.append(" </member>\n");
1558   - msg.append(" <member>\n");
1559   - msg.append(" <name>samp.params</name>\n");
1560   - msg.append(" <value><struct>\n");
1561   - msg.append(" <member>\n");
1562   - msg.append(" <name>id</name>\n");
1563   - msg.append(" <value>"+client+"</value>\n");
1564   - msg.append(" </member>\n");
1565   - msg.append(" </struct></value>\n");
1566   - msg.append(" </member>\n");
1567   - msg.append(" </struct></value></param>\n");
1568   - msg.append("</params>\n");
1569   - msg.append("</methodCall>\n");
1570   -
1571   - // Post notification
1572   - notify(m_clients[i].url, msg);
1573   -
1574   - }
1575   -
1576   - // Metadata
1577   - else if (method == "samp.hub.event.metadata") {
1578   -
1579   - // Get index of client
1580   - int k;
1581   - for (k = 0; k < m_clients.size(); ++k) {
1582   - if (m_clients[k].reference == client) {
1583   - break;
1584   - }
1585   - }
1586   -
1587   - // Fall through if client index is not valid
1588   - if (k >= m_clients.size()) {
1589   - continue;
1590   - }
1591   -
1592   - // Set response for samp.hub.event.metadata
1593   - msg.append("<?xml version=\"1.0\"?>\n");
1594   - msg.append("<methodCall><methodName>samp.client.receiveNotification</methodName>\n");
1595   - msg.append("<params>\n");
1596   - msg.append(" <param><value>");
1597   - msg.append(m_clients[i].private_key);
1598   - msg.append("</value></param>\n");
1599   - msg.append(" <param><value>"+m_hub_id+"</value></param>\n");
1600   - msg.append(" <param><value><struct>\n");
1601   - msg.append(" <member>\n");
1602   - msg.append(" <name>samp.mtype</name>\n");
1603   - msg.append(" <value>samp.hub.event.metadata</value>\n");
1604   - msg.append(" </member>\n");
1605   - msg.append(" <member>\n");
1606   - msg.append(" <name>samp.params</name>\n");
1607   - msg.append(" <value><struct>\n");
1608   - msg.append(" <member>\n");
1609   - msg.append(" <name>id</name>\n");
1610   - msg.append(" <value>"+m_clients[k].reference+"</value>\n");
1611   - msg.append(" </member>\n");
1612   - msg.append(" <member>\n");
1613   - msg.append(" <name>metadata</name>\n");
1614   - msg.append(" <value><struct>\n");
1615   - msg.append(" <member>\n");
1616   - msg.append(" <name>samp.name</name>\n");
1617   - msg.append(" <value>"+m_clients[k].name+"</value>\n");
1618   - msg.append(" </member>\n");
1619   - msg.append(" <member>\n");
1620   - msg.append(" <name>samp.description.text</name>\n");
1621   - msg.append(" <value>"+m_clients[k].description+"</value>\n");
1622   - msg.append(" </member>\n");
1623   - msg.append(" <member>\n");
1624   - msg.append(" <name>samp.icon.url</name>\n");
1625   - msg.append(" <value>"+m_clients[k].icon+"</value>\n");
1626   - msg.append(" </member>\n");
1627   - msg.append(" <member>\n");
1628   - msg.append(" <name>samp.documentation.url</name>\n");
1629   - msg.append(" <value>"+m_clients[k].documentation+"</value>\n");
1630   - msg.append(" </member>\n");
1631   - msg.append(" <member>\n");
1632   - msg.append(" <name>author.affiliation</name>\n");
1633   - msg.append(" <value>"+m_clients[k].affiliation+"</value>\n");
1634   - msg.append(" </member>\n");
1635   - msg.append(" <member>\n");
1636   - msg.append(" <name>author.name</name>\n");
1637   - msg.append(" <value>"+m_clients[k].author_name+"</value>\n");
1638   - msg.append(" </member>\n");
1639   - msg.append(" <member>\n");
1640   - msg.append(" <name>author.email</name>\n");
1641   - msg.append(" <value>"+m_clients[k].email+"</value>\n");
1642   - msg.append(" </member>\n");
1643   - msg.append(" <member>\n");
1644   - msg.append(" <name>home.page</name>\n");
1645   - msg.append(" <value>"+m_clients[k].homepage+"</value>\n");
1646   - msg.append(" </member>\n");
1647   - msg.append(" </struct></value>\n");
1648   - msg.append(" </member>\n");
1649   - msg.append(" </struct></value>\n");
1650   - msg.append(" </member>\n");
1651   - msg.append(" </struct></value></param>\n");
1652   - msg.append("</params>\n");
1653   - msg.append("</methodCall>\n");
1654   -
1655   - // Post notification
1656   - notify(m_clients[i].url, msg);
1657   -
1658   - } // endelse: metadata
1659   -
1660   - } // endif: method was requested one
1661   -
1662   - } // endfor: looped over all methods
1663   -
1664   - } // endfor: looped over all clients
1665   -
1666   - // Return
1667   - return;
1668   -}
1669   -/***********************************************************************//**
1670   - * @brief Send notifications
1671   - *
1672   - * @param[in] method Name of the method
1673   - * @param[in] client Reference of the client
1674   - * @param[in] xml message sent by the client
1675   - *
1676   - * Send notifications to all registered clients that request so.
1677   - ***************************************************************************/
1678   -void GVOHub::send_notifications(const std::string& method,
1679   - const std::string& client,
1680   - const GXml& xml)
1681   -{
1682   - // Debug: dump information to console
1683   - #if defined(G_CONSOLE_DUMP)
1684   - std::cout << "GVOHub::send_notifications 2nd form" << std::endl;
1685   - std::cout << "GVOHub::send_notifications "+method << std::endl;
1686   - #endif
1687   -
1688   - // Loop over all clients
1689   - for (int i = 0; i < m_clients.size(); ++i) {
1690   -
1691   - // Loop over all methods
1692   - for (int j = 0; j < m_clients[i].subscriptions.size(); ++j) {
1693   -
1694   - // Continue only if method matches
1695   - if (method == m_clients[i].subscriptions[j]) {
1696   -
1697   - // Declare notification
1698   - std::string msg = "";
1699   -
1700   - // Image loading
1701   - if (method == "image.load.fits") {
1702   -
1703   - // Debug: dump information to console
1704   - #if defined(G_CONSOLE_DUMP)
1705   - std::cout << "GVOHub:: Preparing broadcast message" << std::endl;
1706   - #endif
1707   -
1708   - // Declare value
1709   - std::string value = "";
1710   -
1711   - // Search for value of specified member
1712   - const GXmlNode* node = xml.element("methodCall > params > param[2] > value > struct > member > value > struct");
1713   - #if defined(G_CONSOLE_DUMP)
1714   - std::cout << "Searching url value" << std::endl;
1715   - #endif
1716   - if (node != NULL) {
1717   - #if defined(G_CONSOLE_DUMP)
1718   - std::cout << "Node found" << std::endl;
1719   - #endif
1720   - int num = node->elements("member");
1721   - for (int i = 0; i < num; ++i) {
1722   - const GXmlNode* member = node->element("member", i);
1723   - std::string one_name;
1724   - std::string one_value;
1725   - get_name_value_pair(member, one_name, one_value);
1726   - #if defined(G_CONSOLE_DUMP)
1727   - std::cout << "name: "+one_name << std::endl;
1728   - #endif
1729   - if (one_name == "url") {
1730   - value = one_value;
1731   - break;
1732   - }
1733   - }
1734   - } else {
1735   - #if defined(G_CONSOLE_DUMP)
1736   - std::cout << "Node not found" << std::endl;
1737   - #endif
1738   - }
1739   -
1740   - // Set response for image.load.fits
1741   - msg.append("<?xml version=\"1.0\"?>\n");
1742   - msg.append("<methodCall>\n");
1743   - msg.append("<methodName>samp.client.receiveNotification</methodName>\n");
1744   - msg.append("<params>\n");
1745   - msg.append(" <param><value>");
1746   - msg.append(m_clients[i].private_key);
1747   - msg.append("</value></param>\n");
1748   - msg.append(" <param><value>");
1749   - msg.append(m_hub_id);
1750   - msg.append("</value></param>\n");
1751   - msg.append(" <param><value><struct>\n");
1752   - msg.append(" <member>\n");
1753   - msg.append(" <name>samp.mtype</name>\n");
1754   - msg.append(" <value>image.load.fits</value>\n");
1755   - msg.append(" </member>\n");
1756   - msg.append(" <member>\n");
1757   - msg.append(" <name>samp.params</name>\n");
1758   - msg.append(" <value><struct>\n");
1759   - msg.append(" <member>\n");
1760   - msg.append(" <name>name</name>\n");
1761   - msg.append(" <value>Gammalib_shared_fits</value>\n");
1762   - msg.append(" </member>\n");
1763   - msg.append(" <member>\n");
1764   - msg.append(" <name>image-id</name>\n");
1765   - msg.append(" <value>Gammalib_shared_fits_id</value>\n");
1766   - msg.append(" </member>\n");
1767   - msg.append(" <member>\n");
1768   - msg.append(" <name>url</name>\n");
1769   - msg.append(" <value>"+value+"</value>\n");
1770   - msg.append(" </member>\n");
1771   - msg.append(" </struct></value>\n");
1772   - msg.append(" </member>\n");
1773   - msg.append(" </struct></value></param>\n");
1774   - msg.append("</params>\n");
1775   - msg.append("</methodCall>\n");
1776   - #if defined(G_CONSOLE_DUMP)
1777   - std::cout << msg << std::endl;
1778   - #endif
1779   -
1780   - // Post notification
1781   - notify(m_clients[i].url, msg);
1782   -
1783   - }
1784   - } // endif: method was requested one
1785   -
1786   - } // endfor: looped over all methods
1787   -
1788   - } // endfor: looped over all clients
1789   -
1790   - // Return
1791   - return;
1792   -}
1793   -
1794   -/***********************************************************************//**
1795 1533 * @brief Creates the lockfile, fill it
1796 1534 *
1797 1535 * Implements IVOA standard REC-SAMP-1.3-20120411.
... ... @@ -2076,6 +1814,264 @@ void GVOHub::notify(const std::string&amp; url,
2076 1814  
2077 1815  
2078 1816 /***********************************************************************//**
  1817 + * @brief Notify client about another client registering at Hub
  1818 + *
  1819 + * @param[in] client Client to notify.
  1820 + * @param[in] reference Reference to client which registered.
  1821 + *
  1822 + * Notify a client about another client that has registered at the Hub. The
  1823 + * method sends a "samp.hub.event.register" message to the @p client.
  1824 + ***************************************************************************/
  1825 +void GVOHub::notify_register(const GVOHub::client& client,
  1826 + const std::string& reference)
  1827 +{
  1828 + // Declare notification
  1829 + std::string msg = "";
  1830 +
  1831 + // Set response for samp.hub.event.register
  1832 + msg.append("<?xml version=\"1.0\"?>\n");
  1833 + msg.append("<methodCall>\n");
  1834 + msg.append("<methodName>samp.client.receiveNotification</methodName>\n");
  1835 + msg.append("<params>\n");
  1836 + msg.append(" <param><value>"+client.private_key+"</value></param>\n");
  1837 + msg.append(" <param><value>"+m_hub_id+"</value></param>\n");
  1838 + msg.append(" <param><value><struct>\n");
  1839 + msg.append(" <member>\n");
  1840 + msg.append(" <name>samp.mtype</name>\n");
  1841 + msg.append(" <value>samp.hub.event.register</value>\n");
  1842 + msg.append(" </member>\n");
  1843 + msg.append(" <member>\n");
  1844 + msg.append(" <name>samp.params</name>\n");
  1845 + msg.append(" <value><struct>\n");
  1846 + msg.append(" <member>\n");
  1847 + msg.append(" <name>id</name>\n");
  1848 + msg.append(" <value>"+reference+"</value>\n");
  1849 + msg.append(" </member>\n");
  1850 + msg.append(" </struct></value>\n");
  1851 + msg.append(" </member>\n");
  1852 + msg.append(" </struct></value></param>\n");
  1853 + msg.append("</params>\n");
  1854 + msg.append("</methodCall>\n");
  1855 +
  1856 + // Post notification
  1857 + notify(client.url, msg);
  1858 +
  1859 + // Return
  1860 + return;
  1861 +}
  1862 +
  1863 +
  1864 +/***********************************************************************//**
  1865 + * @brief Notify client about another client unregistering at Hub
  1866 + *
  1867 + * @param[in] client Client to notify.
  1868 + * @param[in] reference Reference to client who unregistered.
  1869 + *
  1870 + * Notify a client about another client that has unregistered at the Hub. The
  1871 + * method sends a "samp.hub.event.unregister" message to the @p client.
  1872 + ***************************************************************************/
  1873 +void GVOHub::notify_unregister(const GVOHub::client& client,
  1874 + const std::string& reference)
  1875 +{
  1876 + // Declare notification
  1877 + std::string msg = "";
  1878 +
  1879 + // Set response for samp.hub.event.unregister
  1880 + msg.append("<?xml version=\"1.0\"?>\n");
  1881 + msg.append("<methodCall>\n");
  1882 + msg.append("<methodName>samp.client.receiveNotification</methodName>\n");
  1883 + msg.append("<params>\n");
  1884 + msg.append(" <param><value>"+client.private_key+"</value></param>\n");
  1885 + msg.append(" <param><value>"+m_hub_id+"</value></param>\n");
  1886 + msg.append(" <param><value><struct>\n");
  1887 + msg.append(" <member>\n");
  1888 + msg.append(" <name>samp.mtype</name>\n");
  1889 + msg.append(" <value>samp.hub.event.unregister</value>\n");
  1890 + msg.append(" </member>\n");
  1891 + msg.append(" <member>\n");
  1892 + msg.append(" <name>samp.params</name>\n");
  1893 + msg.append(" <value><struct>\n");
  1894 + msg.append(" <member>\n");
  1895 + msg.append(" <name>id</name>\n");
  1896 + msg.append(" <value>"+reference+"</value>\n");
  1897 + msg.append(" </member>\n");
  1898 + msg.append(" </struct></value>\n");
  1899 + msg.append(" </member>\n");
  1900 + msg.append(" </struct></value></param>\n");
  1901 + msg.append("</params>\n");
  1902 + msg.append("</methodCall>\n");
  1903 +
  1904 + // Post notification
  1905 + notify(client.url, msg);
  1906 +
  1907 + // Return
  1908 + return;
  1909 +}
  1910 +
  1911 +
  1912 +/***********************************************************************//**
  1913 + * @brief Notify client about the metadata of another client
  1914 + *
  1915 + * @param[in] client Client to notify.
  1916 + * @param[in] reference Reference of client for which metadata should be sent.
  1917 + *
  1918 + * Notify a client about another the metadata of another client. The method
  1919 + * sends a "samp.hub.event.metadata" message to the @p client.
  1920 + ***************************************************************************/
  1921 +void GVOHub::notify_metadata(const GVOHub::client& client,
  1922 + const std::string& reference)
  1923 +{
  1924 + // Get index of reference client
  1925 + int k;
  1926 + for (k = 0; k < m_clients.size(); ++k) {
  1927 + if (m_clients[k].reference == reference) {
  1928 + break;
  1929 + }
  1930 + }
  1931 +
  1932 + // Continue only if client index is valid
  1933 + if (k < m_clients.size()) {
  1934 +
  1935 + // Declare notification
  1936 + std::string msg = "";
  1937 +
  1938 + // Set response for samp.hub.event.metadata
  1939 + msg.append("<?xml version=\"1.0\"?>\n");
  1940 + msg.append("<methodCall><methodName>samp.client.receiveNotification</methodName>\n");
  1941 + msg.append("<params>\n");
  1942 + msg.append(" <param><value>"+client.private_key+"</value></param>\n");
  1943 + msg.append(" <param><value>"+m_hub_id+"</value></param>\n");
  1944 + msg.append(" <param><value><struct>\n");
  1945 + msg.append(" <member>\n");
  1946 + msg.append(" <name>samp.mtype</name>\n");
  1947 + msg.append(" <value>samp.hub.event.metadata</value>\n");
  1948 + msg.append(" </member>\n");
  1949 + msg.append(" <member>\n");
  1950 + msg.append(" <name>samp.params</name>\n");
  1951 + msg.append(" <value><struct>\n");
  1952 + msg.append(" <member>\n");
  1953 + msg.append(" <name>id</name>\n");
  1954 + msg.append(" <value>"+m_clients[k].reference+"</value>\n");
  1955 + msg.append(" </member>\n");
  1956 + msg.append(" <member>\n");
  1957 + msg.append(" <name>metadata</name>\n");
  1958 + msg.append(" <value><struct>\n");
  1959 + msg.append(" <member>\n");
  1960 + msg.append(" <name>samp.name</name>\n");
  1961 + msg.append(" <value>"+m_clients[k].name+"</value>\n");
  1962 + msg.append(" </member>\n");
  1963 + msg.append(" <member>\n");
  1964 + msg.append(" <name>samp.description.text</name>\n");
  1965 + msg.append(" <value>"+m_clients[k].description+"</value>\n");
  1966 + msg.append(" </member>\n");
  1967 + msg.append(" <member>\n");
  1968 + msg.append(" <name>samp.icon.url</name>\n");
  1969 + msg.append(" <value>"+m_clients[k].icon+"</value>\n");
  1970 + msg.append(" </member>\n");
  1971 + msg.append(" <member>\n");
  1972 + msg.append(" <name>samp.documentation.url</name>\n");
  1973 + msg.append(" <value>"+m_clients[k].documentation+"</value>\n");
  1974 + msg.append(" </member>\n");
  1975 + msg.append(" <member>\n");
  1976 + msg.append(" <name>author.affiliation</name>\n");
  1977 + msg.append(" <value>"+m_clients[k].affiliation+"</value>\n");
  1978 + msg.append(" </member>\n");
  1979 + msg.append(" <member>\n");
  1980 + msg.append(" <name>author.name</name>\n");
  1981 + msg.append(" <value>"+m_clients[k].author_name+"</value>\n");
  1982 + msg.append(" </member>\n");
  1983 + msg.append(" <member>\n");
  1984 + msg.append(" <name>author.email</name>\n");
  1985 + msg.append(" <value>"+m_clients[k].email+"</value>\n");
  1986 + msg.append(" </member>\n");
  1987 + msg.append(" <member>\n");
  1988 + msg.append(" <name>home.page</name>\n");
  1989 + msg.append(" <value>"+m_clients[k].homepage+"</value>\n");
  1990 + msg.append(" </member>\n");
  1991 + msg.append(" </struct></value>\n");
  1992 + msg.append(" </member>\n");
  1993 + msg.append(" </struct></value>\n");
  1994 + msg.append(" </member>\n");
  1995 + msg.append(" </struct></value></param>\n");
  1996 + msg.append("</params>\n");
  1997 + msg.append("</methodCall>\n");
  1998 +
  1999 + // Post notification
  2000 + notify(client.url, msg);
  2001 +
  2002 + } // endif: reference client was valid
  2003 +
  2004 + // Return
  2005 + return;
  2006 +}
  2007 +
  2008 +
  2009 +/***********************************************************************//**
  2010 + * @brief Notify client about image loading
  2011 + *
  2012 + * @param[in] client Client.
  2013 + * @param[in] xml Message from which image information is extracted.
  2014 + *
  2015 + * Notify a client that a FITS image is avialable for loading. The method
  2016 + * sends a "image.load.fits" message to the @p client. Information about the
  2017 + * image is extracted from the @p xml document.
  2018 + ***************************************************************************/
  2019 +void GVOHub::notify_image_load(const GVOHub::client& client,
  2020 + const GXml& xml)
  2021 +{
  2022 + // Get client response
  2023 + const GXmlNode* node = xml.element("methodCall > params > param[2] > value > struct > member > value > struct");
  2024 +
  2025 + // Extract image information from client response
  2026 + std::string name = get_response_value(node, "name");
  2027 + std::string url = get_response_value(node, "url");
  2028 + std::string id = get_response_value(node, "image-id");
  2029 +
  2030 + // Declare notification
  2031 + std::string msg = "";
  2032 +
  2033 + // Set notification for image.load.fits
  2034 + msg.append("<?xml version=\"1.0\"?>\n");
  2035 + msg.append("<methodCall>\n");
  2036 + msg.append("<methodName>samp.client.receiveNotification</methodName>\n");
  2037 + msg.append("<params>\n");
  2038 + msg.append(" <param><value>"+client.private_key+"</value></param>\n");
  2039 + msg.append(" <param><value>"+m_hub_id+"</value></param>\n");
  2040 + msg.append(" <param><value><struct>\n");
  2041 + msg.append(" <member>\n");
  2042 + msg.append(" <name>samp.mtype</name>\n");
  2043 + msg.append(" <value>image.load.fits</value>\n");
  2044 + msg.append(" </member>\n");
  2045 + msg.append(" <member>\n");
  2046 + msg.append(" <name>samp.params</name>\n");
  2047 + msg.append(" <value><struct>\n");
  2048 + msg.append(" <member>\n");
  2049 + msg.append(" <name>name</name>\n");
  2050 + msg.append(" <value>"+name+"</value>\n");
  2051 + msg.append(" </member>\n");
  2052 + msg.append(" <member>\n");
  2053 + msg.append(" <name>image-id</name>\n");
  2054 + msg.append(" <value>"+id+"</value>\n");
  2055 + msg.append(" </member>\n");
  2056 + msg.append(" <member>\n");
  2057 + msg.append(" <name>url</name>\n");
  2058 + msg.append(" <value>"+url+"</value>\n");
  2059 + msg.append(" </member>\n");
  2060 + msg.append(" </struct></value>\n");
  2061 + msg.append(" </member>\n");
  2062 + msg.append(" </struct></value></param>\n");
  2063 + msg.append("</params>\n");
  2064 + msg.append("</methodCall>\n");
  2065 +
  2066 + // Post notification
  2067 + notify(client.url, msg);
  2068 +
  2069 + // Return
  2070 + return;
  2071 +}
  2072 +
  2073 +
  2074 +/***********************************************************************//**
2079 2075 * @brief Generates random string of characters
2080 2076 *
2081 2077 * @param[in] length Length of random string
... ... @@ -2093,6 +2089,8 @@ std::string GVOHub::random_string(const size_t&amp; length) const
2093 2089 // Return string
2094 2090 return str;
2095 2091 }
  2092 +
  2093 +
2096 2094 /***********************************************************************//**
2097 2095 * @brief Extract mtype from XML request
2098 2096 *
... ... @@ -2122,6 +2120,8 @@ std::string GVOHub::get_mtype(const GXml&amp; xml) const
2122 2120 // Return key
2123 2121 return client_key;
2124 2122 }
  2123 +
  2124 +
2125 2125 /***********************************************************************//**
2126 2126 * @brief Extract client destination from XML request
2127 2127 *
... ... @@ -2133,7 +2133,7 @@ std::string GVOHub::get_destination(const GXml&amp; xml) const
2133 2133 {
2134 2134 // Header
2135 2135 #if defined(G_CONSOLE_DUMP)
2136   - std::cout << "GVOHub::get_mtype" << std::endl;
  2136 + std::cout << "GVOHub::get_destination" << std::endl;
2137 2137 #endif
2138 2138  
2139 2139 // Initialise response
... ...