update compat
[lttv.git] / tags / LinuxTraceToolkitViewer-0.10.0-pre-115102007 / doc / developer / developer_guide / docbook / developer_guide.docbook
CommitLineData
7cb02901 1<?xml version="1.0" encoding="UTF-8" ?>
2<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
3 "/usr/share/sgml/docbook/dtd/4.3/xdocbook.dtd">
4<!--<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" >-->
5
6<book>
7
8<bookinfo>
9<title>Linux Trace Toolkit Viewer Developer Guide</title>
10<authorgroup>
11<author>
12<firstname>Mathieu</firstname>
13<surname>Desnoyers</surname>
14</author>
15</authorgroup>
16
17<date>01/12/2004</date>
18<releaseinfo>1.00.00</releaseinfo>
19
20<abstract>
21<para>
22This document describes the basic steps necessary to develop within the
23<application>Linux Trace Toolkit Viewer</application> project.
24
25</para>
26</abstract>
27
28<keywordset>
29<keyword>Linux Trace Toolkit Viewer</keyword>
30<keyword>text</keyword>
31<keyword>module</keyword>
32<keyword>context</keyword>
33</keywordset>
34
35</bookinfo>
36<chapter>
37<title>Linux Trace Toolkit Viewer Text Module Tutorial</title>
38
39<sect1>
40<title>Introduction</title>
41<para>
42This chapter explains all the steps that are necessary to create a text module
43in LTTV.
44</para>
45</sect1>
46
47<sect1>
48<title>A typical module</title>
49<para>
50A typical module must have a init() and destroy() function. Please refer to
51lttv/modules/text/textDump.c for the detail of these functions.
52</para>
53<para>
54The init() function is called when the library is loaded and destroy()
55inversely. It adds options to the command line by calling "lttv_option_add" from
56option.h
57</para>
58<para>
59The module communicates with the main lttv program through the use of global
60attributes. Use lttv/attribute.h, lttv/iattribute.h and lttv/lttv.h, and then
61LTTV_IATTRIBUTE(lttv_global_attributes()) to get the pointer to these
62global attributes.
63</para>
64<para>
65You can then add your hooks (functions that follows the prototype of a hook, as
66defined in lttv/hook.h) in the different hook lists defined in lttv/lttv.h. Note
67that hooks have an assigned priority. This is necessary to inform the trace
68reader that a specific hook needs to be called, for example, before or after the
69state update done for an event by the state module. For that specific example, a
70hook could use the LTTV_PRIO_STATE-5 to get called before the state update and a
71second hook could use the LTTV_PRIO_STATE+5 to get called after the state
72update. This is especially important for graphical module, which is the subject
73of a the chapter named "Linux Trace Toolkit Viewer Graphical Module Tutorial".
74</para>
75<para>
76You should also take a look at lttv/state.c, where by_id hooks are used. When
77you only need some specific events, you should use this interface. It makes the
78event filtering sooner in the dispatch chain : you hook doesn't have to be
79called for each event, only the ones selected. That improves the performances a
80lot!
81</para>
82<para>
83Note that you should use the lttv_trace_find_hook method from
84lttv/tracecontext.h to connect the hook to the right facility/event type. See
85state.c for an example. A problem that may arise is that the LttvTraceHook
86structure must be passed as hook_data when registering the hook. In fact, it is
87not necessary for it to be directly passed as the hook_data parameter. As long
88as the hook function can access the LttvTraceHook fields necessary to parse the
89LttEvent, there is no problem. In a complex viewer where you need a pointer to
90your own data structure, just keep a pointer to the LttvTraceHook structure
91inside your own data structure, and give to pointer to your data structure in
92parameter as the hook_data.
93</para>
94<para>
95Then, you should use the macro LTTV_MODULE, defined in lttv/module.h. It allows
96you to specify the module name, a short and a long description, the init and
97destroy functions and the module dependencies. That permits to the module
98backend to load the right dependencies when needed.
99</para>
100<para>
101A typical text module will depend on batchAnalysis for the batch computation of a
102trace, and simply register before and after trace hooks, as weel as the most
103important one : a event hook.
104</para>
105</sect1>
106
107<sect1>
108<title>The hooks</title>
109<para>
110The before and after trace hooks only exists to be able to generate a report at
111the end of a trace computation. The effective computation is done by the event
112hooks.
113</para>
114<para>
115These hooks does particular computation on data arriving as argument, a
116call_data. The type of the call_data, when a hook is called during the trace
117read, is a traceset context. It contains all the necessary information about the
118read in progress. This is the base class from which inherits trace set
119state, and trace set/trace/tracefile state is the base classe of trace
120set/trace/tracefile statistics. All these types can be casted to another without
121problem (a TracesetState, for example, can be casted to a TracesetContext, but
122it's not true for the casting between a TraceContext and a TracesetContext, see
123the chapter "How to use the trace reading context" for details). They offer the
124input data and they give a container (the attributes of the trace set/trace/tracefile
125statistics) to write the output of this hook.
126</para>
127<para>
128The idea behind writing in the attributes container is to provide an extensible
129way of storing any type of information. For example, a specific module that adds
130statistics to a trace can store them there, and the statistic printout will
131automatically include the results produced by the specific module.
132</para>
133<para>
134Output data does not necessarily need to be stored in such a global container
135though. If we think of data of which we need to keed track during the execution,
136an event counter for example, we should create our own data structure that
137contains this counter, and pass the address of the allocated structure as the
138hook_data parameter of the hook list creation function. That way, the hook will
139be called with its hook_data as first parameter, which it can read and write. We
140can think of this structure as the data related to the function that persists
141between each call to the hook. You must make sure that you cast the hook_data to
142the type of the structure before you use it in the hook function.
143</para>
144<para>
145The detail about how to access the different fields of the reading context (the
146hook's call_data) will be discussed in the chapter "How to use the trace
147reading context".
148</para>
149</sect1>
150
151
152</chapter>
153
154
155<chapter>
156<title>How to use the Linux Trace Toolkit Viewer's Reading Context</title>
157
158<sect1>
159<title>Introduction</title>
160<para>
161This chapter describes how to use the Linux Trace Toolkit reading context, a
162data structure that is given as call data parameter of the modules'callbacks.
163</para>
164<para>
165Linux Trace Toolkit Viewer provides a backend that reads the traces. In combines
166them in tracesets. A trace is an abstaction over many tracefiles, one per CPU.
167LTTV reads the whole trace together, providing the events to modules by calling
168their pre-registered hook lists in a chronological order.
169</para>
170</sect1>
171
172<sect1>
173<title>Why an event driven trace reader ?</title>
174<para>
175The complexity of synchronizing the tracesets is then hidden to the viewer. Some
176future plans involve to be able to put many traces together in a trace set.
177Before this becomes possible, the time of each trace must be synchronized in
178some way. Some work is actually done to create a module that uses the network
179traffic shared by different computers to synchronize the time of different
180traces.
181</para>
182<para>
183In order to make each module integrate well with each other, we made the trace
184reader a simple hook caller. For each event it reads, it just calls the hook
185lists for this event. For each event, it calls the by_id specific hooks
186registered for this event and also the "main" hooks, registered for all events.
187Note that the two hook lists are merged when called so the priority of the
188hooks of each list is respected. For example, a hook of higher priority (20) in
189the main list will be called before a hook of lower priority (40) from the
190by_id specific list.
191</para>
192</sect1>
193
194<sect1>
195<title>Using the reading context</title>
196<para>
197If you have read the tutorials about writing a text and a graphic module, you
198should be fairly ready to use the information provided to your hook by the
199reading API.
200</para>
201<para>
202The data structures of the reading context are based on the gobject, a
203object-oriented library from the glib. Some evolved types that are found in the
204context also comes from the "glib" (GArray, GHashTable and so on). For detailed
205information about "gobjects" and the "glib", see the <ulink
206url="http://www.gtk.org">www.gtk.org</ulink> website. They provide a complete
207API reference about the data types they provide.
208</para>
209<para>
210The reading context is object oriented. It is described by the lttv/tracecontext.h
211header. Is can be illustrated with this UML class diagram :
212</para>
213<para>
214<screenshot>
215<mediaobject>
216<imageobject>
217<imagedata srccredit="Mathieu Desnoyers, 2004" fileref="lttv-context.png"
218format="PNG" align="center"/>
219</imageobject>
220<imageobject>
221<imagedata srccredit="Mathieu Desnoyers, 2004"
222fileref="lttv-context.eps"
223format="EPS" align="center"/>
224</imageobject>
225<!--<imagedata srccredit="Mathieu Desnoyers, 2004" fileref="lttv-numbered-6.svg"
226format="SVG" align="center" scalefit="1"/>
227</imageobject>-->
228<caption><para>Linux Trace Toolkit Viewer Reading Context Class Diagram</para></caption>
229</mediaobject>
230</screenshot>
231</para>
232<para>
233Though, for performance's sake, navigating through it is not as encapsulated as
234it could. Consider the class attributes to be all public (no get/set functions).
235Sometimes, iteration upon a specific element can be uneasy. For example, you may
236have to get the number of tracefiles in a trace from the "vt" field of the trace
237context to be able to iterate over all the tracefiles contained by the trace.
238</para>
239<para>
240To facilitate the common operations on the reading context, LTTV now provides a
241header that consists of simple macros : lttv/contextmacros.h. It gives an object
242look-and-feel to the context classes. Simple "GET" macros can be used to easily
243access the different fields are iterate over the elements (and get the total
244number of elements too).
245</para>
246</sect1>
247</chapter>
248
249<chapter>
250<title>Linux Trace Toolkit Viewer Graphical Module Tutorial</title>
251<sect1>
252<title>Introduction</title>
253<para>
254As a matter of fact, most of the things said for the text modules still hold for
255the graphical modules. However, the fact that every module must instanciate
256objects (called viewers) more than once changes a little bit the scenario. It is
257then impossible to use static structures : everything must be instanciated at
258run-time, except the structures related to the module itself.
259</para>
260</sect1>
261<sect1>
262<title>The static part of a module</title>
263<para>
264A module must have a static part to be able to get loaded just like a text
265module. Now, let's see the differences. The graphical module depends on the
266"lttvwindow" module. See module.c from the control flow viewer for an example.
267</para>
268<para>
269The init() and destroy() functions must register functions that can be called by
270user interaction to instanciate the viewers. That's the goal of
271lttvwindow_register_constructor() and lttvwindow_unregister_constructor() :
272they register a function with a menu entry and an icon. The main window will
273shown them in its interface and call the function when the button or menu item
274is selected. This hook function must receive a pointer to a "Tab" object in
275parameter.
276</para>
277<para>
278Also note the presence of the destroy_walk() method. It is called when the
279module is unloaded : it must destroy all the instances of the viewers from the
280module.
281</para>
282</sect1>
283<sect1>
284<title>The dynamic part of a module : the viewer</title>
285<para>
286The dynamic part starts with the constructor of the viewer. It is called by the
287main window when the corresponding button or menu item is selected. See
288h_guicontrolflow() from control flow viewer eventhooks.c for an example. It does
289basic connexion to the tab's events available : time window change notification,
290current time notification, redraw notification, continue notification. All these
291function should be implemented in your viewer if you want the data you shown to
292be synchronised with the main window and the other viewers. It also calls the
293background computation, which will be discussed in the next section.
294</para>
295<para>
296This is also at this point that the viewer does create it's own memory footprint
297: its inner structure. This structure will have to be passed as hook_data to
298each function registered by the viewer : this is what makes the functions
299"belong" to this instance of the viewer.
300</para>
301</sect1>
302<sect1>
303<title>How to request background computation</title>
304<para>
305You will also notice the presence of a request_background_data() called in the
306constructor. This function, in eventhooks.c, does verify for the presence of the
307state information that could be precomputed by the main window background
308computation. If it has not been precomputed, we ask for a computation and show
309partial data. We also register a hook that will be called (notified) by the main
310window when the requested data will become ready, so the viewer can update
311itself with the new data. If no partial information would have made sense in a
312particular viewer, one could choose to shown a "waiting for computation" message
313while waiting for the notification. See lttvwindow/lttvwindowtraces.h for the API
314of the background requests.
315</para>
316</sect1>
317
318<sect1>
319<title>How to handle events and use the graphical trace reading service</title>
320<para>
321The events that are delivered by the main window are defined in
322lttvwindow/lttvwindow.h. Let's describe them and their use in details. Remember
323that you can refer to the control flow viewer module as an example.
324</para>
325
326<sect2>
327<title>Module Related API</title>
328<para>
329A viewer plugin is, before anything, a plugin. As a dynamically loadable
330module, it thus has an init and a destroy function called whenever it is
331loaded/initialized and unloaded/destroyed. A graphical module depends on
332lttvwindow for construction of its viewer instances. In order to achieve
333this, it must register its constructor function to the main window along
334with button description or text menu entry description. A module keeps
335a list of every viewer that currently sits in memory so it can destroy
336them before the module gets unloaded/destroyed.
337</para>
338<para>
339The contructor registration to the main windows adds button and menu
340entry to each main window, thus allowing instanciation of viewers.
341</para>
342</sect2>
343<sect2>
344<title>Main Window</title>
345<para>
346The main window is a container that offers menus, buttons and a
347notebook. Some of those menus and buttons are part of the core of the
348main window, others are dynamically added and removed when modules are
349loaded/unloaded.
350</para>
351<para>
352The notebook contains as much tabs as wanted. Each tab is linked with
353a set of traces (traceset). Each trace contains many tracefiles (one
354per cpu). A trace corresponds to a kernel being traced. A traceset
355corresponds to many traces read together. The time span of a traceset
356goes from the earliest start of all the traces to the latest end of all
357the traces.
358</para>
359<para>
360Inside each tab are added the viewers. When they interact with the main
361window through the lttvwindow API, they affect the other viewers located
362in the same tab as they are.
363</para>
364<para>
365The insertion of many viewers in a tab permits a quick look at all the
366information wanted in a glance. The main window does merge the read
367requests from all the viewers in the same tab in a way that every viewer
368will get exactly the events it asked for, while the event reading loop
369and state update are shared. It improves performance of events delivery
370to the viewers.
371</para>
372</sect2>
373
374<sect2>
375<title>Viewer Instance Related API</title>
376<para>
377The lifetime of a viewer is as follows. The viewer constructor function
378is called each time an instance view is created (one subwindow of this
379viewer type is created by the user either by clicking on the menu item
380or the button corresponding to the viewer). Thereafter, the viewer gets
381hooks called for different purposes by the window containing it. These
382hooks are detailed below. It also has to deal with GTK Events. Finally,
383it can be destructed by having its top level widget unreferenced by the
384main window or by any GTK Event causing a "destroy-event" signal on the
385its top widget. Another possible way for it do be destroyed is if the
386module gets unloaded. The module unload function will have to emit a
387"destroy" signal on each top level widget of all instances of its viewers.
388</para>
389</sect2>
390<sect2>
391<title>Notices from Main Window</title>
392<variablelist>
393<varlistentry>
394<term>time_window</term>
395<listitem>
396<simpara>This is the time interval visible on the viewer's tab. Every
397 viewer that cares about being synchronised by respect to the
398 time with other viewers should register to this notification.
399 They should redraw all or part of their display when this
400 occurs.</simpara>
401</listitem>
402</varlistentry>
403<varlistentry>
404<term>traceset</term>
405<listitem>
406<simpara>This notification is called whenever a trace is added/removed
407 from the traceset. As it affects all the data displayed by the
408 viewer, it sould redraw itself totally.</simpara>
409</listitem>
410</varlistentry>
411
412<varlistentry>
413<term>filter</term>
414<listitem>
415<simpara>This feature has not been implemented yet.</simpara>
416</listitem>
417</varlistentry>
418
419<varlistentry>
420<term>current_time</term>
421<listitem>
422<simpara>Being able to zoom nearer a specific time or highlight a specific
423 time on every viewer in synchronicity implies that the viewer
424 has to shown a visual sign over the drawing or select an event
425 when it receives this notice. It should also inform the main
426 window with the appropriate report API function when a user
427 selects a specific time as being the current time.</simpara>
428</listitem>
429</varlistentry>
430
431<varlistentry>
432<term>dividor</term>
433<listitem>
434<simpara>This notice links the positions of the horizontal dividors
435 between the graphic display zone of every viewer and their Y axis,
436 typically showing processes, cpus, ...</simpara>
437</listitem>
438</varlistentry>
439</variablelist>
440</sect2>
441<sect2>
442<title>Reporting Changes to the Main Window</title>
443<para>
444In most cases, the enclosing window knows about updates such as described
445in the Notification section higher. There are a few cases, however, where
446updates are caused by actions known by a view instance. For example,
447clicking in a view may update the current time; all viewers within
448the same window must be told about the new current time to change the
449currently highlighted time point. A viewer reports such events by calling
450lttvwindow_report_current_time on its lttvwindow. The lttvwindow will
451consequently call current_time_notify for each of its contained viewers.
452</para>
453<para>
454Available report methods are :
455<itemizedlist>
456<listitem>
457<simpara>
458lttvwindow_report_time_window : reports the new time window.
459</simpara>
460</listitem>
461<listitem>
462<simpara>
463lttvwindow_report_current_time : reports the new current time.
464</simpara>
465</listitem>
466<listitem>
467<simpara>
468lttvwindow_report_dividor : reports the new horizontal dividor's position.
469</simpara>
470</listitem>
471</itemizedlist>
472</para>
473</sect2>
474
475<sect2>
476<title>Requesting Events to Main Window</title>
477<para>
478Events can be requested by passing a EventsRequest structure to the main
479window. They will be delivered later when the next g_idle functions
480will be called. Event delivery is done by calling the event hook for
481this event ID, or the main event hooks. A pointer to the EventsRequest
482structure is passed as hook_data to the event hooks of the viewers.
483</para>
484<para>
485EventsRequest consists in
486<itemizedlist>
487<listitem>
488<simpara>
489a pointer to the viewer specific data structure
490</simpara>
491</listitem>
492<listitem>
493<simpara>
494a start timestamp or position
495</simpara>
496</listitem>
497<listitem>
498<simpara>
499a stop_flag, ending the read process when set to TRUE
500</simpara>
501</listitem>
502<listitem>
503<simpara>
504a end timestamp and/or position and/or number of events to read
505</simpara>
506</listitem>
507<listitem>
508<simpara>
509hook lists to call for traceset/trace/tracefile begin and end, and for each
510 event (event hooks and event_by_id hooks).
511</simpara>
512</listitem>
513</itemizedlist>
514</para>
515<para>
516The main window will deliver events for every EventRequests it has
517pending through an algorithm that guarantee that all events requested,
518and only them, will be delivered to the viewer between the call of the
519tracefile_begin hooks and the call of the tracefile_end hooks.
520</para>
521<para>
522If a viewer wants to stop the event request at a certain point inside the
523event hooks, it has to set the stop_flag to TRUE and return TRUE from the
524hook function. Then return value will stop the process traceset. Then,
525the main window will look for the stop_flag and remove the EventRequests
526from its lists, calling the process_traceset_end for this request (it
527removes hooks from the context and calls the after hooks).
528</para>
529<para>
530It no stop_flag is risen, the end timestamp, end position or number
531of events to read has to be reached to determine the end of the
532request. Otherwise, the end of traceset does determine it.
533</para>
534</sect2>
535<sect2>
536<title>GTK Events</title>
537<sect3>
538<title>Events and Signals</title>
539<para>
540GTK is quite different from the other graphical toolkits around
541there. The main difference resides in that there are many X Windows
542inside one GtkWindow, instead of just one. That means that X events are
543delivered by the glib main loop directly to the widget corresponding to
544the GdkWindow affected by the X event.
545</para>
546<para>
547Event delivery to a widget emits a signal on that widget. Then, if a
548handler is connected to this widget's signal, it will be executed. There
549are default handlers for signals, connected at class instantiation
550time. There is also the possibility to connect other handlers to these
551signals, which is what should be done in most cases when a viewer needs
552to interact with X in any way.
553</para>
554
555<para>
556Signal emission and propagation is described there :
557
558<itemizedlist>
559<listitem>
560<simpara>
561http://www.gtk.org/tutorial/sec-signalemissionandpropagation.html
562</simpara>
563</listitem>
564</itemizedlist>
565</para>
566
567<para>
568For further information on the GTK main loop (now a wrapper over glib main loop)
569see :
570
571<itemizedlist>
572<listitem>
573<simpara>
574http://developer.gnome.org/doc/API/2.0/gtk/gtk-General.html
575</simpara>
576</listitem>
577<listitem>
578<simpara>
579http://developer.gnome.org/doc/API/2.0/glib/glib-The-Main-Event-Loop.html
580</simpara>
581</listitem>
582</itemizedlist>
583</para>
584
585
586<para>
587For documentation on event handling in GTK/GDK, see :
588
589<itemizedlist>
590<listitem>
591<simpara>
592http://developer.gnome.org/doc/API/2.0/gdk/gdk-Events.html
593</simpara>
594</listitem>
595<listitem>
596<simpara>
597http://developer.gnome.org/doc/API/2.0/gdk/gdk-Event-Structures.html
598</simpara>
599</listitem>
600</itemizedlist>
601</para>
602
603
604<para>
605Signals can be connected to handlers, emitted, propagated, blocked,
606stopped. See :
607
608<itemizedlist>
609<listitem>
610<simpara>
611http://developer.gnome.org/doc/API/2.0/gobject/gobject-Signals.html
612</simpara>
613</listitem>
614</itemizedlist>
615</para>
616
617</sect3>
618
619
620<sect3>
621<title>The "expose_event"</title>
622<para>
623Provides the exposed region in the GdkEventExpose structure.
624</para>
625<para>
626There are two ways of dealing with exposures. The first one is to directly
627draw on the screen and the second one is to draw in a pixmap buffer,
628and then to update the screen when necessary.
629</para>
630<para>
631In the first case, the expose event will be responsible for registering
632hooks to process_traceset and require time intervals to the main
633window. So, in this scenario, if a part of the screen is damaged, the
634trace has to be read to redraw the screen.
635</para>
636<para>
637In the second case, with a pixmap buffer, the expose handler is only
638responsible of showing the pixmap buffer on the screen. If the pixmap
639buffer has never been filled with a drawing, the expose handler may ask
640for it to be filled.
641</para>
642<para>
643The interest of using events request to the main window instead of reading
644the events directly from the trace comes from the fact that the main
645window does merge requests from the different viewers in the same tab so
646that the read loop and the state update is shared. As viewers will, in
647the common scenario, request the same events, only one pass through the
648trace that will call the right hooks for the right intervals will be done.
649</para>
650<para>
651When the traceset read is over for a events request, the traceset_end
652hook is called. It has the responsibility of finishing the drawing if
653some parts still need to be drawn and to show it on the screen (if the
654viewer uses a pixmap buffer).
655</para>
656<para>
657It can add dotted lines and such visual effects to enhance the user's
658experience.
659</para>
660</sect3>
661</sect2>
662</sect1>
663
664</chapter>
665
666
667
668</book>
This page took 0.070619 seconds and 4 git commands to generate.