Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
O
OpenXG UE
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Michael Black
OpenXG UE
Commits
ced1e30b
Commit
ced1e30b
authored
May 04, 2016
by
Cedric Roux
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
put textlog.[ch] in logger/ and rename remote.c to textlog.c
parent
a68ee890
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
406 additions
and
389 deletions
+406
-389
common/utils/T/tracer/Makefile.remote
common/utils/T/tracer/Makefile.remote
+9
-5
common/utils/T/tracer/logger/Makefile
common/utils/T/tracer/logger/Makefile
+13
-0
common/utils/T/tracer/logger/textlog.c
common/utils/T/tracer/logger/textlog.c
+189
-0
common/utils/T/tracer/logger/textlog.h
common/utils/T/tracer/logger/textlog.h
+0
-0
common/utils/T/tracer/remote.c
common/utils/T/tracer/remote.c
+0
-220
common/utils/T/tracer/textlog.c
common/utils/T/tracer/textlog.c
+195
-164
No files found.
common/utils/T/tracer/Makefile.remote
View file @
ced1e30b
...
...
@@ -11,17 +11,20 @@ OBJS=remote_old.o plot.o database.o gui.o utils.o
$(PROG)
:
gui/gui.a $(OBJS)
$(CC)
$(CFLAGS)
-o
$(PROG)
$(OBJS)
gui/gui.a
$(LIBS)
textlog
:
utils.o
remote.o database.o event.o handler.o textlog
.o
\
event_selector.o view/view.a gui/gui.a
textlog
:
utils.o
textlog.o database.o event.o handler
.o
\
event_selector.o view/view.a gui/gui.a
logger/logger.a
$(CC)
$(CFLAGS)
-o
textlog
$^
$(LIBS)
.PHONY
:
gui/gui.a view/view.a
.PHONY
:
gui/gui.a view/view.a logger/logger.a
gui/gui.a
:
cd
gui
&&
make
view/view.a
:
cd
view
&&
make
gui/gui
.a
:
cd
gui
&&
make
logger/logger
.a
:
cd
logger
&&
make
%.o
:
%.c
$(CC)
$(CFLAGS)
-c
-o
$@
$<
...
...
@@ -30,3 +33,4 @@ clean:
rm
-f
*
.o
$(PROG)
core textlog
cd
gui
&&
make clean
cd
view
&&
make clean
cd
logger
&&
make clean
common/utils/T/tracer/logger/Makefile
0 → 100644
View file @
ced1e30b
CC
=
gcc
CFLAGS
=
-Wall
-g
-pthread
-I
..
OBJS
=
textlog.o
logger.a
:
$(OBJS)
ar cr logger.a
$(OBJS)
%.o
:
%.c
$(CC)
$(CFLAGS)
-o
$@
-c
$<
clean
:
rm
-f
*
.a
*
.o
common/utils/T/tracer/logger/textlog.c
0 → 100644
View file @
ced1e30b
#include "textlog.h"
#include "handler.h"
#include "database.h"
#include "view/view.h"
#include "utils.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
enum
format_item_type
{
INSTRING
,
INT
,
STRING
,
BUFFER
};
struct
format_item
{
enum
format_item_type
type
;
union
{
/* INSTRING */
char
*
s
;
/* others */
int
event_arg
;
};
};
struct
textlog
{
char
*
event_name
;
char
*
format
;
void
*
database
;
unsigned
long
handler_id
;
/* parsed format string */
struct
format_item
*
f
;
int
fsize
;
/* list of views */
view
**
v
;
int
vsize
;
/* local output buffer */
OBUF
o
;
};
static
void
_event
(
void
*
p
,
event
e
)
{
struct
textlog
*
l
=
p
;
int
i
;
l
->
o
.
osize
=
0
;
for
(
i
=
0
;
i
<
l
->
fsize
;
i
++
)
switch
(
l
->
f
[
i
].
type
)
{
case
INSTRING
:
PUTS
(
&
l
->
o
,
l
->
f
[
i
].
s
);
break
;
case
INT
:
PUTI
(
&
l
->
o
,
e
.
e
[
l
->
f
[
i
].
event_arg
].
i
);
break
;
case
STRING
:
PUTS_CLEAN
(
&
l
->
o
,
e
.
e
[
l
->
f
[
i
].
event_arg
].
s
);
break
;
case
BUFFER
:
PUTS
(
&
l
->
o
,
"{buffer size:"
);
PUTI
(
&
l
->
o
,
e
.
e
[
l
->
f
[
i
].
event_arg
].
bsize
);
PUTS
(
&
l
->
o
,
"}"
);
break
;
}
PUTC
(
&
l
->
o
,
0
);
for
(
i
=
0
;
i
<
l
->
vsize
;
i
++
)
l
->
v
[
i
]
->
append
(
l
->
v
[
i
],
l
->
o
.
obuf
);
}
enum
chunk_type
{
C_ERROR
,
C_STRING
,
C_ARG_NAME
,
C_EVENT_NAME
};
struct
chunk
{
enum
chunk_type
type
;
char
*
s
;
enum
format_item_type
it
;
int
event_arg
;
};
/* TODO: speed it up? */
static
int
find_argument
(
char
*
name
,
database_event_format
f
,
enum
format_item_type
*
it
,
int
*
event_arg
)
{
int
i
;
for
(
i
=
0
;
i
<
f
.
count
;
i
++
)
if
(
!
strcmp
(
name
,
f
.
name
[
i
]))
break
;
if
(
i
==
f
.
count
)
return
0
;
*
event_arg
=
i
;
if
(
!
strcmp
(
f
.
type
[
i
],
"int"
))
*
it
=
INT
;
else
if
(
!
strcmp
(
f
.
type
[
i
],
"string"
))
*
it
=
STRING
;
else
if
(
!
strcmp
(
f
.
type
[
i
],
"buffer"
))
*
it
=
BUFFER
;
else
return
0
;
return
1
;
}
static
struct
chunk
next_chunk
(
char
**
s
,
database_event_format
f
)
{
char
*
cur
=
*
s
;
char
*
name
;
enum
format_item_type
it
;
int
event_arg
;
/* argument in [ ] */
if
(
*
cur
==
'['
)
{
*
cur
=
0
;
cur
++
;
name
=
cur
;
/* no \ allowed there */
while
(
*
cur
&&
*
cur
!=
']'
&&
*
cur
!=
'\\'
)
cur
++
;
if
(
*
cur
!=
']'
)
goto
error
;
*
cur
=
0
;
cur
++
;
*
s
=
cur
;
if
(
find_argument
(
name
,
f
,
&
it
,
&
event_arg
)
==
0
)
goto
error
;
return
(
struct
chunk
){
type
:
C_ARG_NAME
,
s
:
name
,
it
:
it
,
event_arg
:
event_arg
};
}
/* { } is name of event (anything in between is smashed) */
if
(
*
cur
==
'{'
)
{
*
cur
=
0
;
cur
++
;
while
(
*
cur
&&
*
cur
!=
'}'
)
cur
++
;
if
(
*
cur
!=
'}'
)
goto
error
;
*
cur
=
0
;
cur
++
;
*
s
=
cur
;
return
(
struct
chunk
){
type
:
C_EVENT_NAME
};
}
/* anything but [ and { is raw string */
/* TODO: deal with \ */
name
=
cur
;
while
(
*
cur
&&
*
cur
!=
'['
&&
*
cur
!=
'{'
)
cur
++
;
*
s
=
cur
;
return
(
struct
chunk
){
type
:
C_STRING
,
s
:
name
};
error:
return
(
struct
chunk
){
type
:
C_ERROR
};
}
textlog
*
new_textlog
(
event_handler
*
h
,
void
*
database
,
char
*
event_name
,
char
*
format
)
{
struct
textlog
*
ret
;
int
event_id
;
database_event_format
f
;
char
*
cur
;
ret
=
calloc
(
1
,
sizeof
(
struct
textlog
));
if
(
ret
==
NULL
)
abort
();
ret
->
event_name
=
strdup
(
event_name
);
if
(
ret
->
event_name
==
NULL
)
abort
();
ret
->
format
=
strdup
(
format
);
if
(
ret
->
format
==
NULL
)
abort
();
ret
->
database
=
database
;
event_id
=
event_id_from_name
(
database
,
event_name
);
ret
->
handler_id
=
register_handler_function
(
h
,
event_id
,
_event
,
ret
);
f
=
get_format
(
database
,
event_id
);
/* we won't get more than strlen(format) "chunks" */
ret
->
f
=
malloc
(
sizeof
(
struct
format_item
)
*
strlen
(
format
));
if
(
ret
->
f
==
NULL
)
abort
();
cur
=
ret
->
format
;
while
(
*
cur
)
{
struct
chunk
c
=
next_chunk
(
&
cur
,
f
);
switch
(
c
.
type
)
{
case
C_ERROR
:
goto
error
;
case
C_STRING
:
ret
->
f
[
ret
->
fsize
].
type
=
INSTRING
;
ret
->
f
[
ret
->
fsize
].
s
=
c
.
s
;
break
;
case
C_ARG_NAME
:
ret
->
f
[
ret
->
fsize
].
type
=
c
.
it
;
ret
->
f
[
ret
->
fsize
].
event_arg
=
c
.
event_arg
;
break
;
case
C_EVENT_NAME
:
ret
->
f
[
ret
->
fsize
].
type
=
INSTRING
;
ret
->
f
[
ret
->
fsize
].
s
=
ret
->
event_name
;
break
;
}
ret
->
fsize
++
;
}
return
ret
;
error:
printf
(
"%s:%d: bad format '%s'
\n
"
,
__FILE__
,
__LINE__
,
format
);
abort
();
}
void
textlog_add_view
(
textlog
*
_l
,
view
*
v
)
{
struct
textlog
*
l
=
_l
;
l
->
vsize
++
;
l
->
v
=
realloc
(
l
->
v
,
l
->
vsize
*
sizeof
(
view
*
));
if
(
l
->
v
==
NULL
)
abort
();
l
->
v
[
l
->
vsize
-
1
]
=
v
;
}
common/utils/T/tracer/textlog.h
→
common/utils/T/tracer/
logger/
textlog.h
View file @
ced1e30b
File moved
common/utils/T/tracer/remote.c
deleted
100644 → 0
View file @
a68ee890
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include "database.h"
#include "event.h"
#include "handler.h"
#include "textlog.h"
#include "view/view.h"
#include "gui/gui.h"
#include "utils.h"
#include "../T_defs.h"
#include "event_selector.h"
#define DEFAULT_REMOTE_PORT 2021
int
get_connection
(
char
*
addr
,
int
port
)
{
struct
sockaddr_in
a
;
socklen_t
alen
;
int
s
,
t
;
printf
(
"waiting for connection on %s:%d
\n
"
,
addr
,
port
);
s
=
socket
(
AF_INET
,
SOCK_STREAM
,
0
);
if
(
s
==
-
1
)
{
perror
(
"socket"
);
exit
(
1
);
}
t
=
1
;
if
(
setsockopt
(
s
,
SOL_SOCKET
,
SO_REUSEADDR
,
&
t
,
sizeof
(
int
)))
{
perror
(
"setsockopt"
);
exit
(
1
);
}
a
.
sin_family
=
AF_INET
;
a
.
sin_port
=
htons
(
port
);
a
.
sin_addr
.
s_addr
=
inet_addr
(
addr
);
if
(
bind
(
s
,
(
struct
sockaddr
*
)
&
a
,
sizeof
(
a
)))
{
perror
(
"bind"
);
exit
(
1
);
}
if
(
listen
(
s
,
5
))
{
perror
(
"bind"
);
exit
(
1
);
}
alen
=
sizeof
(
a
);
t
=
accept
(
s
,
(
struct
sockaddr
*
)
&
a
,
&
alen
);
if
(
t
==
-
1
)
{
perror
(
"accept"
);
exit
(
1
);
}
close
(
s
);
printf
(
"connected
\n
"
);
return
t
;
}
void
usage
(
void
)
{
printf
(
"options:
\n
"
" -d <database file> this option is mandatory
\n
"
" -on <GROUP or ID> turn log ON for given GROUP or ID
\n
"
" -off <GROUP or ID> turn log OFF for given GROUP or ID
\n
"
" -ON turn all logs ON
\n
"
" -OFF turn all logs OFF
\n
"
" note: you may pass several -on/-off/-ON/-OFF,
\n
"
" they will be processed in order
\n
"
" by default, all is off
\n
"
" -p <port> use given port (default %d)
\n
"
" -x GUI output
\n
"
" -debug-gui activate GUI debug logs
\n
"
" -no-gui disable GUI entirely
\n
"
,
DEFAULT_REMOTE_PORT
);
exit
(
1
);
}
int
fullread
(
int
fd
,
void
*
_buf
,
int
count
)
{
char
*
buf
=
_buf
;
int
ret
=
0
;
int
l
;
while
(
count
)
{
l
=
read
(
fd
,
buf
,
count
);
if
(
l
<=
0
)
{
printf
(
"read socket problem
\n
"
);
abort
();
}
count
-=
l
;
buf
+=
l
;
ret
+=
l
;
}
return
ret
;
}
event
get_event
(
int
s
,
char
*
v
,
void
*
d
)
{
int
type
;
int32_t
length
;
fullread
(
s
,
&
length
,
4
);
fullread
(
s
,
&
type
,
sizeof
(
int
));
length
-=
sizeof
(
int
);
fullread
(
s
,
v
,
length
);
return
new_event
(
type
,
length
,
v
,
d
);
}
static
void
*
gui_thread
(
void
*
_g
)
{
gui
*
g
=
_g
;
gui_loop
(
g
);
return
NULL
;
}
int
main
(
int
n
,
char
**
v
)
{
extern
int
volatile
gui_logd
;
char
*
database_filename
=
NULL
;
void
*
database
;
int
port
=
DEFAULT_REMOTE_PORT
;
char
**
on_off_name
;
int
*
on_off_action
;
int
on_off_n
=
0
;
int
*
is_on
;
int
number_of_events
;
int
s
;
int
i
;
char
t
;
int
l
;
event_handler
*
h
;
textlog
*
textlog
;
gui
*
g
;
int
gui_mode
=
0
;
view
*
out
;
int
gui_active
=
1
;
on_off_name
=
malloc
(
n
*
sizeof
(
char
*
));
if
(
on_off_name
==
NULL
)
abort
();
on_off_action
=
malloc
(
n
*
sizeof
(
int
));
if
(
on_off_action
==
NULL
)
abort
();
for
(
i
=
1
;
i
<
n
;
i
++
)
{
if
(
!
strcmp
(
v
[
i
],
"-h"
)
||
!
strcmp
(
v
[
i
],
"--help"
))
usage
();
if
(
!
strcmp
(
v
[
i
],
"-d"
))
{
if
(
i
>
n
-
2
)
usage
();
database_filename
=
v
[
++
i
];
continue
;
}
if
(
!
strcmp
(
v
[
i
],
"-p"
))
{
if
(
i
>
n
-
2
)
usage
();
port
=
atoi
(
v
[
++
i
]);
continue
;
}
if
(
!
strcmp
(
v
[
i
],
"-on"
))
{
if
(
i
>
n
-
2
)
usage
();
on_off_name
[
on_off_n
]
=
v
[
++
i
];
on_off_action
[
on_off_n
++
]
=
1
;
continue
;
}
if
(
!
strcmp
(
v
[
i
],
"-off"
))
{
if
(
i
>
n
-
2
)
usage
();
on_off_name
[
on_off_n
]
=
v
[
++
i
];
on_off_action
[
on_off_n
++
]
=
0
;
continue
;
}
if
(
!
strcmp
(
v
[
i
],
"-ON"
))
{
on_off_name
[
on_off_n
]
=
NULL
;
on_off_action
[
on_off_n
++
]
=
1
;
continue
;
}
if
(
!
strcmp
(
v
[
i
],
"-OFF"
))
{
on_off_name
[
on_off_n
]
=
NULL
;
on_off_action
[
on_off_n
++
]
=
0
;
continue
;
}
if
(
!
strcmp
(
v
[
i
],
"-x"
))
{
gui_mode
=
1
;
continue
;
}
if
(
!
strcmp
(
v
[
i
],
"-debug-gui"
))
{
gui_logd
=
1
;
continue
;
}
if
(
!
strcmp
(
v
[
i
],
"-no-gui"
))
{
gui_active
=
0
;
continue
;
}
usage
();
}
if
(
gui_active
==
0
)
gui_mode
=
0
;
if
(
database_filename
==
NULL
)
{
printf
(
"ERROR: provide a database file (-d)
\n
"
);
exit
(
1
);
}
database
=
parse_database
(
database_filename
);
number_of_events
=
number_of_ids
(
database
);
is_on
=
calloc
(
number_of_events
,
sizeof
(
int
));
if
(
is_on
==
NULL
)
abort
();
h
=
new_handler
(
database
);
if
(
gui_active
)
{
g
=
gui_init
();
new_thread
(
gui_thread
,
g
);
}
if
(
gui_mode
)
{
widget
*
w
,
*
win
;
// w = new_textlist(g, 600, 20, 0);
w
=
new_textlist
(
g
,
800
,
50
,
BACKGROUND_COLOR
);
win
=
new_toplevel_window
(
g
,
800
,
50
*
12
,
"textlog"
);
widget_add_child
(
g
,
win
,
w
,
-
1
);
out
=
new_view_textlist
(
1000
,
10
,
g
,
w
);
//tout = new_view_textlist(7, 4, g, w);
}
else
{
out
=
new_view_stdout
();
}
for
(
i
=
0
;
i
<
number_of_events
;
i
++
)
{
char
*
name
,
*
desc
;
database_get_generic_description
(
database
,
i
,
&
name
,
&
desc
);
textlog
=
new_textlog
(
h
,
database
,
name
,
desc
);
// "ENB_UL_CHANNEL_ESTIMATE",
// "ev: {} eNB_id [eNB_ID] frame [frame] subframe [subframe]");
textlog_add_view
(
textlog
,
out
);
free
(
name
);
free
(
desc
);
}
for
(
i
=
0
;
i
<
on_off_n
;
i
++
)
on_off
(
database
,
on_off_name
[
i
],
is_on
,
on_off_action
[
i
]);
s
=
get_connection
(
"0.0.0.0"
,
port
);
/* send the first message - activate selected traces */
t
=
0
;
if
(
write
(
s
,
&
t
,
1
)
!=
1
)
abort
();
l
=
0
;
for
(
i
=
0
;
i
<
number_of_events
;
i
++
)
if
(
is_on
[
i
])
l
++
;
if
(
write
(
s
,
&
l
,
sizeof
(
int
))
!=
sizeof
(
int
))
abort
();
for
(
l
=
0
;
l
<
number_of_events
;
l
++
)
if
(
is_on
[
l
])
if
(
write
(
s
,
&
l
,
sizeof
(
int
))
!=
sizeof
(
int
))
abort
();
if
(
gui_active
)
setup_event_selector
(
g
,
database
,
s
,
is_on
);
/* read messages */
while
(
1
)
{
char
v
[
T_BUFFER_MAX
];
event
e
;
e
=
get_event
(
s
,
v
,
database
);
handle_event
(
h
,
e
);
}
return
0
;
}
common/utils/T/tracer/textlog.c
View file @
ced1e30b
#include "textlog.h"
#include "handler.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include "database.h"
#include "event.h"
#include "handler.h"
#include "logger/textlog.h"
#include "view/view.h"
#include "gui/gui.h"
#include "utils.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "../T_defs.h"
#include "event_selector.h"
enum
format_item_type
{
INSTRING
,
INT
,
STRING
,
BUFFER
};
struct
format_item
{
enum
format_item_type
type
;
union
{
/* INSTRING */
char
*
s
;
/* others */
int
event_arg
;
};
};
struct
textlog
{
char
*
event_name
;
char
*
format
;
void
*
database
;
unsigned
long
handler_id
;
/* parsed format string */
struct
format_item
*
f
;
int
fsize
;
/* list of views */
view
**
v
;
int
vsize
;
/* local output buffer */
OBUF
o
;
};
static
void
_event
(
void
*
p
,
event
e
)
#define DEFAULT_REMOTE_PORT 2021
int
get_connection
(
char
*
addr
,
int
port
)
{
struct
textlog
*
l
=
p
;
int
i
;
struct
sockaddr_in
a
;
socklen_t
alen
;
int
s
,
t
;
l
->
o
.
osize
=
0
;
for
(
i
=
0
;
i
<
l
->
fsize
;
i
++
)
switch
(
l
->
f
[
i
].
type
)
{
case
INSTRING
:
PUTS
(
&
l
->
o
,
l
->
f
[
i
].
s
);
break
;
case
INT
:
PUTI
(
&
l
->
o
,
e
.
e
[
l
->
f
[
i
].
event_arg
].
i
);
break
;
case
STRING
:
PUTS_CLEAN
(
&
l
->
o
,
e
.
e
[
l
->
f
[
i
].
event_arg
].
s
);
break
;
case
BUFFER
:
PUTS
(
&
l
->
o
,
"{buffer size:"
);
PUTI
(
&
l
->
o
,
e
.
e
[
l
->
f
[
i
].
event_arg
].
bsize
);
PUTS
(
&
l
->
o
,
"}"
);
break
;
}
PUTC
(
&
l
->
o
,
0
);
printf
(
"waiting for connection on %s:%d
\n
"
,
addr
,
port
);
s
=
socket
(
AF_INET
,
SOCK_STREAM
,
0
);
if
(
s
==
-
1
)
{
perror
(
"socket"
);
exit
(
1
);
}
t
=
1
;
if
(
setsockopt
(
s
,
SOL_SOCKET
,
SO_REUSEADDR
,
&
t
,
sizeof
(
int
)))
{
perror
(
"setsockopt"
);
exit
(
1
);
}
a
.
sin_family
=
AF_INET
;
a
.
sin_port
=
htons
(
port
);
a
.
sin_addr
.
s_addr
=
inet_addr
(
addr
);
if
(
bind
(
s
,
(
struct
sockaddr
*
)
&
a
,
sizeof
(
a
)))
{
perror
(
"bind"
);
exit
(
1
);
}
if
(
listen
(
s
,
5
))
{
perror
(
"bind"
);
exit
(
1
);
}
alen
=
sizeof
(
a
);
t
=
accept
(
s
,
(
struct
sockaddr
*
)
&
a
,
&
alen
);
if
(
t
==
-
1
)
{
perror
(
"accept"
);
exit
(
1
);
}
close
(
s
);
printf
(
"connected
\n
"
);
for
(
i
=
0
;
i
<
l
->
vsize
;
i
++
)
l
->
v
[
i
]
->
append
(
l
->
v
[
i
],
l
->
o
.
obuf
)
;
return
t
;
}
enum
chunk_type
{
C_ERROR
,
C_STRING
,
C_ARG_NAME
,
C_EVENT_NAME
};
struct
chunk
{
enum
chunk_type
type
;
char
*
s
;
enum
format_item_type
it
;
int
event_arg
;
};
/* TODO: speed it up? */
static
int
find_argument
(
char
*
name
,
database_event_format
f
,
enum
format_item_type
*
it
,
int
*
event_arg
)
void
usage
(
void
)
{
int
i
;
for
(
i
=
0
;
i
<
f
.
count
;
i
++
)
if
(
!
strcmp
(
name
,
f
.
name
[
i
]))
break
;
if
(
i
==
f
.
count
)
return
0
;
*
event_arg
=
i
;
if
(
!
strcmp
(
f
.
type
[
i
],
"int"
))
*
it
=
INT
;
else
if
(
!
strcmp
(
f
.
type
[
i
],
"string"
))
*
it
=
STRING
;
else
if
(
!
strcmp
(
f
.
type
[
i
],
"buffer"
))
*
it
=
BUFFER
;
else
return
0
;
return
1
;
printf
(
"options:
\n
"
" -d <database file> this option is mandatory
\n
"
" -on <GROUP or ID> turn log ON for given GROUP or ID
\n
"
" -off <GROUP or ID> turn log OFF for given GROUP or ID
\n
"
" -ON turn all logs ON
\n
"
" -OFF turn all logs OFF
\n
"
" note: you may pass several -on/-off/-ON/-OFF,
\n
"
" they will be processed in order
\n
"
" by default, all is off
\n
"
" -p <port> use given port (default %d)
\n
"
" -x GUI output
\n
"
" -debug-gui activate GUI debug logs
\n
"
" -no-gui disable GUI entirely
\n
"
,
DEFAULT_REMOTE_PORT
);
exit
(
1
);
}
static
struct
chunk
next_chunk
(
char
**
s
,
database_event_format
f
)
int
fullread
(
int
fd
,
void
*
_buf
,
int
count
)
{
char
*
cur
=
*
s
;
char
*
name
;
enum
format_item_type
it
;
int
event_arg
;
/* argument in [ ] */
if
(
*
cur
==
'['
)
{
*
cur
=
0
;
cur
++
;
name
=
cur
;
/* no \ allowed there */
while
(
*
cur
&&
*
cur
!=
']'
&&
*
cur
!=
'\\'
)
cur
++
;
if
(
*
cur
!=
']'
)
goto
error
;
*
cur
=
0
;
cur
++
;
*
s
=
cur
;
if
(
find_argument
(
name
,
f
,
&
it
,
&
event_arg
)
==
0
)
goto
error
;
return
(
struct
chunk
){
type
:
C_ARG_NAME
,
s
:
name
,
it
:
it
,
event_arg
:
event_arg
};
char
*
buf
=
_buf
;
int
ret
=
0
;
int
l
;
while
(
count
)
{
l
=
read
(
fd
,
buf
,
count
);
if
(
l
<=
0
)
{
printf
(
"read socket problem
\n
"
);
abort
();
}
count
-=
l
;
buf
+=
l
;
ret
+=
l
;
}
return
ret
;
}
/* { } is name of event (anything in between is smashed) */
if
(
*
cur
==
'{'
)
{
*
cur
=
0
;
cur
++
;
while
(
*
cur
&&
*
cur
!=
'}'
)
cur
++
;
if
(
*
cur
!=
'}'
)
goto
error
;
*
cur
=
0
;
cur
++
;
*
s
=
cur
;
return
(
struct
chunk
){
type
:
C_EVENT_NAME
};
}
event
get_event
(
int
s
,
char
*
v
,
void
*
d
)
{
int
type
;
int32_t
length
;
/* anything but [ and { is raw string */
/* TODO: deal with \ */
name
=
cur
;
while
(
*
cur
&&
*
cur
!=
'['
&&
*
cur
!=
'{'
)
cur
++
;
*
s
=
cur
;
return
(
struct
chunk
){
type
:
C_STRING
,
s
:
name
};
fullread
(
s
,
&
length
,
4
);
fullread
(
s
,
&
type
,
sizeof
(
int
));
length
-=
sizeof
(
int
);
fullread
(
s
,
v
,
length
);
error:
return
(
struct
chunk
){
type
:
C_ERROR
};
return
new_event
(
type
,
length
,
v
,
d
);
}
textlog
*
new_textlog
(
event_handler
*
h
,
void
*
database
,
char
*
event_name
,
char
*
format
)
static
void
*
gui_thread
(
void
*
_g
)
{
struct
textlog
*
ret
;
int
event_id
;
database_event_format
f
;
char
*
cur
;
ret
=
calloc
(
1
,
sizeof
(
struct
textlog
));
if
(
ret
==
NULL
)
abort
();
ret
->
event_name
=
strdup
(
event_name
);
if
(
ret
->
event_name
==
NULL
)
abort
();
ret
->
format
=
strdup
(
format
);
if
(
ret
->
format
==
NULL
)
abort
();
ret
->
database
=
database
;
event_id
=
event_id_from_name
(
database
,
event_name
);
ret
->
handler_id
=
register_handler_function
(
h
,
event_id
,
_event
,
ret
);
f
=
get_format
(
database
,
event_id
);
/* we won't get more than strlen(format) "chunks" */
ret
->
f
=
malloc
(
sizeof
(
struct
format_item
)
*
strlen
(
format
));
if
(
ret
->
f
==
NULL
)
abort
();
cur
=
ret
->
format
;
while
(
*
cur
)
{
struct
chunk
c
=
next_chunk
(
&
cur
,
f
);
switch
(
c
.
type
)
{
case
C_ERROR
:
goto
error
;
case
C_STRING
:
ret
->
f
[
ret
->
fsize
].
type
=
INSTRING
;
ret
->
f
[
ret
->
fsize
].
s
=
c
.
s
;
break
;
case
C_ARG_NAME
:
ret
->
f
[
ret
->
fsize
].
type
=
c
.
it
;
ret
->
f
[
ret
->
fsize
].
event_arg
=
c
.
event_arg
;
break
;
case
C_EVENT_NAME
:
ret
->
f
[
ret
->
fsize
].
type
=
INSTRING
;
ret
->
f
[
ret
->
fsize
].
s
=
ret
->
event_name
;
break
;
}
ret
->
fsize
++
;
gui
*
g
=
_g
;
gui_loop
(
g
);
return
NULL
;
}
int
main
(
int
n
,
char
**
v
)
{
extern
int
volatile
gui_logd
;
char
*
database_filename
=
NULL
;
void
*
database
;
int
port
=
DEFAULT_REMOTE_PORT
;
char
**
on_off_name
;
int
*
on_off_action
;
int
on_off_n
=
0
;
int
*
is_on
;
int
number_of_events
;
int
s
;
int
i
;
char
t
;
int
l
;
event_handler
*
h
;
textlog
*
textlog
;
gui
*
g
;
int
gui_mode
=
0
;
view
*
out
;
int
gui_active
=
1
;
on_off_name
=
malloc
(
n
*
sizeof
(
char
*
));
if
(
on_off_name
==
NULL
)
abort
();
on_off_action
=
malloc
(
n
*
sizeof
(
int
));
if
(
on_off_action
==
NULL
)
abort
();
for
(
i
=
1
;
i
<
n
;
i
++
)
{
if
(
!
strcmp
(
v
[
i
],
"-h"
)
||
!
strcmp
(
v
[
i
],
"--help"
))
usage
();
if
(
!
strcmp
(
v
[
i
],
"-d"
))
{
if
(
i
>
n
-
2
)
usage
();
database_filename
=
v
[
++
i
];
continue
;
}
if
(
!
strcmp
(
v
[
i
],
"-p"
))
{
if
(
i
>
n
-
2
)
usage
();
port
=
atoi
(
v
[
++
i
]);
continue
;
}
if
(
!
strcmp
(
v
[
i
],
"-on"
))
{
if
(
i
>
n
-
2
)
usage
();
on_off_name
[
on_off_n
]
=
v
[
++
i
];
on_off_action
[
on_off_n
++
]
=
1
;
continue
;
}
if
(
!
strcmp
(
v
[
i
],
"-off"
))
{
if
(
i
>
n
-
2
)
usage
();
on_off_name
[
on_off_n
]
=
v
[
++
i
];
on_off_action
[
on_off_n
++
]
=
0
;
continue
;
}
if
(
!
strcmp
(
v
[
i
],
"-ON"
))
{
on_off_name
[
on_off_n
]
=
NULL
;
on_off_action
[
on_off_n
++
]
=
1
;
continue
;
}
if
(
!
strcmp
(
v
[
i
],
"-OFF"
))
{
on_off_name
[
on_off_n
]
=
NULL
;
on_off_action
[
on_off_n
++
]
=
0
;
continue
;
}
if
(
!
strcmp
(
v
[
i
],
"-x"
))
{
gui_mode
=
1
;
continue
;
}
if
(
!
strcmp
(
v
[
i
],
"-debug-gui"
))
{
gui_logd
=
1
;
continue
;
}
if
(
!
strcmp
(
v
[
i
],
"-no-gui"
))
{
gui_active
=
0
;
continue
;
}
usage
();
}
return
ret
;
if
(
gui_active
==
0
)
gui_mode
=
0
;
error:
printf
(
"%s:%d: bad format '%s'
\n
"
,
__FILE__
,
__LINE__
,
format
);
abort
(
);
}
if
(
database_filename
==
NULL
)
{
printf
(
"ERROR: provide a database file (-d)
\n
"
);
exit
(
1
);
}
void
textlog_add_view
(
textlog
*
_l
,
view
*
v
)
{
struct
textlog
*
l
=
_l
;
l
->
vsize
++
;
l
->
v
=
realloc
(
l
->
v
,
l
->
vsize
*
sizeof
(
view
*
));
if
(
l
->
v
==
NULL
)
abort
();
l
->
v
[
l
->
vsize
-
1
]
=
v
;
database
=
parse_database
(
database_filename
);
number_of_events
=
number_of_ids
(
database
);
is_on
=
calloc
(
number_of_events
,
sizeof
(
int
));
if
(
is_on
==
NULL
)
abort
();
h
=
new_handler
(
database
);
if
(
gui_active
)
{
g
=
gui_init
();
new_thread
(
gui_thread
,
g
);
}
if
(
gui_mode
)
{
widget
*
w
,
*
win
;
// w = new_textlist(g, 600, 20, 0);
w
=
new_textlist
(
g
,
800
,
50
,
BACKGROUND_COLOR
);
win
=
new_toplevel_window
(
g
,
800
,
50
*
12
,
"textlog"
);
widget_add_child
(
g
,
win
,
w
,
-
1
);
out
=
new_view_textlist
(
1000
,
10
,
g
,
w
);
//tout = new_view_textlist(7, 4, g, w);
}
else
{
out
=
new_view_stdout
();
}
for
(
i
=
0
;
i
<
number_of_events
;
i
++
)
{
char
*
name
,
*
desc
;
database_get_generic_description
(
database
,
i
,
&
name
,
&
desc
);
textlog
=
new_textlog
(
h
,
database
,
name
,
desc
);
// "ENB_UL_CHANNEL_ESTIMATE",
// "ev: {} eNB_id [eNB_ID] frame [frame] subframe [subframe]");
textlog_add_view
(
textlog
,
out
);
free
(
name
);
free
(
desc
);
}
for
(
i
=
0
;
i
<
on_off_n
;
i
++
)
on_off
(
database
,
on_off_name
[
i
],
is_on
,
on_off_action
[
i
]);
s
=
get_connection
(
"0.0.0.0"
,
port
);
/* send the first message - activate selected traces */
t
=
0
;
if
(
write
(
s
,
&
t
,
1
)
!=
1
)
abort
();
l
=
0
;
for
(
i
=
0
;
i
<
number_of_events
;
i
++
)
if
(
is_on
[
i
])
l
++
;
if
(
write
(
s
,
&
l
,
sizeof
(
int
))
!=
sizeof
(
int
))
abort
();
for
(
l
=
0
;
l
<
number_of_events
;
l
++
)
if
(
is_on
[
l
])
if
(
write
(
s
,
&
l
,
sizeof
(
int
))
!=
sizeof
(
int
))
abort
();
if
(
gui_active
)
setup_event_selector
(
g
,
database
,
s
,
is_on
);
/* read messages */
while
(
1
)
{
char
v
[
T_BUFFER_MAX
];
event
e
;
e
=
get_event
(
s
,
v
,
database
);
handle_event
(
h
,
e
);
}
return
0
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment