1 /******************************************************************************
2 * Copyright (c) 2000-2016 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
13 ******************************************************************************/
14 #include "LoggerPlugin.hh"
15 #include "ILoggerPlugin.hh"
20 bool str_ends_with(const char *str
, const char *suffix
)
22 if (!str
|| !suffix
) return false;
23 size_t lenstr
= strlen(str
);
24 size_t lensuffix
= strlen(suffix
);
25 if (lensuffix
> lenstr
) return false;
26 return strncmp(str
+ lenstr
- lensuffix
, suffix
, lensuffix
) == 0;
29 enum SoType
{ RT1_SINGLE
, RT1_PARALLEL
, RT2_SINGLE
, RT2_PARALLEL
};
31 // determine the library type from the name ending
32 SoType
get_so_type(const char* filename
)
34 if (str_ends_with(filename
, "-rt2.so")) {
35 return str_ends_with(filename
, "-parallel-rt2.so") ? RT2_PARALLEL
: RT2_SINGLE
;
37 return str_ends_with(filename
, "-parallel.so") ? RT1_PARALLEL
: RT1_SINGLE
;
41 void LoggerPlugin::load()
43 if (this->filename_
) {
44 // determine the required library
45 bool single_mode
= TTCN_Runtime::is_single();
46 #ifndef TITAN_RUNTIME_2
47 const SoType required_so_type
= single_mode
? RT1_SINGLE
: RT1_PARALLEL
;
48 const char* required_suffix_str
= single_mode
? ".so" : "-parallel.so";
49 const char* required_runtime_str
= single_mode
? "Load Test Single Mode Runtime" : "Load Test Parallel Mode Runtime";
51 const SoType required_so_type
= single_mode
? RT2_SINGLE
: RT2_PARALLEL
;
52 const char* required_suffix_str
= single_mode
? "-rt2.so" : "-parallel-rt2.so";
53 const char* required_runtime_str
= single_mode
? "Function Test Single Mode Runtime" : "Function Test Parallel Mode Runtime";
55 // if the provided filename ends with .so it is assumed to be a full file name,
56 // otherwise it's assumed to be the base of the file name that has to be suffixed automatically
57 expstring_t real_filename
= mcopystr(this->filename_
);
58 if (str_ends_with(this->filename_
,".so")) {
59 // check if the filename is correct
60 if (get_so_type(this->filename_
)!=required_so_type
) {
61 TTCN_Logger::fatal_error("Incorrect plugin file name was provided (%s). "
62 "This executable is linked with the %s, the matching plugin file name must end with `%s'. "
63 "Note: if the file name ending is omitted it will be automatically appended.",
64 this->filename_
, required_runtime_str
, required_suffix_str
);
66 } else { // add the appropriate suffix if the filename extension was not provided
67 real_filename
= mputstr(real_filename
, required_suffix_str
);
70 // Dynamic plug-in. Try to resolve all symbols, die early with RTLD_NOW.
71 this->handle_
= dlopen(real_filename
, RTLD_NOW
);
73 TTCN_Logger::fatal_error("Unable to load plug-in %s with file name %s (%s)", this->filename_
, real_filename
, dlerror());
77 cb_create_plugin create_plugin
=
78 (cb_create_plugin
)(unsigned long)dlsym(this->handle_
, "create_plugin");
79 if (!create_plugin
) return;
80 this->ref_
= (*create_plugin
)();
82 // Static plug-in. We simply instantiate the class without any `dl*()'.
83 assert(this->create_
);
84 this->ref_
= this->create_();
88 this->is_log2str_capable_
= this->ref_
->is_log2str_capable();
91 // Completely destroy the logger plug-in and make it useless. However,
92 // reloading is possible. This should be called before the logger is
94 void LoggerPlugin::unload()
96 if (!this->ref_
) return;
98 if (this->filename_
) {
99 cb_destroy_plugin destroy_plugin
=
100 (cb_destroy_plugin
)(unsigned long)dlsym(this->handle_
,
102 if (destroy_plugin
) {
103 (*destroy_plugin
)(this->ref_
);
105 dlclose(this->handle_
);
106 this->handle_
= NULL
;
108 // For static plug-ins, it's simple.
110 this->create_
= NULL
;