Source
20
20
//# Correspondence concerning AIPS++ should be addressed as follows:
21
21
//# Internet email: aips2-request@nrao.edu.
22
22
//# Postal address: AIPS++ Project Office
23
23
//# National Radio Astronomy Observatory
24
24
//# 520 Edgemont Road
25
25
//# Charlottesville, VA 22903-2475 USA
26
26
//#
27
27
//# $Id$
28
28
#if ! defined(WITHOUT_DBUS)
29
29
#include <display/QtViewer/QtDBusViewerAdaptor.qo.h>
30
+
#else
31
+
#include <display/QtViewer/grpcViewerAdaptor.qo.h>
32
+
#include <grpc++/grpc++.h>
33
+
#include <casagrpc/protos/registrar.grpc.pb.h>
34
+
#include <casagrpc/protos/img.grpc.pb.h>
35
+
36
+
using casatools::rpc::Registrar;
37
+
30
38
#endif
31
39
#include <display/QtViewer/QtViewer.qo.h>
32
40
#include <display/QtViewer/QtDisplayPanelGui.qo.h>
33
41
#include <display/QtViewer/QtCleanPanelGui.qo.h>
34
42
#include <display/QtViewer/QtCleanPanelGui2.qo.h>
35
43
36
-
37
44
extern int qInitResources_QtViewer();
38
45
39
46
using namespace casacore;
40
47
namespace casa { //# NAMESPACE CASA - BEGIN
41
48
42
-
49
+
#if defined(WITHOUT_DBUS)
50
+
inline std::string to_string(const QString &other) { return std::string((const char*) other.toLatin1().data()); }
51
+
#endif
43
52
QString QtViewer::name_;
44
53
45
54
const QString &QtViewer::name( ) {
46
55
return name_;
47
56
}
48
57
49
-
QtViewer::QtViewer( const std::list<std::string> &args, bool is_server, const char *dbus_name ) :
58
+
QtViewer::QtViewer( const std::list<std::string> &args, bool is_server, const char *server_string ) :
50
59
QtViewerBase(is_server),
51
60
#if ! defined(WITHOUT_DBUS)
52
61
dbus_(NULL),
53
62
#endif
54
63
args_(args), is_server_(is_server) {
55
64
56
65
name_ = (is_server_ ? "view_server" : "viewer");
57
-
dbus_name_ = (dbus_name ? dbus_name : 0);
66
+
server_string_ = (server_string ? server_string : 0);
58
67
59
68
qInitResources_QtViewer();
60
69
// Makes QtViewer icons, etc. available via Qt resource system.
61
70
//
62
71
// You would normally use this macro for the purpose instead:
63
72
//
64
73
// Q_INIT_RESOURCE(QtViewer);
65
74
//
66
75
// It translates as:
67
76
//
68
77
// extern int qInitResources_QtViewer();
69
78
// qInitResources_QtViewer();
70
79
//
71
80
// It doesn't work here because it makes the linker looks for
72
81
// casa::qInitResources_QtViewer() :-) dk
73
82
74
83
if ( is_server_ ) {
75
84
#if ! defined(WITHOUT_DBUS)
76
85
dbus_ = new QtDBusViewerAdaptor(this);
77
-
dbus_->connectToDBus(dbus_name_);
86
+
dbus_->connectToDBus(server_string_);
78
87
} else {
79
88
dbus_ = 0;
80
89
#else
81
-
fprintf( stderr, "CONNECTION TO DBUS WOULD HAPPEN HERE\n" );
82
-
fflush( stderr );
90
+
91
+
grpcViewerState *state = new grpcViewerState(this);
92
+
93
+
//***
94
+
//*** set up a default address (grpc picks port) and address buffers
95
+
//***
96
+
char address_buf[100];
97
+
constexpr char address_template[] = "0.0.0.0:%d";
98
+
snprintf(address_buf,sizeof(address_buf),address_template,0);
99
+
std::string server_address(address_buf);
100
+
int selected_port = 0;
101
+
102
+
//***
103
+
//*** build grpc service
104
+
//***
105
+
grpc::ServerBuilder builder;
106
+
// Listen on the given address without any authentication mechanism.
107
+
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials(), &selected_port);
108
+
// Register "service" as the instance through which we'll communicate with
109
+
// clients. In this case it corresponds to an *synchronous* service.
110
+
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
111
+
// image viewer service (and currently interactive clean service though this needs
112
+
// to eventually move to a seperate grpc service description which could e.g. be
113
+
// shared with carta
114
+
auto viewer_svc = state->viewer_service.get( );
115
+
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
116
+
// all gui operations must happen in the "gui thread" because Qt is not
117
+
// thread-safe... so we need create & result signals and slots
118
+
connect( viewer_svc, SIGNAL(panel(const QString&,bool,int)),
119
+
this, SLOT(grpc_panel(const QString&,bool,int)) );
120
+
connect( this, SIGNAL(grpc_panel_result(QtDisplayPanelGui*,int)),
121
+
viewer_svc, SLOT(panel_result(QtDisplayPanelGui*,int)) );
122
+
builder.RegisterService(viewer_svc);
123
+
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
124
+
// shutdown service is used by casatools etc. to notify gui services
125
+
// when the system is shutting down...
126
+
auto shutdown_svc = state->shutdown_service.get( );
127
+
builder.RegisterService(shutdown_svc);
128
+
connect( shutdown_svc, SIGNAL(exitnow( )),
129
+
this, SLOT(quit( )) );
130
+
131
+
132
+
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
133
+
// Launch server...
134
+
state->server = builder.BuildAndStart( );
135
+
if ( selected_port > 0 ) {
136
+
// if an available port can be found, selected_port is set to a value greater than zero
137
+
snprintf(address_buf,sizeof(address_buf),address_template,selected_port);
138
+
state->uri = address_buf;
139
+
if (getenv("GRPC_DEBUG")) {
140
+
std::cout << "viewer service available at " << state->uri << std::endl;
141
+
fflush(stdout);
142
+
}
143
+
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
144
+
// create the connection to the registrar for service registration using the uri
145
+
// provided on the command line...
146
+
std::unique_ptr<Registrar::Stub> proxy =
147
+
Registrar::NewStub(grpc::CreateChannel(server_string, grpc::InsecureChannelCredentials( )));
148
+
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
149
+
// register our "shutdown, "image-view" and "interactive-clean" services with
150
+
// the registrar...
151
+
casatools::rpc::ServiceId sid;
152
+
sid.set_id("casaviewer");
153
+
sid.set_uri(state->uri);
154
+
sid.add_types("shutdown");
155
+
sid.add_types("image-view");
156
+
sid.add_types("interactive-clean");
157
+
grpc::ClientContext context;
158
+
casatools::rpc::ServiceId accepted_sid;
159
+
if (getenv("GRPC_DEBUG")) {
160
+
std::cout << "registering services with registrar (at " << server_string << ")" << std::endl;
161
+
fflush(stdout);
162
+
}
163
+
::grpc::Status status = proxy->add(&context,sid,&accepted_sid);
164
+
if ( ! status.ok( ) ) {
165
+
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
166
+
// if registration was not successful, we exit...
167
+
std::cerr << "registration failed, exiting..." << std::endl;
168
+
fflush(stderr);
169
+
state->server->Shutdown( );
170
+
QCoreApplication::exit(1);
171
+
exit(1);
172
+
}
173
+
174
+
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
175
+
// complete startup
176
+
grpc_.reset(state);
177
+
if (getenv("GRPC_DEBUG")) {
178
+
std::cout << "accepted service id: ( " << accepted_sid.id( ) << ", " << accepted_sid.uri( ) << ", ";
179
+
for ( auto i=accepted_sid.types( ).begin( ); i != accepted_sid.types( ).end( ); ++i )
180
+
std::cout << "'" << (*i) << "' ";
181
+
std::cout << ")" << std::endl;
182
+
fflush(stdout);
183
+
}
184
+
} else grpc_.reset( );
185
+
83
186
#endif
84
187
}
85
188
}
86
189
87
190
88
191
QtViewer::~QtViewer() {
89
192
// wonder if we need to delete dbus adaptor...
90
193
}
91
194
92
195
QtDisplayPanelGui *QtViewer::createDPG() {
173
276
QtCleanPanelGui2* cpg = new QtCleanPanelGui2(this,0,args_);
174
277
return cpg;
175
278
}
176
279
177
280
void QtViewer::activate( bool state ) {
178
281
for ( panel_list_t::iterator iter = panels.begin( ); iter != panels.end( ); ++iter )
179
282
(*iter)->activate( state );
180
283
}
181
284
182
285
void QtViewer::quit() {
183
-
QtViewerBase::quit();
286
+
#if defined(WITHOUT_DBUS)
287
+
288
+
if ( grpc_ && grpc_->server ) {
289
+
if (getenv("GRPC_DEBUG")) {
290
+
std::cout << "entering QtViewer::quit( )..." << std::endl;
291
+
std::cout << " ...shutting down grpc server..." << std::endl;
292
+
fflush(stdout);
293
+
}
294
+
grpc_->server->Shutdown( );
295
+
}
296
+
297
+
if ( getenv("GRPC_DEBUG") && grpc_->server ) {
298
+
std::cout << " ...shutting down qt..." << std::endl;
299
+
fflush(stdout);
300
+
}
301
+
302
+
#endif
303
+
QtViewerBase::quit();
304
+
#if defined(WITHOUT_DBUS)
305
+
if ( grpc_ && grpc_->server ) {
306
+
QCoreApplication::exit( );
307
+
// calling the system exit( ) here causes immediate
308
+
// shutdown, but does not allow global cleanup...
309
+
}
310
+
#endif
184
311
}
185
312
313
+
#if defined(WITHOUT_DBUS)
314
+
void QtViewer::grpc_panel( const QString &type, bool hidden, int panel_id ){
315
+
316
+
QtDisplayPanelGui *result = 0;
317
+
318
+
if ( type == "clean" ) {
319
+
320
+
// <drs> need to ensure that this is not leaked...
321
+
result = createInteractiveCleanGui( );
322
+
323
+
if ( hidden ) result->hide( );
324
+
325
+
//*grpc* connect(result, SIGNAL(interact(QVariant)), this, SLOT(handle_interact(QVariant)));
326
+
327
+
} else if ( type == "clean2" ) {
328
+
329
+
// <drs> need to ensure that this is not leaked...
330
+
result = createInteractiveCleanGui2( );
331
+
332
+
if ( hidden ) result->hide( );
333
+
334
+
//*grpc* connect(cpg_, SIGNAL(interact(QVariant)), this, SLOT(handle_interact(QVariant)));
335
+
336
+
}
337
+
else {
338
+
339
+
result = createDPG();
340
+
//*grpc* connect( result, SIGNAL(destroyed(QObject*)), SLOT(handle_destroyed_panel(QObject*)) );
341
+
342
+
if ( type.endsWith(".rstr") ) {
343
+
struct stat buf;
344
+
if ( stat( type.toLatin1( ).constData( ), &buf ) == 0 ) {
345
+
result->restorePanelState(to_string(type));
346
+
}
347
+
}
348
+
349
+
if ( hidden ) result->hide( );
350
+
}
351
+
352
+
emit grpc_panel_result( result, panel_id );
353
+
}
354
+
#endif
355
+
186
356
187
357
} //# NAMESPACE CASA - END