Hello everyone,
As you may already be aware, I have been investigating the possibility of m=
oving the high priority event list into it's own thread.
That turned out to be the easy part,.
When I tested it out I realized the macro system was never designed for mul=
ti-threaded support and it was getting stomped on.
To that end I have decided to robustify the macro system by creating a hand=
ful of wrapper functions that will make the macros thread safe (as long as =
all macro calls are passed through them).
These functions are
sprintf_macro_data
set_macro_data
get_macro_data
free_macro_data
The functions create and enforce thread safety through a couple of methods.
First off, mutexes are used to keep more than one hand at a time out of the=
cookie jar.
Secondly, there is no shared mutable data=20
Data returned from get_macro_data is a copy rather than the raw data itself.
To eliminate a bunch of boiler plate code, set_macro_data calls free_macro_=
data to free it's old copy of the data first.
Additionally, set_macro_data creates it's own copy of the data passed in to=
it, leaving the callee's copy alone.
Now each thread will be provided with it's own copy of the macro data upon =
request.
This way the callee can do whatever it wants with it's own copy of the data=
at it's leisure, a side benefit is this can prevent double free and memory=
corruption conditions.
So how do you update macro data now?
It's quite simple really
We use get, modify and set
For instance...
Previously it would have been
dosomething(macro_x[SOMEMACRO]);
Now it's
char * data =3D get_macro_data(macro_x,SOMEMACRO);
dosomething(data);
set_macro_data(data);
free(data);
The problem with the previous method is that one thread may try to free SOM=
EMACRO at the same time it's being used by another thread.
There will be a slight performance hit for doing it this way, but I don't p=
redict anything too drastic, and I think the benefits will outweigh the cos=
ts in the long term.
The fact is we don't update macros that many places in the code base, it's =
all get, set or free for the most part, so a performance hit in the update =
section should be negligible.
There are additional benefits as well.
Thus far, I have managed to replace large sections of boiler plate code wit=
h the thread safe versions, for instance.
In grab_service_macros
There are several sections that look like this...
/* get the last state change time macro */
if(macro_x[MACRO_LASTSERVICESTATECHANGE]!=3DNULL)
free(macro_x[MACRO_LASTSERVICESTATECHANGE]);
macro_x[MACRO_LASTSERVICESTATECHANGE]=3D(char *)malloc(MAX_DATETIME_LENGTH=
);
if(macro_x[MACRO_LASTSERVICESTATECHANGE]!=3DNULL){
snprintf(macro_x[MACRO_LASTSERVICESTATECHANGE],MAX_DATETIME_LENGTH,"%lu",=
(unsigned long)svc->last_state_change);
macro_x[MACRO_LASTSERVICESTATECHANGE][MAX_DATETIME_LENGTH-1]=3D'\x0';
}
All of that code can be replaced with a single call to sprintf_macro_data
sprintf_macro_data(macro_x,MACRO_LASTSERVICESTATECHANGE,MAX_DATETIME_LENGTH=
,"%lu",(unsigned long)svc->last_state_change);
I believe at this point I've got everything covered, but if anyone sees any=
thing I may have overlooked, please let me know
Sincerely,
Steve
NOTICE: This email message is for the sole use of the intended recipient(s=
) and may contain confidential and privileged information. Any unauthorized=
review, use, disclosure or distribution is prohibited. If you are not the =
intended recipient, please contact the sender by reply email and destroy al=
l copies of the original message.
This post was automatically imported from historical nagios-devel mailing list archives
Original poster: [email protected]