log4cplus does not show all messages - c++

We are building a module that is part of a full embedded Linux operating systems. We are using log4cplus for diagnostics.
log.properties contains:
log4cplus.logger.CompanyGlue=TRACE, console
cm_bind_helper.h contains much more complicated than this. All of the DBG_XXX messages appear on the console.
#include "qobject.h"
#include "log4cplus/dbglog.h"
class bind_helper : public QObject
{
protected:
const char *debugModuleName = "CompanyGlue";
log4cplus::Logger debugModule { Logger::getInstance(debugModuleName) };
bool set_value(CMPath path, PType &input)
{
auto old_value = CMRoot()->getValue(path);
if (input != old_value) {
DBG_DEBUG("Changing " << path << " to " << input);
}
}
}
cm_bridge.cpp contains much more code than this. However, none of the DBG_XXX messages appear on the console.
#include "cm_bridge.h"
#include "cm_bind_helpers.h"
struct CompanyContentModelBridge::detail_ : public bind_helper
{
std::shared_ptr<company::device_base> base;
detail_(QObject *parent)
: bind_helper(parent)
{
configure_system_advanced_control();
}
void configure_system_advanced_control();
std::string get_exported_file_size();
}
using detail_ = CompanyContentModelBridge::detail_;
void detail_::configure_system_advanced_control()
{
base->add_get_only_entry<std::string>("SPDSZ", get_exported_file_size());
}
std::string detail_::get_exported_file_size()
{
DBG_INFO("get exported file size");
//diag("exported file size");
}
I have tried various ways to configure log4cplus in cm_bridge.cpp, including the same two lines in cm_bind_helpers.h and as follows. I also removed them assuming that inheritance would handle it. Nothing made the DBG_XXX messages appear.
DBG_IMPL_DEBUG_MODULE(CompanyGlue);
Eventually, I added this function to cm_bind_helpers.h. It worked when called from its own class but failed when called from get_exported_file_size() (with comment removed).
void diag(std::string_view what) {
DBG_DEBUG("bind helper diag " << what);
}
I'm stumped. I do not know why messages are being suppressed from one file but not the other.

Related

Why does this exception appears when reading a file, but not when storing in it?

I'm currently working on a project with MFC and I noticed something weird that apparently has been there for a couple of years. When I launch the .exe of the program, it will do n number of things including reading a .DAT file and storing it as well. If the file doesn't exists, the program will try to find it with no luck throwing this CFile exception: The file could not be located. Which is correct because it doesn't exists. I have to do some operations first to generate that file, the storing process works fine. When the file exists and I run the program again, it's supposed read the file but this CArchive exception shows up: Invalid file format. And I don't understand why.
This is the Serialize():
//Fruits.cpp
void CFruits::Serialize(CArchive &ar)
{
int nVersion = 0;
CObject::Serialize(ar);
ar.SerializeClass(GetRuntimeClass());
if(ar.IsStoring())
{
ar.Write(&m_bInit,sizeof(bool));
ar.Write(&m_bYummy,sizeof(bool));
ar.Write(&m_bAcid, sizeof(bool));
ar.Write(&m_bFresh,sizeof(bool));
...
...
...
ar<<m_cType;
ar<<m_cColour;
ar<<m_cFlavor;
ar<<m_cPrice;
ar<<m_cQuantity;
}
else
{
nVersion = ar.GetObjectSchema();
ar.Read(&m_bInit,sizeof(bool));
ar.Read(&m_bYummy,sizeof(bool));
ar.Read(&m_bAcid, sizeof(bool));
ar.Read(&m_bFresh,sizeof(bool));
...
...
...
if( nVersion >= 2 || nVersion < 0)
ar<<m_cType;
else
m_cType=0;
if (nVersion >= 3 || nVersion < 0)
ar<<m_cColour;
else
m_cColour=0;
if (nVersion >= 4 || nVersion < 0)
ar<<m_cFlavor;
else
ar<<m_cFlavor=0;
if( nVersion >= 5 || nVersion < 0)
{
ar<<m_cPrice;
ar<<m_cQuantity;
}
else
{
m_cPrice=0;
m_cQuantity=0;
}
}
m_oSales.Serialize(ar);
m_oAdmin.Serialize(ar);
...
...
}
IMPLEMENT_SERIAL(CVehiculo,CObject,VERSIONABLE_SCHEMA | 6)
This is the SerializeElements:
//Fruits.cpp
void AFXAPI SerializeElements(CArchive &ar,CFruits * fruits,int ncount)
{
try
{
for(cont=0;cont<ncount;cont++)
fruits[cont].Serialize(ar);
}
catch(CArchiveException *AE)
{
//Here it stores the exception in a Log. Exception 5
}
}
The serializeElements is used to store and read the file n times, as declared here in the header file of fruits:
//Fruits.h
class CFruits : public CObject
{
public:
CFruits();
CFruits(const CFruits &O);
virtual ~CFruits();
void operator = (const CFruits &O);
void Serialize(CArchive &ar);
protected:
DECLARE_SERIAL(CFruits)
};
void AFXAPI SerializeElements(CArchive &ar,CFruits * fruits,int ncount);
typedef CArray<CFruits, CFruitso&> TArrayFruits;
The values of this Array, and the methods used to call the serialize are defined here in my main function:
//main.h
#include "CFruits.h"
class CMain : public CDialog
{
// Construction
public:
enum T_Fruits { eFruitsOnLine, eFruitsIng, eFruitsTra, eFruitsAnt, eFruitsP3, eFruitsP2, eFruitsP1, eFruitsC1, eFruitsC0, eFruitsEscape, eFruitsVideo};
private:
void StoreFruits();
void ReadFruits();
The SerializeElements for-loop is supposed to run 11 times, but I noticed that it only does it 1 time, then the Schema version changes to -1, (originally 6 cause I managed to trace the value). This happens only when reading the file.
I've tried the following:
I can't use debug so I have to use Logs, I placed a Log after every sentence in the Serialize() function, I found what seems to be the issue, this line:
ar.SerializeClass(GetRuntimeClass());
I used a try-catch and found that when that sentence happens, it throws the exception so, it doesn't continue reading. That is the moment where the version changes to -1. I tried to change that to:
ar.SerializeClass(RUNTIME_CLASS(CFruits));
Is the same result, I've read many forums trying to find the answer but I can't seem to do so. I've read the documentation and I found this here:
https://learn.microsoft.com/en-us/cpp/mfc/reference/carchive-class?view=vs-2019#serializeclass
Like ReadClass, SerializeClass verifies that the archived class
information is compatible with your runtime class. If it is not
compatible, SerializeClass will throw a CArchiveException.
But it doesn't make sense to me, because it doesn't fail storing. Should I look into something else?
Thank you
EDIT:
I'm posting the Store and Read methods
void CMain::ReadFruits()
{
CString CSerror, sFileName;
CString sDebug;
try
{
sFileName.Format("FRUITS%03d.DAT",GetNumT());
CFile fFruitsTag(sFileName,CFile::modeRead);
CArchive ar(&fFruitsTag,CArchive::load);
m_vFruits.Serialize(ar);
ar.Close();
fFruitsTag.Close();
}
catch(CFileException *FE)
{
...
}
catch(CArchiveException *AE)
{
...
}
}
void CMain::StoreFruits()
{
CString CSerror, sFileName;
try
{
if(!m_bStoringFruits)
{
sFileName.Format("FRUITS%03d.DAT",GetNumT());
m_bStoringFruits=true;
CFile fFruitsTag(sFileName,CFile::modeCreate|CFile::modeWrite);
CArchive ar(&fFruitsTag,CArchive::store);
m_vFruits.Serialize(ar);
ar.Close();
fFruitsTag.Close();
m_bStoringFruits=false;
}
}
catch(CFileException *FE)
{
...
}
catch(CArchiveException *AE)
{
...
}
catch(CException *e)
{
...
}
}

QLibrary functions work slow on first call

I'm using QLibrary to load functions from one .dll file.
I succesfully load it, succesfully resolve functions.
But when i use some function from that .dll for the first time, this function works very slow(even if it is very simple one). Next time i use it again - and the speed is just fine (immediately, as it should be).
What is the reason for such behaviour? I suspect some caсhing somewhere.
Edit 1: Code:
typedef int(*my_type)(char *t_id);
QLibrary my_lib("Path_to_lib.dll");
my_lib.load();
if(my_lib.isLoaded){
my_type func = (my_type)my_lib.resolve("_func_from_dll");
if(func){
char buf[50] = {0};
char buf2[50] = {0};
//Next line works slow
qint32 resultSlow = func(buf);
//Next line works fast
qint32 resultFast = func(buf2);
}
}
I wouldn't blame QLibrary: func simply takes long the first time it's invoked. I bet that you'll have identical results if you resolve its address using platform-specific code, e.g. dlopen and dlsym on Linux. QLibrary doesn't really do much besides wrapping the platform API. There's nothing specific to it that would make the first call slow.
There is some code smell of doing file I/O in constructors of presumably generic classes: do the users of the class know that the constructor may block on disk I/O and thus ideally shouldn't be invoked from the GUI thread? Qt makes the doing this task asynchronously fairly easy, so I'd at least try to be nice that way:
class MyClass {
QLibrary m_lib;
enum { my_func = 0, other_func = 1 };
QFuture<QVector<FunctionPointer>> m_functions;
my_type my_func() {
static my_type value;
if (Q_UNLIKELY(!value) && m_functions.size() > my_func)
value = reinterpret_cast<my_type>(m_functions.result().at(my_func));
return value;
}
public:
MyClass() {
m_lib.setFileName("Path_to_lib.dll");
m_functions = QtConcurrent::run{
m_lib.load();
if (m_lib.isLoaded()) {
QVector<QFunctionPointer> funs;
funs.push_back(m_lib.resolve("_func_from_dll"));
funs.push_back(m_lib.resolve("_func2_from_dll"));
return funs;
}
return QVector<QFunctionPointer>();
}
}
void use() {
if (my_func()) {
char buf1[50] = {0}, buf2[50] = {0};
QElapsedTimer timer;
timer.start();
auto result1 = my_func()(buf1);
qDebug() << "first call took" << timer.restart() << "ms";
auto result2 = my_func()(buf2);
qDebug() << "second call took" << timer.elapsed() << "ms";
}
}
};

Calling a method async does not work anymore after refactoring

In order to separate my GUI from the logic (which fetches data from a REST service), I refactored some logic into a controller.
Now, only part of the logic seems to work.
The GUI component looks like this after refactoring (I am using the JUCE framework)
#pragma once
#include "../../JuceLibraryCode/JuceHeader.h"
#include "../../GUI.Controller/includes/ProjectEntryListController.h"
#include "ProjectEntryListComponent.h"
#include "LocalProjectEntryComponent.h"
class ProjectBrowserTabComponent : public TabbedComponent
{
public:
ProjectBrowserTabComponent();
~ProjectBrowserTabComponent();
private:
ProjectEntryListComponent m_remote_proj;
ProjectEntryListComponent m_local_proj;
ProjectEntryListController *pelccont = new ProjectEntryListController(&m_remote_proj);
ProjectEntryListController *pelccont2 = new ProjectEntryListController(&m_local_proj);
};
The GUI controller looks like this:
#define BOOST_THREAD_PROVIDES_FUTURE
#include "../includes/ProjectEntryListController.h"
template<typename R>
bool isReady(std::future<R> const& f)
{
Logger::writeToLog("check future");
return f.wait_for(std::chrono::seconds(-1)) == std::future_status::ready;
}
ProjectEntryListController::ProjectEntryListController(ProjectEntryListComponent *comp) {
m_comp = comp;
requestProjects();
}
void ProjectEntryListController::requestProjects()
{
Logger::writeToLog("requesting projects");
projectsFuture = std::async(std::launch::async, &ProjectsController::getProjects, &pc);
Logger::writeToLog("requested projects");
}
void ProjectEntryListController::backgroundCheckFuture()
{
timer = new boost::asio::deadline_timer(io_service, boost::posix_time::seconds(interval_secs));
timer->async_wait(boost::bind(&ProjectEntryListController::fetchData, this, boost::asio::placeholders::error, timer));
ioSvcFuture = std::async(std::launch::async, static_cast<size_t(boost::asio::io_service::*)()>(&boost::asio::io_service::run), &io_service);
}
void ProjectEntryListController::initData() {
requestProjects();
backgroundCheckFuture();
}
void ProjectEntryListController::fetchData(const boost::system::error_code& /*e*/,
boost::asio::deadline_timer* tmr) {
if (isReady(projectsFuture)) {
projects = projectsFuture.get();
for (auto project : projects)
{
ProjectEntryComponent *pec = new ProjectEntryComponent(std::to_string(project.getId()), "222");
m_comp->addListEntry(pec);
m_comp->repaint();
}
Logger::writeToLog("got projs");
}
else {
tmr->expires_at(tmr->expires_at() + boost::posix_time::seconds(interval_secs));
tmr->async_wait(boost::bind(&ProjectEntryListController::fetchData, this, boost::asio::placeholders::error, tmr));
}
}
The requestProjects method's log messages are appearing in my console, but not the log message of the getProjects method I am calling asynchronously:
std::vector<Project> ProjectsController::getProjects() {
std::vector<Project> result;
if(serviceClient != nullptr) {
try
{
std::this_thread::sleep_for(std::chrono::seconds());
std::cout << "controller requested projs\n";
result = serviceClient->getAvailableProjects();
}
catch (const std::exception&)
{
}
}
return result;
}
However, when I debug into the code, the debugger (using VS 2015) also is able to step to the log message.
What am I doing wrong?
Actually I solved this now.
1.) I was calling the wrong method requestProjects instead of initData
2.) I couldn't see the result because the implementation of ProjectEntryComponent::ProjectEntryComponent(std::string name, std::string version) was missing

Visual Studio C++ unit testing (unmanaged)

I'm setting up a unit test suite for some unmanaged C++ code, and I've got some questions.
Setup
I added the project to my solution with Visual C++ → Test → Native Unit Test Project.
Code
In order to figure out how things are grouped in this test framework, and what initialization runs when, I replaced the content of the source file (unittest1.cpp) with a modified version of the USAGE EXAMPLE from the top of CppUnitTest.h:
#include <CppUnitTest.h>
#include <string>
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using std::string;
BEGIN_TEST_MODULE_ATTRIBUTE()
TEST_MODULE_ATTRIBUTE(L"Date", L"2010/6/12")
END_TEST_MODULE_ATTRIBUTE()
static string Indent("");
void openBlock()
{
Logger::WriteMessage((Indent + "{").c_str());
Indent += " ";
}
void closeBlock()
{
Indent.resize(Indent.size() >= 2 ? (Indent.size() - 2) : 0);
Logger::WriteMessage((Indent + "}").c_str());
}
TEST_MODULE_INITIALIZE(ModuleInitialize)
{
Logger::WriteMessage((Indent + "In Module Initialize").c_str());
openBlock();
}
TEST_MODULE_CLEANUP(ModuleCleanup)
{
closeBlock();
Logger::WriteMessage((Indent + "In Module Cleanup").c_str());
}
TEST_CLASS(Class1)
{
public:
Class1()
{
Logger::WriteMessage((Indent + "In Class1").c_str());
openBlock();
}
~Class1()
{
closeBlock();
Logger::WriteMessage((Indent + "In ~Class1").c_str());
}
TEST_CLASS_INITIALIZE(ClassInitialize)
{
Logger::WriteMessage((Indent + "In Class Initialize").c_str());
openBlock();
}
TEST_CLASS_CLEANUP(ClassCleanup)
{
closeBlock();
Logger::WriteMessage((Indent + "In Class Cleanup").c_str());
}
BEGIN_TEST_METHOD_ATTRIBUTE(Method1)
TEST_OWNER(L"OwnerName")
TEST_PRIORITY(1)
END_TEST_METHOD_ATTRIBUTE()
TEST_METHOD(Method1)
{
Logger::WriteMessage((Indent + "In Method1").c_str());
Assert::AreEqual(0, 0);
}
TEST_METHOD(Method2)
{
Logger::WriteMessage((Indent + "In Method2").c_str());
Assert::Fail(L"Fail");
Logger::WriteMessage("This won't print due to failure above.");
}
};
Output
It generated the output below. (I added some linebreaks for clarity.)
In Module Initialize
{
In Class Initialize
{
In Class1
{
In Method1
}
In ~Class1
In Class1
{
In Method2
}
In ~Class1
}
In Class Cleanup
}
In Module Cleanup
Inferences
From this I infer:
Each TEST_MODULE contains zero or more TEST_CLASSes.
Each TEST_CLASS contains zero or more TEST_METHODs.
TEST_MODULE_INITIALIZE() and TEST_MODULE_CLEANUP() are run once for each TEST_MODULE, before/after its series of TEST_CLASSes are executed.
TEST_CLASS_INITIALIZE() and TEST_CLASS_CLEANUP() are run once for each TEST_CLASS, before/after its series of TEST_METHODs are executed.
Each TEST_METHOD is an instance of a TEST_CLASS. The class constructor is executed immediately before the TEST_METHOD(), and the class destructor is executed immediately after the TEST_METHOD().
Questions
Are my inferences above all correct? Have I missed anything important?
Should/must I always have one and only one TEST_MODULE per source file? Can a TEST_MODULE be split among multiple source files? What is best practice?
May I have more than one TEST_CLASS per file or TEST_MODULE? Are there best practices in this regard?
What is the purpose of ATTRIBUTEs? How are they used?
What is the name of this unit test framework? What search terms can I use to learn more?

Coding State Machine in C++

I'm attempting to code a state machine based on a gumball machine. I have a interface class of a basic state, while I have specific states that use this interface. I have four states, no_quarter, has_quarter, sold, and sold_out states. I also have a gumball machine class that handles these states and depending on which state my machine is in, it will go that class and do the needed action. Here is my code that is having the problem, I'll post my functions also.
Gumball_Machine.h
class Gumball_Machine
{
private:
int gumball_count;
State *current_state;
No_Quarter_State *nqs;
Has_Quarter_State *hqs;
Sold_State *ss;
Sold_Out_State *sos;
public:
Gumball_Machine(int inventory)
{
gumball_count = inventory;
nqs = new No_Quarter_State(this);
hqs = new Has_Quarter_State(this);
ss = new Sold_State(this);
sos = new Sold_Out_State(this);
if (gumball_count == 0)
set_state(sos);
else
set_state(nqs);
}
void insert_quarter()
{
current_state->insert_quarter();
}
void eject_quarter()
{
current_state->eject_quarter();
}
void turn_crank()
{
current_state->turn_crank();
}
void dispense()
{
current_state->dispense();
}
void set_state(State *new_state)
{
current_state = new_state;
}
State *get_no_quarter_state()
{
return nqs;
}
State *get_has_quarter_state()
{
return hqs;
}
State *get_sold_state()
{
return ss;
}
State *get_sold_out_state()
{
return sos;
}
No_Quarter_State.h
#ifndef NO_QUARTER_STATE_H_INCLUDED
#define NO_QUARTER_STATE_H_INCLUDED
#include "State.h"
class No_Quarter_State: public State
{
public:
No_Quarter_State(Gumball_Machine *gbm);
void insert_quarter();
void eject_quarter();
void turn_crank();
void dispense();
};
#endif // NO_QUARTER_STATE_H_INCLUDED
No_Quarter_State.cpp
#include "No_Quarter_State.h"
#include "Gumball_Machine.h"
No_Quarter_State::No_Quarter_State(Gumball_Machine *machine)
{
machine = machine;
}
void No_Quarter_State::insert_quarter()
{
cout << "You inserted a quarter.\n";
machine->set_state(machine->get_has_quarter_state());
}
void No_Quarter_State::eject_quarter()
{
cout << "You must insert a quarter before you can eject one.\n";
}
void No_Quarter_State::turn_crank()
{
cout << "You must insert a quarter before you can crank the handle.\n";
}
void No_Quarter_State::dispense()
{
cout << "You need to pay first before you can get a gumball.\n";
}
The line I'm having an issue is in the No_Quarter_State.cpp
machine->set_state(machine->get_has_quarter_state());
This is giving me a run-time error. I've seen examples like this but I'm not completely sure if this is legal in C++. I'm attempting to switch the state of my gumball machine object.
The error I get is a generic not responding error: "test.ext has stopped working". I'm using CodeBlocks to code this.
In the constructor, the presumed member variable machine is hidden by the parameter.
No_Quarter_State::No_Quarter_State(Gumball_Machine *machine)
{
machine = machine;
}
You can fix this by using initializer list syntax instead:Thanks Sneftel and NathanOliver
No_Quarter_State::No_Quarter_State(Gumball_Machine *machine)
: machine(machine)
{
}
However, in regular method functions, you would have to use this-> if you named the method parameter the same as the member variable. A typical style used to avoid that issue is to prepend m_ or append _ to member names.