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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
|
<!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD>
<TITLE>nevrax.org : docs</TITLE>
<LINK REL=stylesheet TYPE="text/css" HREF="/inc/css/nevrax.css">
<link href="doxygen.css" rel="stylesheet" type="text/css">
</HEAD>
<BODY MARGINHEIGHT="0" MARGINWIDTH="0">
<!-- uplinks -->
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0>
<TR>
<TD WIDTH=16><IMG SRC="/inc/img/pixel.gif" WIDTH="16" HEIGHT="16" BORDER=0 ALT=""></TD>
<TD WIDTH=140 BGCOLOR=#dddddd><IMG SRC="/inc/img/pixel.gif" WIDTH="140" HEIGHT="16" BORDER=0 ALT=""></TD>
<TD WIDTH=16><IMG SRC="/inc/img/pixel.gif" WIDTH="16" HEIGHT="16" BORDER=0 ALT=""></TD>
<TD><IMG width=6 height=14 SRC="/inc/img/reddots.gif" ALT="#" VSPACE=2 HSPACE=2 BORDER=0 ></TD><TD VALIGN=middle> <A CLASS=uplinks HREF='/'><b>Home</B></FONT></A> </TD>
<TD><IMG width=6 height=14 SRC="/inc/img/reddots.gif" ALT="#" VSPACE=2 HSPACE=2 BORDER=0 ></TD><TD VALIGN=middle> <A CLASS=uplinks HREF='/'><b>nevrax.com</B></FONT></A> </TD>
</TR>
</TABLE>
<!-- banner Nevrax -->
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%>
<TR><TD BGCOLOR="#000000" BACKGROUND="/inc/img/black_banner.jpg"><A HREF=""><IMG SRC="/inc/img/nevrax.gif" WIDTH="170" HEIGHT="45" BORDER=0 ALT="Nevrax" ></A></TD></TR>
</TABLE>
<!-- main table -->
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 height=100%>
<TR>
<TD WIDTH=16><IMG SRC="/inc/img/pixel.gif" WIDTH="16" HEIGHT="10" BORDER=0 ALT=""></TD>
<TD WIDTH=140 BGCOLOR=#dddddd VALIGN=TOP ALIGN=middle><IMG SRC="/inc/img/pixel.gif" WIDTH="140" HEIGHT="10" BORDER=0 ALT="">
<!------ Begin Box ------>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 BGCOLOR=black><TR><TD><TABLE border=0 cellspacing=2 cellpadding=0 width=120><tr><TD ALIGN=middle bgcolor=black>
<FONT COLOR=white FACE="sans-serif"><B>Nevrax.org</B></FONT></TD></TR><tr><td colspan=2 bgcolor=#FFFFFF>
<TABLE cellspacing=0 cellpadding=1 border=0>
<tr><td ALIGN=middle><a class='linkbox' href="/news/" TITLE="Rubrique news"><img width=13 height=15 hspace=5 border=0 src=/inc/img/picto-news.gif ALT=#></A></td><td><a class='linkbox' href="/news/" TITLE="News">News</a></td></tr>
<tr><td ALIGN=middle><a class='linkbox' href="/mail/" TITLE="Rubrique mail"><img width=15 height=11 hspace=5 border=0 src=/inc/img/picto-mail.gif ALT=#></A></td><td><a class='linkbox' href="/mail/" TITLE="Mailing list archive">Mailing-list</a></td></tr>
<tr><td ALIGN=middle><a class='linkbox' href="/docs/" TITLE="Rubrique docs"><img width=14 height=16 hspace=5 border=0 src=/inc/img/picto-docs.gif ALT=#></A></td><td><a class='linkbox' href="/docs/" TITLE="Documentation">Documentation</a></td></tr>
<tr><td ALIGN=middle><a class='linkbox' href="/cvs/" TITLE="Rubrique cvs"><img width=13 height=17 hspace=5 border=0 src=/inc/img/picto-cvs.gif ALT=#></A></td><td><a class='linkbox' href="/cvs/" TITLE="CVS Web">CVS</a></td></tr>
<tr><td ALIGN=middle><a class='linkbox' href="/bugs/" TITLE="Rubrique bugs"><img width=20 height=16 hspace=5 border=0 src=/inc/img/picto-bugs.gif ALT=#></A></td><td><a class='linkbox' href="/bugs/" TITLE="Bugtracking">Bugs</a></td></tr>
<tr><td ALIGN=middle><a class='linkbox' href="/GPL.php3" TITLE="Rubrique license"><img width=18 height=12 hspace=5 border=0 src=/inc/img/picto-gpl.gif ALT=#></A></td><td><a class='linkbox' href="/GPL.php3" TITLE="License">License</a></td></tr>
</TABLE>
</TD></TR></TABLE></TD></TR></TABLE>
<!------ End Box ------>
</TD>
<TD WIDTH=15><IMG SRC="/inc/img/pixel.gif" WIDTH="16" HEIGHT="16" BORDER=0 ALT=""></TD>
<TD ALIGN=left valign=top><IMG SRC="/inc/img/pixel.gif" WIDTH="140" HEIGHT="10" BORDER=0 ALT="">
<!-- title -->
<TABLE background="/inc/img/redline.gif" CELLSPACING=0 CELLPADDING=0 BORDER=0 width=100%><tr><td>
<A HREF="/docs/"><img src="/inc/img/t_docs.gif" ALT="Docs" HEIGHT=20 BORDER=0></A>
</td><td><IMG SRC="/inc/img/pixel.gif" WIDTH="1" HEIGHT="1" BORDER=0 ALT="">
</td></tr></table>
<!-- block -->
<TABLE bgcolor="#dddddd" CELLSPACING=0 CELLPADDING=0 BORDER=0 width=100%><tr><td width=1% valign=middle><img width=6 height=14 hspace=2 vspace=2 src="/inc/img/reddots.gif"></TD>
<TD><B>Documentation</B></TD>
<TD ALIGN=RIGHT> </td>
</tr></table>
<!-- Generated by Doxygen 1.2.14 -->
<center>
<a class="qindex" href="index.html">Main Page</a> <a class="qindex" href="namespaces.html">Namespace List</a> <a class="qindex" href="hierarchy.html">Class Hierarchy</a> <a class="qindex" href="classes.html">Alphabetical List</a> <a class="qindex" href="annotated.html">Compound List</a> <a class="qindex" href="files.html">File List</a> <a class="qindex" href="namespacemembers.html">Namespace Members</a> <a class="qindex" href="functions.html">Compound Members</a> <a class="qindex" href="globals.html">File Members</a> <a class="qindex" href="pages.html">Related Pages</a> <a class="qindexRef" doxygen="_cgi:/cgi-bin/nel-search.cgi" href="/cgi-bin/nel-search.cgi">Search</a> </center>
<hr><a name="message_recorder"><h2>The NeL Net Message Recorder</h2></a>
<dl compact><dt><b>
Author: </b><dd>
Olivier Cado</dl><dl compact><dt><b>
Date: </b><dd>
June 12, 2001</dl><a name="mroverview"><h2>Overview</h2></a>
<p>
When creating client-server applications, it is generally hard to debug one program, because you need one or more external processes to run it. Moreover, these other external programs should work perfectly in order to debug the first program, but to test them you need the first program to work perfectly too ! Eventually, when several processes run in parallel and interact with each other, a bug behaviour is difficult to reproduce.
<p>
The Message Recorder allows to record every message and network event (connection, disconnection...) that is managed by the Nel network engine. Then, it is easy to replay the sequence later, even if the peers (clients or servers) are not running, and to trace it with a debugger.
<p>
<a name="mrhtrecord"><h2>How to record and replay ?</h2></a>
<p>
<a name="mrrecservice"><h3>In a service</h3></a>
<p>
If your program is a service based on the NeL service framework (see <a class="el" href="classNLNET_1_1IService.html">NLNET::IService</a>), all you have to do is to add the following line in the config file of the service (this is also where you type the address of the Naming Service): <div class="fragment"><pre>Rec = <font class="stringliteral">"Record"</font>;
</pre></div> or <div class="fragment"><pre>Rec = <font class="stringliteral">"Replay"</font>;
</pre></div>
<p>
Note that in the first case, you lauch the service in the same way as usual, launching other services such as the Naming Service before, but in the second case, the service process is the only one required.
<p>
To disable recording/replaying, remove or comment out the line in the config file, or set it to: <div class="fragment"><pre>Rec = <font class="stringliteral">"Off"</font>;
</pre></div>
<p>
Besides, if your service creates some client connections using layer 3, creating CCallbackClient or CCallbackServer objects, you need to change the code. For example:
<p>
<div class="fragment"><pre>MyConnection = <font class="keyword">new</font> CCallbackClient( <font class="stringliteral">"OneService"</font> );
</pre></div> becomes <div class="fragment"><pre>MyConnection = <font class="keyword">new</font> CCallbackClient( <font class="stringliteral">"OneService"</font>, IService::recordingState(), <font class="stringliteral">"one_service.nmr"</font> );
</pre></div>
<p>
If your service uses layer 4 to create additionnal connections, using CNetManager::addClient() or CNetManager::addServer(), you don't need to change the code.
<p>
<a name="mrrecclient"><h3>In another type of program</h3></a>
<p>
If your program is not based on the service framework, there is no standard config file. Consequently, you need to change the code. For example, using layer 3:
<p>
<div class="fragment"><pre>MyConnection = <font class="keyword">new</font> CCallbackClient( <font class="stringliteral">"OneService"</font> );
</pre></div> becomes <div class="fragment"><pre>MyConnection = <font class="keyword">new</font> CCallbackClient( <font class="stringliteral">"OneService"</font>, CCallbackNetBase::Record,
<font class="stringliteral">"one_service.nmr"</font> );
</pre></div>
<p>
The type of the second argument is CCallbackNetBase::TRecordingState and can take one of these values: Off, Record, Replay.
<p>
Using layer 4, all you have to do is to pass the recording state to CNetManager::init().
<p>
<a name="mrfiles"><h2>Where are stored the messages and network events ?</h2></a>
<p>
In the examples above, we set the output/input file to "one_service.nmr". When using layer 4 or the service framework, each client connection or server gets a short service name, such as NS for Naming Service. The output/input filenames are built upon this short service name and the extension ".nmr". NMR stands for NeL Message Record.
<p>
Consequently, do not run several programs located in the same directory in record or replay mode at the same time. The filenames would conflict.
<p>
The messages and events are stored in plain text, so that anyone can read them.
<p>
<a name="mrdef"><h2>Required NeL settings</h2></a>
In <a class="el" href="callback__net__base_8h.html">nel/net/callback_net_base.h</a>, the macro USE_MESSAGE_RECORDER must be defined. In <a class="el" href="message_8h.html">nel/net/message.h</a>, the macro MESSAGES_PLAIN_TEXT must be defined.
<p>
<a name="mrfaq"><h2>Frequently Asked Questions</h2></a>
<p>
<ul>
<li>Why don't I see exactly the same outputs in the logs, in replay mode ?</ul>
In replay mode, the sockets operations are only simulated, the implementation of the network engine is very different; there are no additional threads; the sending of data does not simulate the buffering delays. That is why some outputs are not displayed. Keep in mind that the message recorder's goal is to replay a sequence of users' messages to debug users' code, and not to debug NeL itself.
<p>
<ul>
<li>When replaying a sequence, what does the following warning means ?</ul>
<div class="fragment"><pre>WRN <thread_id> : L3C: No disconnection event <a class="code" href="driver__opengl__extension__def_8h.html#a404">in</a> the replay <a class="code" href="driver__opengl__extension__def_8h.html#a394">data</a>
</pre></div> It means that your program is actively disconnecting a socket, while the disconnection has not been recorded at this moment in the replay data.
<p>
<ul>
<li>How are handled socket descriptors and socket ids in replay mode ?</ul>
When replaying, the sockets ids are not identical to the recorded ones, but they work as usual. The socket descriptors (displayed in logs for information purpose) are neither valid in replay mode, nor are the "CLT" or "SRV" tags.
<p>
<ul>
<li>Why does the replayed sequence halts and restarts after a short while ?</ul>
The recorder stores the number of updates between the network events. If an event occured after a moment while recording (for example in an interactive session), it will be the same when replaying it. Because it is not based on the time but on the update counter, it allows to step into the code, using a debugger.
<p>
<ul>
<li>Why does the replayed sequence does not exit at the end ?</ul>
When recording, no user input is recorded. Therefore, if you exit the program by Ctrl-C, the replayed sequence will remain running.
<p>
<!-- footer -->
<BR><FONT Size=+5> </FONT>
</TD>
<TD WIDTH=15><IMG SRC=/inc/img/pixel.gif WIDTH=15 HEIGHT=15 BORDER=0 ALT=""></TD>
</TR>
</TABLE>
</BODY>
</HTML>
|