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
|
/******************************************************************************
* Copyright (c) 2000-2018 Ericsson Telecom AB
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
*
* Contributors:
* Balasko, Jeno
* Delic, Adam
* Raduly, Csaba
*
******************************************************************************/
#include "LoggerPlugin.hh"
#include "ILoggerPlugin.hh"
#include <assert.h>
#include <dlfcn.h>
boolean str_ends_with(const char *str, const char *suffix)
{
if (!str || !suffix) return FALSE;
size_t lenstr = strlen(str);
size_t lensuffix = strlen(suffix);
if (lensuffix > lenstr) return FALSE;
return strncmp(str + lenstr - lensuffix, suffix, lensuffix) == 0;
}
enum SoType { RT1_SINGLE, RT1_PARALLEL, RT2_SINGLE, RT2_PARALLEL };
// determine the library type from the name ending
SoType get_so_type(const char* filename)
{
if (str_ends_with(filename, "-rt2.so")) {
return str_ends_with(filename, "-parallel-rt2.so") ? RT2_PARALLEL : RT2_SINGLE;
} else { // rt1
return str_ends_with(filename, "-parallel.so") ? RT1_PARALLEL : RT1_SINGLE;
}
}
void LoggerPlugin::load()
{
if (this->filename_) {
// determine the required library
boolean single_mode = TTCN_Runtime::is_single();
#ifndef TITAN_RUNTIME_2
const SoType required_so_type = single_mode ? RT1_SINGLE : RT1_PARALLEL;
const char* required_suffix_str = single_mode ? ".so" : "-parallel.so";
const char* required_runtime_str = single_mode ? "Load Test Single Mode Runtime" : "Load Test Parallel Mode Runtime";
#else
const SoType required_so_type = single_mode ? RT2_SINGLE : RT2_PARALLEL;
const char* required_suffix_str = single_mode ? "-rt2.so" : "-parallel-rt2.so";
const char* required_runtime_str = single_mode ? "Function Test Single Mode Runtime" : "Function Test Parallel Mode Runtime";
#endif
// if the provided filename ends with .so it is assumed to be a full file name,
// otherwise it's assumed to be the base of the file name that has to be suffixed automatically
expstring_t real_filename = mcopystr(this->filename_);
if (str_ends_with(this->filename_,".so")) {
// check if the filename is correct
if (get_so_type(this->filename_)!=required_so_type) {
TTCN_Logger::fatal_error("Incorrect plugin file name was provided (%s). "
"This executable is linked with the %s, the matching plugin file name must end with `%s'. "
"Note: if the file name ending is omitted it will be automatically appended.",
this->filename_, required_runtime_str, required_suffix_str);
}
} else { // add the appropriate suffix if the filename extension was not provided
real_filename = mputstr(real_filename, required_suffix_str);
}
// Dynamic plug-in. Try to resolve all symbols, die early with RTLD_NOW.
this->handle_ = dlopen(real_filename, RTLD_NOW);
if (!this->handle_) {
TTCN_Logger::fatal_error("Unable to load plug-in %s with file name %s (%s)", this->filename_, real_filename, dlerror());
}
Free(real_filename);
cb_create_plugin create_plugin =
(cb_create_plugin)(unsigned long)dlsym(this->handle_, "create_plugin");
if (!create_plugin) return;
this->ref_ = (*create_plugin)();
} else {
// Static plug-in. We simply instantiate the class without any `dl*()'.
assert(this->create_);
this->ref_ = this->create_();
}
this->ref_->init();
this->is_log2str_capable_ = this->ref_->is_log2str_capable();
}
// Completely destroy the logger plug-in and make it useless. However,
// reloading is possible. This should be called before the logger is
// deleted.
void LoggerPlugin::unload()
{
if (!this->ref_) return;
this->ref_->fini();
if (this->filename_) {
cb_destroy_plugin destroy_plugin =
(cb_destroy_plugin)(unsigned long)dlsym(this->handle_,
"destroy_plugin");
if (destroy_plugin) {
(*destroy_plugin)(this->ref_);
}
dlclose(this->handle_);
this->handle_ = NULL;
} else {
// For static plug-ins, it's simple.
delete this->ref_;
this->create_ = NULL;
}
this->ref_ = NULL;
}
|