Application.cc 30.8 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// $Id$

/*************************************************************************
 * XDAQ Components for Distributed Data Acquisition                      *
 * Copyright (C) 2000-2014, CERN.                                        *
 * All rights reserved.                                                  *
 * Authors: L.Orsini, A.Petrucci, A.Forrest								 *
 * For the licensing terms see LICENSE.                                  *
 * For the list of contributors see CREDITS.                             *
 *************************************************************************/

#include "pt/ibv/Application.h"

#include "cgicc/CgiDefs.h"
#include "cgicc/Cgicc.h"
#include "cgicc/HTTPHTMLHeader.h"
#include "cgicc/HTMLClasses.h"
#include "xgi/Utils.h"
#include "xgi/Input.h"
#include "xgi/Output.h"

#include "xgi/Method.h"
#include "i2o/Method.h"
#include "i2o/utils/AddressMap.h"
#include "pt/PeerTransportAgent.h"

#include "xoap/Method.h"
#include "xdaq/NamespaceURI.h"
#include "xoap/MessageFactory.h"
#include "xoap/SOAPPart.h"
#include "xoap/SOAPEnvelope.h"
#include "xoap/SOAPBody.h"
#include "xoap/domutils.h"
#include "xcept/tools.h"

aforrest's avatar
aforrest committed
36
37
#include "xgi/framework/Method.h"

38
39
40
41
42
43
#include "pt/ibv/PeerTransport.h"
#include "ibvla/Allocator.h"
#include "ibvla/Device.h"
#include "ibvla/Utils.h"

#include "toolbox/string.h"
44
#include "toolbox/fsm/FailedEvent.h"
45
46
47

XDAQ_INSTANTIATOR_IMPL (pt::ibv::Application)

48
pt::ibv::Application::Application (xdaq::ApplicationStub* stub) 
49
50
51
	: xdaq::Application(stub), 
	xgi::framework::UIManager(this),
	fsm_("StateMachine"),
52
	rcmsStateNotifier_(getApplicationLogger(), const_cast<xdaq::ApplicationDescriptor*>(getApplicationDescriptor()),getApplicationContext())
53
{
54
	retrivedRcmsStateListener_ = false;
55
56
57
58
59
60
61
62
63
64
65
66
67
	this->iaName_ = "unknown";

	this->senderPoolSize_ = 0x100000;
	this->receiverPoolSize_ = 0x100000;

	this->recvPoolName_ = "ribv";
	this->sendPoolName_ = "sibv";

	this->completionQueueSize_ = 16;
	this->sendQueuePairSize_ = 16;
	this->recvQueuePairSize_ = 16;

	this->maxMessageSize_ = 4096;
68
	this->maxMessageSizeCheck_ = true;
69
70
71
72
73
74
75
76
	this->deviceMTU_ = 4096;

	this->recvPoolHighThreshold_ = 0.9;
	this->recvPoolLowThreshold_ = 0.7;

	this->sendPoolHighThreshold_ = 0.9;
	this->sendPoolLowThreshold_ = 0.7;

77
	this->sendWithTimeout_ = true;
78
	this->useRelay_ = false;
79
	this->stateName_ = "Halted";
80

81
82
	this->memAllocTimeout_ = "PT5S";

83
84
	stub->getDescriptor()->setAttribute("icon", "/pt/ibv/images/pt-ibv-icon.png");
	stub->getDescriptor()->setAttribute("icon16x16", "/pt/ibv/images/pt-ibv-icon.png");
85
86

	// Define general state machine
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
	fsm_.addState('H', "Halted",this, &pt::ibv::Application::stateChanged);
	fsm_.addState('C', "Connecting", this, &pt::ibv::Application::stateChanged);
	fsm_.addState('E', "Enabled",this, &pt::ibv::Application::stateChanged);
	fsm_.addState('S', "Halting", this, &pt::ibv::Application::stateChanged);

	fsm_.addStateTransition('H', 'C', "connect");
	fsm_.addStateTransition('C', 'E', "enable");
	fsm_.addStateTransition('E', 'S', "halt");
	fsm_.addStateTransition('S', 'H', "done");
	fsm_.addStateTransition('H', 'F', "fail");
	fsm_.addStateTransition('C', 'F', "fail");
	fsm_.addStateTransition('E', 'F', "fail");
	fsm_.addStateTransition('S', 'F', "fail");

	fsm_.setFailedStateTransitionAction( this, &pt::ibv::Application::FailAction );
	fsm_.setFailedStateTransitionChanged(this, &pt::ibv::Application::stateChanged );
	
104
	fsm_.setInitialState('H');
105
106
	fsm_.setStateName('F', "Failed"); // give a name to the 'F' state

107
108
	fsm_.reset();

109
	// Bind CGI callbacks
aforrest's avatar
aforrest committed
110
	xgi::framework::deferredbind(this, this, &pt::ibv::Application::Default, "Default");
111
112
	xgi::bind(this, &pt::ibv::Application::resetAsyncEventCount, "resetAsyncEventCount");
	xgi::bind(this, &pt::ibv::Application::resetWorkCompletionCount, "resetWorkCompletionCount");
113
114
115
116
117
118
119
120
121
	//
	// Bind SOAP callbacks
	//
	xoap::bind(this, &pt::ibv::Application::fireEvent, "Connect", XDAQ_NS_URI );	
	xoap::bind(this, &pt::ibv::Application::fireEvent, "connect", XDAQ_NS_URI );	
	xoap::bind(this, &pt::ibv::Application::fireEvent, "Halt", XDAQ_NS_URI );	
	xoap::bind(this, &pt::ibv::Application::fireEvent, "halt", XDAQ_NS_URI );	
	xoap::bind(this, &pt::ibv::Application::fireEvent, "Fail", XDAQ_NS_URI );	
	xoap::bind(this, &pt::ibv::Application::fireEvent, "fail", XDAQ_NS_URI );	
122
123

	this->getApplicationInfoSpace()->fireItemAvailable("iaName", &iaName_);
124
	this->getApplicationInfoSpace()->fireItemAvailable("memAllocTimeout", &memAllocTimeout_);
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
	this->getApplicationInfoSpace()->fireItemAvailable("receiverPoolSize", &receiverPoolSize_);
	this->getApplicationInfoSpace()->fireItemAvailable("senderPoolSize", &senderPoolSize_);

	this->getApplicationInfoSpace()->fireItemAvailable("recvPoolName", &recvPoolName_);
	this->getApplicationInfoSpace()->fireItemAvailable("sendPoolName", &sendPoolName_);

	this->getApplicationInfoSpace()->fireItemAvailable("recvPoolHighThreshold", &recvPoolHighThreshold_);
	this->getApplicationInfoSpace()->fireItemAvailable("recvPoolLowThreshold", &recvPoolLowThreshold_);
	this->getApplicationInfoSpace()->fireItemAvailable("sendPoolHighThreshold", &sendPoolHighThreshold_);
	this->getApplicationInfoSpace()->fireItemAvailable("sendPoolLowThreshold", &sendPoolLowThreshold_);

	this->getApplicationInfoSpace()->fireItemAvailable("completionQueueSize", &completionQueueSize_);
	this->getApplicationInfoSpace()->fireItemAvailable("sendQueuePairSize", &sendQueuePairSize_);
	this->getApplicationInfoSpace()->fireItemAvailable("recvQueuePairSize", &recvQueuePairSize_);

	this->getApplicationInfoSpace()->fireItemAvailable("maxMessageSize", &maxMessageSize_);
141
	this->getApplicationInfoSpace()->fireItemAvailable("maxMessageSizeCheck", &maxMessageSizeCheck_);
142
143
	this->getApplicationInfoSpace()->fireItemAvailable("deviceMTU", &deviceMTU_);

144
	this->getApplicationInfoSpace()->fireItemAvailable("sendWithTimeout", &sendWithTimeout_);
145
	this->getApplicationInfoSpace()->fireItemAvailable("useRelay", &useRelay_);
146
	this->getApplicationInfoSpace()->fireItemAvailable("stateName", &stateName_);
147

148
149
	getApplicationInfoSpace()->fireItemAvailable("rcmsStateListener", rcmsStateNotifier_.getRcmsStateListenerParameter());
	getApplicationInfoSpace()->fireItemAvailable("foundRcmsStateListener", rcmsStateNotifier_.getFoundRcmsStateListenerParameter());
150
	rcmsStateNotifier_.subscribeToChangesInRcmsStateListener(getApplicationInfoSpace());
151
152


153
154
155
156
157
	// Bind setting of default parameters
	getApplicationInfoSpace()->addListener(this, "urn:xdaq-event:setDefaultValues");

}

158
void pt::ibv::Application::FailAction (toolbox::Event::Reference e) 
159
{
160
	toolbox::fsm::FailedEvent& fe = dynamic_cast<toolbox::fsm::FailedEvent&>(*e);
161

162
	const std::string msg = "Called FailAction of Peer Transport pt::ibv\n";
163
	LOG4CPLUS_ERROR(getApplicationLogger(), msg << xcept::stdformat_exception_history(fe.getException()));
164
165

	// Notify the sentinel
166
	XCEPT_DECLARE_NESTED(pt::ibv::exception::Exception, sentinelException, msg, fe.getException());
167
168
169
170
	this->notifyQualified("error", sentinelException);

}

171
void pt::ibv::Application::stateChanged (toolbox::fsm::FiniteStateMachine &fsm) 
172
{
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
	std::string state = fsm.getStateName (fsm.getCurrentState());
	stateName_ = state;
	LOG4CPLUS_INFO (getApplicationLogger(), "New state is:" << state );
	
	if (state == "Enabled" || state == "Halted"){
		//Send the state notification to RCMS
		notifyRCMS("Changed stated to " + state);
	}
	else if (state == "Failed") {
		notifyRCMS("Changed state to " + state);
	}
	else if (state == "Connecting")
	{
		try
        	{
			// Connect action
			this->autoConnect();	
			toolbox::Event::Reference e(new toolbox::Event("enable",this));
			fsm.fireEvent(e);
        	}
        	catch (xdaq::exception::Exception& e)
        	{
                	LOG4CPLUS_ERROR (getApplicationLogger(), xcept::stdformat_exception_history(e));
        	}
	}
	else if (state == "Halting")
	{
		try
        	{
			// Halt action
			toolbox::Event::Reference e(new toolbox::Event("done",this));
			fsm.fireEvent(e);
        	}
        	catch (xdaq::exception::Exception& e)
        	{
                	LOG4CPLUS_ERROR (getApplicationLogger(), xcept::stdformat_exception_history(e));
        	}
	}

}

void pt::ibv::Application::notifyRCMS(std::string msg ) 
{

    std::string statestr = fsm_.getStateName(fsm_.getCurrentState());

    try
        {
            // if the statenotifier has not been used yet, we have to find him first
            if (!retrivedRcmsStateListener_) 
                {

  			rcmsStateNotifier_.findRcmsStateListener();
			retrivedRcmsStateListener_ = rcmsStateNotifier_.getFoundRcmsStateListenerParameter();
                }
            rcmsStateNotifier_.stateChanged( statestr, msg );
        }

    catch(xcept::Exception &e)
        {
233

234
235
            XCEPT_DECLARE_NESTED( xdaq::exception::Exception, top, "Cannot notify RCMS about asynchronous transition to state \"" + statestr + "\". Continueing anyway...", e);
            this->notifyQualified("error", top);
236

237
        }
238
239
}

240
241


242
243
244
245
246
247
248
249
250
251
252
253
254
//
// run control requests current paramater values
//
void pt::ibv::Application::actionPerformed (xdata::Event& e)
{

	if (e.type() == "urn:xdaq-event:setDefaultValues")
	{

		pt_ = 0;

		try
		{
255
			pt_ = new pt::ibv::PeerTransport(this);
256
257
258
259
260
		}
		catch (pt::exception::Exception & e)
		{
			XCEPT_DECLARE_NESTED(pt::exception::Exception, ex, "Cannot create peer transport", e);
			this->notifyQualified("fatal", ex);
261
262
			try
			{
263
				toolbox::Event::Reference input(new toolbox::Event("fail", this));
264
				fsm_.fireEvent(input);
265
266
			}
			catch (toolbox::fsm::exception::Exception & exception)
267
268
269
270
			{
				XCEPT_DECLARE_NESTED(pt::exception::Exception, ex, "Invalid command", exception);
				this->notifyQualified("fatal", ex);
			}
271
			return;
272
273
274
275
276
		}

		pt::PeerTransportAgent* pta = pt::getPeerTransportAgent();
		pta->addPeerTransport(pt_);

277
278
279
280
		try
		{
			toolbox::Event::Reference input(new toolbox::Event("Configure", this));
			fsm_.fireEvent(input);
281
282
		}
		catch (toolbox::fsm::exception::Exception & exception)
283
284
285
286
		{
			XCEPT_DECLARE_NESTED(pt::exception::Exception, ex, "Invalid command", exception);
			this->notifyQualified("fatal", ex);
		}
287
288
289
		LOG4CPLUS_INFO(this->getApplicationLogger(), "IBV configured");
	}
}
290
xoap::MessageReference pt::ibv::Application::fireEvent (xoap::MessageReference msg) 
291
292
293
294
295
296
297
298
299
300
301
302
303
{
	xoap::SOAPPart part = msg->getSOAPPart();
	xoap::SOAPEnvelope env = part.getEnvelope();
	xoap::SOAPBody body = env.getBody();
	DOMNode* node = body.getDOMNode();
	DOMNodeList* bodyList = node->getChildNodes();

	for (unsigned int i = 0; i < bodyList->getLength(); i++)
	{
		DOMNode* command = bodyList->item(i);

		if (command->getNodeType() == DOMNode::ELEMENT_NODE)
		{
304
			std::string state = "";
305
			std::string commandName = toolbox::tolower(xoap::XMLCh2String(command->getLocalName()));
306

307
308
309
			std::stringstream ss;
			ss << "Received SOAP command '" << commandName << "'";
			LOG4CPLUS_INFO(this->getApplicationLogger(), ss.str());
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
			try {
				std::map<std::string, toolbox::fsm::State, std::less<std::string> >  transitions = fsm_.getTransitions(fsm_.getCurrentState());	
				std::map<std::string, toolbox::fsm::State, std::less<std::string> >::iterator i;
				for ( i = transitions.begin(); i != transitions.end(); i++ ){
					if ((*i).first == commandName) {
						state = fsm_.getStateName ((*i).second);
						LOG4CPLUS_INFO(getApplicationLogger(), "transitions command="+(*i).first + " " + (*i).second );
						break;
					}
				}
				if (state=="") {
					state = fsm_.getStateName(fsm_.getCurrentState());
				}				
				toolbox::Event::Reference e(new toolbox::Event(commandName,this));
				fsm_.fireEvent(e);
				
			} catch (toolbox::fsm::exception::Exception & e)
327
			{
328
329
330
				XCEPT_RETHROW(xoap::exception::Exception, "invalid command", e);
			}		
	
331
332
333
334
			xoap::MessageReference reply = xoap::createMessage();
			xoap::SOAPEnvelope envelope = reply->getSOAPPart().getEnvelope();
			xoap::SOAPName responseName = envelope.createName(commandName + "Response", "xdaq", XDAQ_NS_URI);

335
336
			xoap::SOAPBodyElement responseElement = envelope.getBody().addBodyElement(responseName);
			xoap::SOAPName stateName = envelope.createName("state", "xdaq", XDAQ_NS_URI);
337
338
			xoap::SOAPElement stateElement = responseElement.addChildElement(stateName);
			xoap::SOAPName attributeName = envelope.createName("stateName", "xdaq", XDAQ_NS_URI);
339
			stateElement.addAttribute(attributeName, state);
340
341
342
343
344
345
346
			return reply;
		}
	}

	XCEPT_RAISE(xcept::Exception, "SOAP command not found");
}

347

348
349
void pt::ibv::Application::autoConnect ()
{
350
351
	std::vector<const xdaq::Network*> networks = this->getApplicationContext()->getNetGroup()->getNetworks();
	for (std::vector<const xdaq::Network*>::iterator n = networks.begin(); n != networks.end(); n++)
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
	{
		if ((*n)->getProtocol() == "ibv")
		{
			if ((*n)->isEndpointExisting(this->getApplicationDescriptor()->getContextDescriptor()))
			{
				pt::Address::Reference local = (*n)->getAddress(this->getApplicationDescriptor()->getContextDescriptor());

				std::stringstream ss;
				ss << "Found local network : " << (*n)->getName() << " - " << (*n)->getProtocol() << " - " << local->toString();

				LOG4CPLUS_DEBUG(this->getApplicationLogger(), ss.str());

				std::vector<xdaq::ContextDescriptor*> contexts = this->getApplicationContext()->getContextTable()->getContextDescriptors();

				for (std::vector<xdaq::ContextDescriptor*>::iterator c = contexts.begin(); c != contexts.end(); c++)
				{
					if ((*c)->getURL() != this->getApplicationDescriptor()->getContextDescriptor()->getURL())
					{
						if ((*n)->isEndpointExisting((*c)))
						{
							LOG4CPLUS_DEBUG(this->getApplicationLogger(), "Found Endpoint matching in network " << (*n)->getName() << " for remote context " << (*c)->getURL());

							pt::Address::Reference remote;
							try
							{
								remote = (*n)->getAddress(*c);
							}
							catch (...)
							{
								// there is no matching address for this network
								continue;
							}
							if (!remote->equals(local))
							{
								pt::ibv::Address & rAddr = dynamic_cast<pt::ibv::Address&>(*remote);
								std::stringstream ss;
								ss << "Found remote network (cacheing messenger) : " << (*n)->getName() << " - " << (*n)->getProtocol() << " url: " << rAddr.toString();

								LOG4CPLUS_DEBUG(this->getApplicationLogger(), ss.str());

								pt::Messenger::Reference mr = pt::getPeerTransportAgent()->getMessenger(remote, local);
								pt::ibv::I2OMessenger & m = dynamic_cast<pt::ibv::I2OMessenger&>(*mr);
								try
								{
									m.postConnect();
								}
								catch (pt::ibv::exception::Exception & e)
								{
									LOG4CPLUS_ERROR(this->getApplicationLogger(), "failed to connect cached messenger");
									this->notifyQualified("error", e);
402
403
									try
									{
404
										toolbox::Event::Reference input(new toolbox::Event("fail", this));
405
										fsm_.fireEvent(input);
406
407
									}
									catch (toolbox::fsm::exception::Exception & exception)
408
409
410
									{
										XCEPT_DECLARE_NESTED(pt::exception::Exception, ex, "Invalid command", exception);
										this->notifyQualified("fatal", ex);
411
									}
412
413
								}
							}
414
							std::string enabled("Enabled");
415
416
417
418
							if (fsm_.getStateName(fsm_.getCurrentState()).compare(enabled) != 0)
							{
								try
								{
419
									toolbox::Event::Reference input(new toolbox::Event("enable", this));
420
421
422
423
424
425
426
									fsm_.fireEvent(input);
								}
								catch (toolbox::fsm::exception::Exception & exception)
								{
									XCEPT_DECLARE_NESTED(pt::exception::Exception, ex, "Invalid command", exception);
									this->notifyQualified("fatal", ex);
								}
427
							}
428
429
430
431
432
433
434
435
436
437
438
439
						}
						else
						{
							LOG4CPLUS_DEBUG(this->getApplicationLogger(), "No Endpoint matching in network " << (*n)->getName() << " for remote context " << (*c)->getURL());
						}
					}
				}
			}
		}
	}
}

440
void pt::ibv::Application::resetAsyncEventCount (xgi::Input * in, xgi::Output * out) 
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
{
	size_t n = 0;
	try
	{
		cgicc::Cgicc cgi(in);

		cgicc::form_iterator rl = cgi.getElement("en");
		if (rl != cgi.getElements().end())
		{
			n = cgi["en"]->getIntegerValue();
		}
	}
	catch (const std::exception & e)
	{
		std::cout << "Failed to reset async event count, xgi error" << std::endl;
		return;
	}

	pt_->asyncEventCounter_[n] = 0;

	*out << "<html><head><meta http-equiv=\"refresh\" content=\"0; URL=Default\"></head></html>";
}

464
void pt::ibv::Application::resetWorkCompletionCount (xgi::Input * in, xgi::Output * out) 
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
{
	size_t n = 0;
	try
	{
		cgicc::Cgicc cgi(in);

		cgicc::form_iterator rl = cgi.getElement("en");
		if (rl != cgi.getElements().end())
		{
			n = cgi["en"]->getIntegerValue();
		}
	}
	catch (const std::exception & e)
	{
		std::cout << "Failed to reset work completion count, xgi error" << std::endl;
		return;
	}

	if (n == 100)
	{
		pt_->totalSent_ = 0;
	}
	else if (n == 101)
	{
		pt_->totalRecv_ = 0;
	}
	else
	{
		pt_->workCompletionCounter_[n] = 0;
	}

	*out << "<html><head><meta http-equiv=\"refresh\" content=\"0; URL=Default\"></head></html>";
}

499
void pt::ibv::Application::Default (xgi::Input * in, xgi::Output * out) 
500
{
aforrest's avatar
aforrest committed
501
	*out << "<div class=\"xdaq-tab-wrapper\">" << std::endl;
502

503
504
	if (stateName_ != "failed")
	{
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
		*out << "<div class=\"xdaq-tab\" title=\"Output\">" << std::endl;
		this->SenderTabPage(out);
		*out << "</div>";

		*out << "<div class=\"xdaq-tab\" title=\"Input\">" << std::endl;
		this->ReceiverTabPage(out);
		*out << "</div>";

		*out << "<div class=\"xdaq-tab\" title=\"Settings\">" << std::endl;
		this->SettingsTabPage(out);
		*out << "</div>";

		*out << "<div class=\"xdaq-tab\" title=\"Events\">" << std::endl;
		this->EventsTabPage(out);
		*out << "</div>";
520

521
		*out << "<div class=\"xdaq-tab\" title=\"Endpoints\">" << std::endl;
522
523
		this->EndpointsTabPage(out);
		*out << "</div>";
524
525
526
	}
	else
	{
527
528
529
530
		*out << "<div class=\"xdaq-tab\" title=\"Info\">" << std::endl;
		*out << "The IBV peer transport is in failed state and the HyperDAQ page with more detail information is not available." << std::endl;
		*out << "</div>";
	}
531

532
	*out << "</div>";
533
534
535
536
}

void pt::ibv::Application::SenderTabPage (xgi::Output * sout)
{
537
	std::list < pt::Messenger::Reference > messengers = pt_->getMessengers();
538

539
	*sout << cgicc::table().set("class", "xdaq-table") << std::endl;
540

541
542
543
	*sout << cgicc::caption(iaName_) << std::endl;

	*sout << cgicc::thead() << std::endl;
544
545
546
547
548
549
550
551
552
553

	*sout << cgicc::tr();
	*sout << cgicc::th("IP");
	*sout << cgicc::th("Host");
	*sout << cgicc::th("Port");
	*sout << cgicc::th("Sent");
	*sout << cgicc::th("Scheduled sends");
	*sout << cgicc::th("Local QPN");
	*sout << cgicc::th("Remote QPN");
	*sout << cgicc::th("QP State");
554
	*sout << cgicc::th("Connection Time");
555
556
557
	//*sout << cgicc::th("");
	*sout << cgicc::tr() << std::endl;

558
559
560
561
	*sout << cgicc::thead() << std::endl;

	*sout << cgicc::tbody() << std::endl;

562
563
564
565
566
567
568
569
570
571
572
573
	for (std::list<pt::Messenger::Reference>::iterator i = messengers.begin(); i != messengers.end(); i++)
	{
		pt::ibv::I2OMessenger * m = dynamic_cast<pt::ibv::I2OMessenger*>(&(*(*i)));
		*sout << *m << std::endl;
	}

	*sout << cgicc::tbody();
	*sout << cgicc::table();
}

void pt::ibv::Application::ReceiverTabPage (xgi::Output * sout)
{
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598

	*sout << cgicc::table().set("class", "xdaq-table") << std::endl;
	*sout << cgicc::caption(iaName_) << "-" << " receive completion queue " << std::endl;

	*sout << cgicc::thead() << std::endl;

	*sout << cgicc::tr();
	*sout << cgicc::th("Idle");
	*sout << cgicc::th("Actual receive");
	*sout << cgicc::tr() << std::endl;

	*sout << cgicc::thead() << std::endl;


	*sout << cgicc::tbody() << std::endl;
	*sout << cgicc::tr();
	*sout << "<td>" << pt_->getCompletionWorLoopReceiver()->emptyDispatcherQueueCounter_ << "</td>";
	*sout << "<td>" << pt_->getCompletionWorLoopReceiver()->receivedEventCounter_ << "</td>";
	*sout << cgicc::tr();
	*sout << cgicc::tbody();
	*sout << cgicc::table();


	// queue pair statistics

599
600
	std::list < ibvla::QueuePair > qps = pt_->getAcceptedQueuePairs();

601
	*sout << cgicc::table().set("class", "xdaq-table") << std::endl;
602

603
604
605
	*sout << cgicc::caption(iaName_) << std::endl;

	*sout << cgicc::thead() << std::endl;
606
607
608
609
610
611
612
613
614
615
616

	*sout << cgicc::tr();
	*sout << cgicc::th("IP");
	*sout << cgicc::th("Hostname");
	*sout << cgicc::th("Recv count");
	*sout << cgicc::th("Local QPN");
	*sout << cgicc::th("Remote QPN");
	*sout << cgicc::th("QP State");
	//*sout << cgicc::th("");
	*sout << cgicc::tr() << std::endl;

617
618
619
620
	*sout << cgicc::thead() << std::endl;

	*sout << cgicc::tbody() << std::endl;

621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
	for (std::list<ibvla::QueuePair>::iterator i = qps.begin(); i != qps.end(); i++)
	{
		struct pt::ibv::PeerTransport::qpInfo * info = ((struct pt::ibv::PeerTransport::qpInfo *) (*i).getContext());
		*sout << cgicc::tr();
		*sout << "<td>" << info->ip << "</td>"; // ip
		*sout << "<td>" << info->host << "</td>"; // hostname
		*sout << "<td>" << info->recv_count << "</td>"; //
		*sout << "<td>";
		*sout << (*i).qp_->qp_num << std::endl; // qp
		*sout << "</td>";
		*sout << "<td>";
		*sout << info->remote_qpn << std::endl; // qp
		*sout << "</td>";

		if ((*i).getState() == IBV_QPS_ERR)
		{
637
			*sout << "<td class=\"xdaq-red\">";
638
639
640
		}
		else if ((*i).getState() == IBV_QPS_INIT)
		{
641
			*sout << "<td class=\"xdaq-blue\">";
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
		}
		else
		{
			*sout << "<td>";
		}

		*sout << ibvla::stateToString(*i) << std::endl; // qp
		*sout << "</td>";

		//*sout << "<td><a href=\"destroyAcceptedQueuePair?qpn=" << (*i).qp_->qp_num << "\">Destroy</a></td>";
		//*sout << "<td><input type=\"button\" class=\"red-button\" onClick=\"parent.location='destroyAcceptedQueuePair?qpn=" << (*i).qp_->qp_num << "'\" value=\"Destroy\"></td>" << std::endl;
		*sout << cgicc::tr() << std::endl;
	}

	*sout << cgicc::tbody();
	*sout << cgicc::table();
}

void pt::ibv::Application::SettingsTabPage (xgi::Output * sout)
{
662
	*sout << cgicc::table().set("class", "xdaq-table-vertical") << std::endl;
663

664
	*sout << cgicc::tbody() << std::endl;
665
666

	*sout << cgicc::tr();
aforrest's avatar
aforrest committed
667
	*sout << "<th class=\"xdaq-tooltip\">" << "Device Name" << " <span class=\"xdaq-tooltip-msg\">" << "NIC name" << "</span></th>";
668
	*sout << "<td style=\"text-align:center;\">" << iaName_.toString() << "</td>";
669
670
	*sout << cgicc::tr() << std::endl;

671
	size_t realMTU = ibvla::mtu_to_enum(deviceMTU_);
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
	if (realMTU == 1)
		realMTU = 256;
	else if (realMTU == 2)
		realMTU = 512;
	else if (realMTU == 3)
		realMTU = 1024;
	else if (realMTU == 4)
		realMTU = 2048;
	else if (realMTU == 5)
		realMTU = 4096;
	else
		realMTU = 0;

	const int MB = 1048576.0;

	*sout << cgicc::tr();
aforrest's avatar
aforrest committed
688
	*sout << "<th class=\"xdaq-tooltip\">" << "MTU" << " <span class=\"xdaq-tooltip-msg\">" << "Configured max transfer unit for the device" << "</span></th>";
689
690
691

	if (realMTU == 0)
	{
692
		*sout << "<td class=\"xdaq-red\" style=\"text-align:center;\">";
693
694
695
	}
	else
	{
696
		*sout << "<td style=\"text-align:center;\">";
697
698
699
700
701
	}
	*sout << realMTU << "</td>";
	*sout << cgicc::tr() << std::endl;

	*sout << cgicc::tr();
702
	*sout << "<th class=\"xdaq-tooltip\">" << "Max Message Size" << " <span class=\"xdaq-tooltip-msg\">" << "Maximum message size that can be sent" << "</span></th>";
703
	*sout << "<td style=\"text-align:center;\">" << maxMessageSize_ << "</td>";
704
705
706
	*sout << cgicc::tr() << std::endl;

	*sout << cgicc::tr();
aforrest's avatar
aforrest committed
707
	*sout << "<th class=\"xdaq-tooltip\">" << "Completion Queue Size" << " <span class=\"xdaq-tooltip-msg\">" << "Size of the completion queues (1 for send, 1 for receive)" << "</span></th>";
708
709
710
711
	*sout << "<td style=\"text-align:center;\">" << completionQueueSize_ << "</td>";
	*sout << cgicc::tr() << std::endl;

	*sout << cgicc::tr();
aforrest's avatar
aforrest committed
712
	*sout << "<th class=\"xdaq-tooltip\">" << "Send Queue Size" << " <span class=\"xdaq-tooltip-msg\">" << "Maximum number of messages that can be queued to send at once" << "</span></th>";
713
714
715
716
	*sout << "<td style=\"text-align:center;\">" << sendQueuePairSize_ << "</td>";
	*sout << cgicc::tr() << std::endl;

	*sout << cgicc::tr();
aforrest's avatar
aforrest committed
717
	*sout << "<th class=\"xdaq-tooltip\">" << "Receive Queue Size" << " <span class=\"xdaq-tooltip-msg\">" << "Number of buffers that are posted to receive into" << "</span></th>";
718
719
720
721
	*sout << "<td style=\"text-align:center;\">" << recvQueuePairSize_ << "</td>";
	*sout << cgicc::tr() << std::endl;

	*sout << cgicc::tr();
aforrest's avatar
aforrest committed
722
	*sout << "<th class=\"xdaq-tooltip\">" << "Receive Queue Memory" << " <span class=\"xdaq-tooltip-msg\">" << "How much memory is taken up by the receive queue (recvQueuePairSize * maxMessageSize)" << "</span></th>";
723
	*sout << "<td style=\"text-align:center;\">" << ((double) (recvQueuePairSize_ * maxMessageSize_)) / MB << " MB</td>";
724
725
726
	*sout << cgicc::tr() << std::endl;

	*sout << cgicc::tr();
aforrest's avatar
aforrest committed
727
	*sout << "<th class=\"xdaq-tooltip\">" << "Receive Pool Size" << "</th>";
728
729
730
731
	*sout << "<td style=\"text-align:center;\">" << ((double) receiverPoolSize_) / MB << " MB</td>";
	*sout << cgicc::tr() << std::endl;

	*sout << cgicc::tr();
aforrest's avatar
aforrest committed
732
	*sout << "<th class=\"xdaq-tooltip\">" << "Send Pool Size" << "</th>";
733
734
735
	*sout << "<td style=\"text-align:center;\">" << ((double) senderPoolSize_) / MB << " MB</td>";
	*sout << cgicc::tr() << std::endl;

736
	*sout << cgicc::tr();
aforrest's avatar
aforrest committed
737
	*sout << "<th class=\"xdaq-tooltip\">" << "Use Relay" << "</th>";
738
739
	if (useRelay_)
	{
740
		*sout << "<td style=\"text-align:center;\">true</td>";
741
742
743
	}
	else
	{
744
		*sout << "<td style=\"text-align:center;\">false</td>";
745
746
747
	}
	*sout << cgicc::tr() << std::endl;

748
749
750
751
752
753
	*sout << cgicc::tbody();
	*sout << cgicc::table();
}

void pt::ibv::Application::EventsTabPage (xgi::Output * sout)
{
aforrest's avatar
aforrest committed
754
	*sout << "<table><tr><td style=\"vertical-align:top; padding-right: 20px;\">" << std::endl;
755
756
757

	//////////

aforrest's avatar
aforrest committed
758
759
760
	std::stringstream myurl;
	myurl << this->getApplicationDescriptor()->getContextDescriptor()->getURL() << "/" << this->getApplicationDescriptor()->getURN() << "/";

761
	*sout << cgicc::table().set("class", "xdaq-table") << std::endl;
762

763
764
	*sout << cgicc::caption("Asynchronous Events") << std::endl;

765
766
767
768
	*sout << cgicc::thead() << std::endl;
	*sout << cgicc::tr();
	*sout << cgicc::th("Name");
	*sout << cgicc::th("Count");
aforrest's avatar
aforrest committed
769
	*sout << cgicc::th("");
770
771
772
	*sout << cgicc::tr();
	*sout << cgicc::thead() << std::endl;

773
	*sout << cgicc::tbody() << std::endl;
774
775
776
777

	for (size_t i = 0; i < MAX_ASYNC_EVENT; i++)
	{
		*sout << cgicc::tr();
778
		*sout << "<td class=\"xdaq-tooltip\" style=\"text-align: right;\">" << ibvla::asyncEventToStringLiteral(i) << " <span class=\"xdaq-tooltip-msg\">" << ibvla::asyncEventToString(i) << "</span></td>";
779
780
		*sout << "<td>" << pt_->asyncEventCounter_[i] << "</td>";
		*sout << "<td><input type=\"button\" onClick=\"parent.location='" << myurl.str() << "resetAsyncEventCount?en=" << i << "'\" value=\"Reset\"></td>" << std::endl;
781
782
783
784
785
786
787
788
789

		*sout << cgicc::tr() << std::endl;
	}

	*sout << cgicc::tbody();
	*sout << cgicc::table();

	//////////

aforrest's avatar
aforrest committed
790
	*sout << "</td><td style=\"vertical-align:top; padding-right: 20px;\">" << std::endl;
791
792
793

	//////////

794
	*sout << cgicc::table().set("class", "xdaq-table") << std::endl;
795

796
797
	*sout << cgicc::caption("Work Completions") << std::endl;

798
799
800
801
	*sout << cgicc::thead() << std::endl;
	*sout << cgicc::tr();
	*sout << cgicc::th("Name");
	*sout << cgicc::th("Count");
802
	*sout << cgicc::th("");
803
804
805
	*sout << cgicc::tr();
	*sout << cgicc::thead() << std::endl;

806
	*sout << cgicc::tbody() << std::endl;
807
808
809

	// Do total sent / received first
	*sout << cgicc::tr();
810
	*sout << "<td style=\"text-align: right;\">Sent</td>";
811
812
	*sout << "<td>" << pt_->totalSent_ << "</td>";
	*sout << "<td><input type=\"button\" onClick=\"parent.location='" << myurl.str() << "resetWorkCompletionCount?en=100'\" value=\"Reset\"></td>" << std::endl;
813
	*sout << cgicc::tr() << std::endl;
814

815
	*sout << cgicc::tr();
816
	*sout << "<td style=\"text-align: right;\">Received</td>";
817
818
	*sout << "<td>" << pt_->totalRecv_ << "</td>";
	*sout << "<td><input type=\"button\" onClick=\"parent.location='" << myurl.str() << "resetWorkCompletionCount?en=101'\" value=\"Reset\"></td>" << std::endl;
819
820
821
822
823
	*sout << cgicc::tr() << std::endl;

	for (size_t i = 1; i < MAX_WC_EVENT; i++) // 0 == success
	{
		*sout << cgicc::tr();
824
		*sout << "<td class=\"xdaq-tooltip\" style=\"text-align: right;\">" << ibvla::workCompletionToStringLiteral(i) << " <span class=\"xdaq-tooltip-msg\">" << ibvla::workCompletionToString(i) << "</span></td>";
825
826
827

		if (pt_->workCompletionCounter_[i] != 0)
		{
828
			*sout << "<td class\"xdaq-red\">";
829
830
831
		}
		else
		{
832
			*sout << "<td>";
833
834
835
		}

		*sout << pt_->workCompletionCounter_[i] << "</td>";
836
		*sout << "<td><input type=\"button\" onClick=\"parent.location='" << myurl.str() << "resetWorkCompletionCount?en=" << i << "'\" value=\"Reset\"></td>" << std::endl;
837
838
839
840
841
842
843
844
845
846
847
		*sout << cgicc::tr() << std::endl;
	}

	*sout << cgicc::tbody();
	*sout << cgicc::table();

	//////////

	*sout << "</td></tr></table>";
}

848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
void pt::ibv::Application::EndpointsTabPage (xgi::Output * sout)
{

	std::vector<const xdaq::Network*> networks = this->getApplicationContext()->getNetGroup()->getNetworks();
	for (std::vector<const xdaq::Network*>::iterator n = networks.begin(); n != networks.end(); n++)
	{
		if ((*n)->getProtocol() == "ibv")
		{
				if ((*n)->isEndpointExisting(this->getApplicationDescriptor()->getContextDescriptor()))
				{
					pt::Address::Reference local = (*n)->getAddress(this->getApplicationDescriptor()->getContextDescriptor());

					//std::stringstream ss;
					//ss << "Found local network : " << (*n)->getName() << " - " << (*n)->getProtocol() << " - " << local->toString();

					pt::ibv::Address & lAddr = dynamic_cast<pt::ibv::Address&>(*local);

					*sout << cgicc::table().set("class", "xdaq-table-vertical") << std::endl;
					*sout << cgicc::tbody() << std::endl;

					*sout << cgicc::tr();
					*sout << "<th style=\"text-align:left;\">URL</th>";
					*sout << "<td style=\"text-align:center;\">" << lAddr.getURL() << "</td>";
					*sout << cgicc::tr() << std::endl;

					*sout << cgicc::tr();
					*sout << "<th style=\"text-align:left;\">Network Name</th>";
					*sout << "<td style=\"text-align:center;\">" << (*n)->getName() << "</td>";
					*sout << cgicc::tr() << std::endl;

					*sout << cgicc::tr();
					*sout << "<th style=\"text-align:left;\">Protocol</th>";
					*sout << "<td style=\"text-align:center;\">" << (*n)->getProtocol() << "</td>";
					*sout << cgicc::tr() << std::endl;

					*sout << cgicc::tr();
					*sout << "<th style=\"text-align:left;\">Service</th>";
					*sout << "<td style=\"text-align:center;\">" << lAddr.getService() << "</td>";
					*sout << cgicc::tr() << std::endl;

					*sout << cgicc::tr();
					*sout << "<th style=\"text-align:left;\">Host</th>";
					*sout << "<td style=\"text-align:center;\">" << lAddr.getHost() << "</td>";
					*sout << cgicc::tr() << std::endl;

					*sout << cgicc::tr();
					*sout << "<th style=\"text-align:left;\">Port</th>";
					*sout << "<td style=\"text-align:center;\">" << lAddr.getPort() << "</td>";
					*sout << cgicc::tr() << std::endl;

					*sout << cgicc::tr();
					*sout << "<th style=\"text-align:left;\">IBPort</th>";
					*sout << "<td style=\"text-align:center;\">" << lAddr.getIBPort() << "</td>";
					*sout << cgicc::tr() << std::endl;

					*sout << cgicc::tr();
					*sout << "<th style=\"text-align:left;\">IBPath</th>";
					*sout << "<td style=\"text-align:center;\">" << lAddr.getIBPath() << "</td>";
					*sout << cgicc::tr() << std::endl;

					*sout << cgicc::tr();
					*sout << "<th style=\"text-align:left;\">IsGlobal</th>";
					*sout << "<td style=\"text-align:center;\">" << lAddr.getIsGlobal() << "</td>";
					*sout << cgicc::tr() << std::endl;

					*sout << cgicc::tr();
					*sout << "<th style=\"text-align:left;\">SGIDIndex</th>";
					*sout << "<td style=\"text-align:center;\">" << lAddr.getSGIDIndex() << "</td>";
					*sout << cgicc::tr() << std::endl;

					*sout << cgicc::tbody();
					*sout << cgicc::table();

				}
		}
	}

}