Filter by scope in Boost.Log - c++

I'm using Boost.Log library. I've created a named_scope attribute that keeps track of where I am in the code. (I specify it by hand with BOOST_LOG_NAMED_SCOPE("...").) Is it possible to create a filter (using set_filter) that would select only the messages from a particular scope?

Please refer to Andrey's latest & greatest logging doc :
The scope stack is implemented as a thread-specific global storage
internally. There is the named_scope attribute that allows hooking
this stack into the logging pipeline. This attribute generates value
of the nested type named_scope::scope_stack which is the instance of
the scope stack. The attribute can be registered in the following way:
logging::core::get()->add_global_attribute("Scope",
attrs::named_scope());
Then, you should configure your front end sink filter to latch only your tags of interest (in the filter lambda or in your custom filter which you pass to set_filter() you can use the following in order to extract the scope name, assuming u work with MBCS)
typedef attrs::basic_named_scope< char >::value_type scope_stack;
logging::value_extractor<char, scope_stack> S("Scope");
scope_stack s = *S(rec);
if ( s.empty() == false )
{
const attrs::basic_named_scope_entry<char>& e = s.back();
// Filter by e.scope_name
...
}
I hope it will work for you :)

Related

Remove a property by name in OpenMesh

In OpenMesh, once a named property is added to an element, it will be permanent in the sense that the property survives the scope of the property manager as explained here. My question is, how to remove such a property by its name?
So far I tried removing by the property manager and even this one fails:
auto face_props = OpenMesh::FProp<FaceProp>(mesh, "face_props");
mesh.remove_property(face_props);
with the error
error: no matching function for call to ‘OpenMesh::TriMesh_ArrayKernelT<>::remove_property(OpenMesh::PropertyManager<OpenMesh::FPropHandleT<FaceProp>, int>&)’
Is there a remove_property function where I could write remove_property("face_props") (or similar) to remove the property?
Edit: The following gives the same error:
mesh.remove_property( OpenMesh::getProperty<OpenMesh::FaceHandle, FaceProp>(mesh, "face_props") );
I suspect that mesh.remove_property() expects a property handle object, but getProperty() returns a property manager. I don't see how to get around this.
Edit2: I guess an alternative question would be: how to get a property handle to a property from a property manager?
Edit3: Looking at the source, it seems like PropertyManager has a member function deleteProperty() but a) is private and b) it only deletes the property if retain is not set which I assume would be set for named properties.
Apparently one can define a lower level property handle and then use get_property_handle which takes a handle as reference and updates it in place. This works:
OpenMesh::FPropHandleT< FaceProp > fprop;
mesh.get_property_handle(fprop, "face_props");
mesh.remove_property( fprop );
I wish this was better documented. Or that I was better in C++.

Changing model parameters by cPar in other module

I am using this module hierarchy :
Node: {udpApp[0]<->udp<->networkLayer->wlan[0]} and wlan[0]: {CNPCBeacon<->mac<->radio}
I have given some initial parameter in the ini file for udpApp as :
**.host*.numUdpApps = 2
**.host*.udpApp[0].typename = "UDPBasicApp"
**.host*.udpApp[0].chooseDestAddrMode = "perBurst"
**.host*.udpApp[0].destAddresses = "gw1"
**.host*.udpApp[0].startTime = 1.32s
**.host*.udpApp[0].stopTime = 1.48s
But at run time I want to change the startTime and stopTime for udpAPP[0] through CNPCBeacon module. Hence I changed CNPCBeacon.cc as:-
cModule* parentmod = getParentModule();
cModule* grantParentmod = parentmod->getParentModule();
cModule* udpmod;
for (cSubModIterator iter(*grantParentmod); !iter.end(); iter++)
{
//EV<<"get the modulde "<< iter()->getFullName()<<endl;
if (strcmp(iter()->getFullName(), "udpApp[0]") == 0)
{
udpmod = iter();
break;
}
}
cPar& startTime = udpmod->par("startTime");
cPar& stopTime = udpmod->par("stopTime");
And I am successfully able to receive the values of startTime and stopTime. However I want to change these value in current module, which is resulting in an error by following code:
udpmod->par("startTime").setDoubleValue(4.2);
Can anybody please suggest me a way to change it at run time.
Declaring your parameter as volatile should solve your problem. But for future reference I'll provide further explanation below
Volatile vs. non-volatile:
Here it depends how you want to use this parameter. Mainly via the .ini file you have two types of parameters: volatile and non-volatile.
volatile parameters are read every time during your run. That woule be helpful if you want this parameter to be generated by a built-in function, for example, uniform(0,10) each time this volatile parameter will get a different value.
On the other hand non-volatile parameters are read just one, as they don't change from run to run.
Using the volatile type parameter does not give you full flexibility, in the sense that your parameter value will always fall with in a range predefined in the .ini
Dynamic Variable (parameter) Reassignment:
Instead what you could do is use a more robust approach, and re-define the variable which stores the value from that module parameter each time you have to do so.
For example in your case you could do the following:
varHoldingStartTime = par("startTime").doubleValue();
varHoldingStartTime = 4.2;
This way the actual value will change internally without reflecting to your run.
Parameter Studies:
Alternatively if you want this change of the parameter to be applied to multiple runs you could use the advanced built-in approach provided by OMNeT++ which allows you to perform Parameter Studies.
I have explained here how Parameter Studies work: https://stackoverflow.com/a/30572095/4786271 and also here how it can be achieved with constraints etc: https://stackoverflow.com/a/29622426/4786271
If none of the approaches suggested by me fit your case, answers to this question altogether might solve your problem: How to change configuration of network during simulation in OMNeT++?
EDIT: extending the answer to roughly explain handleParameterChange()
I have not used handleParameterChange() before as well, but from what can I see this function provides a watchdog functionality to the module which utilizes it.
To activate this functionality first the void handleParameterChange(const char *parameterName); has to be re-defined.
In essence what it seems to do is the following:
Assume we have two modules moduleA and moduleB and moduleB has parameter parB. moduleA changes the parB and when that happens, moduleB reacts to this change based on the behaviour defined in:
moduleB::handleParameterChange(parB);
The behaviour could be re-reading the original value for parB from the .ini etc.

How to access predefined variables within cfscript?

The following code works:
<cfoutput>#$.currentURL()#</cfoutput>
However, within a function, "$" is not available.
<cfscript>
function myTest() {
return $.currentURL();
}
</cfscript>
Does anyone know what actually is the equivalent of $ within a function?
Likewise, #pluginConfig.getDirectory()# works when used directly in cfoutput. However, within a cfscript function, it reports "unknown variable pluginConfig."
Thank you for advance for guiding me in the right direction.
When writing code outside the Mura Event Scope (like you do with that function), you have to obtain an instance of the Mura Scope ($) yourself. This can be done using the following code:
$ = application.serviceFactory.getBean('$');
Next you'll have to initialise the instance using an event object, a struct with value pairs or a 'siteID':
$.init(event);
$.init(myStruct);
$.init(siteID);
The same counts for the pluginConfig, this you can abtain via the Mura Scope. You'll have to pass the pluginID, moduleID, name or package of the plugin:
$.getPlugin(pluginID);
$.getPlugin(moduleID);
$.getPlugin(name);
$.getPlugin(package);
An other option you have is to pass the Mura Scope and the pluginConfig as arguments to the function. When writing a small plugin, this might be the easier way. But when writting medium or large plugins, it will get a bit messy when you're passing along these objects all the time.
The $ is used as a special framework variable in some CF frameworks (like Mura). You will need to figure out the framework context (if any) your code is executing in

Angular js directive dynamic template binding

I have a template which looks like:
scope:{
localClickFunc: "&click",
myLocalDbClickFunc: "&dblclick"
} ...
<myButton ng-click="localClickFunc($event)" ng-doubleckick="myLocalDbClickFunc($event)"/>
there are many other events (mouseover etc)
my localClickFunc are binded in scope directive with controller functions(they could be binded with "=" for my case It doesn't matter).
The problem is that in the usage of this 'myButton' directive not all attributes are necessary .If I use it with all the other events will get registered and fired through angular to a noop function.
I can have as many as 1000 buttons on the screen .What would be the solution to this ?. Are there conditional templates ?
The ? in the scope binding definition makes the attribute optional.
However, function bindings (&) are always optional, as far as Angular is concerned. I.e. Angular will not complain if you do not specify a function in this binding and it will put a function in the scope of the directive anyway. So you cannot write if( scope.localClickFunc == null ) to check for its existence.
I would suggest to use the optional binding =? to specify the callbacks. This way you will be able to check the scope for the existence of the binding and, only if it exists, bind it to the actual DOM event. Example code:
scope:{
localClickFunc: "=?click",
localDbClickFunc: "=?dblclick"
},
link: function(scope, element, attrs) {
...
if( scope.localClickFunc != null ) {
element.on("click", scope.localClickFunc);
}
...
}
Then use the directive as:
<myButton click="localClickFunc($event)"
dblclick="myLocalDbClickFunc($event)"
/>
You can specify any or all of the attributes and the handlers will be installed accordingly.
u can send the attr like say the directive name is mydir then and then in the link and compile functions one of the 3rd parameter is usually names as params and u get there by params.mydir (value will be ovidiu). you can send anything textbased like ';' seperated like "click;dbclick;onmouseout" and break it in the directive with params.mydir.split(';'). from there you can even go to groups of events like "allClicks", u just need in the link some dictionary or switch that will append the right stuff.

Boost.Log: how to filter by current thread id

I'm using Boost.Log, which is a part of Boost v1.54. I have a sink, which I want to only accept log messages from the current thread. How can I achieve that?
BOOST_LOG_ATTRIBUTE_KEYWORD(thread_id, "ThreadID", logging::attributes::current_thread_id::value_type)
std::stringstream stream;
logging::add_common_attributes();
boost::shared_ptr<text_sink> sink = boost::make_shared<text_sink>();
sink->locked_backend()->add_stream(stream);
logging::core::get()->add_sink(sink);
boost::thread::id currentThreadId = boost::this_thread::get_id();
// At this line compiler complains about the '==' operator.
sink->set_filter(thread_id == currentThreadId);
Without the last line everything works fine, and when I configure sink formatter, it outputs the calling thread ID. What is the proper way to compare thread_id attribute with the currentThreadId?
I know I can use some custom attribute to tag messages with the current thread ID, and then filter them by that attribute, but what about the default boost's current_thread_id attribute? Is it usable for such a purpose?
Well, after spending half the night digging around I came across the (undocumented?) boost::log::aux namespace, where I found boost::log::aux::this_thread::get_id() function. It returns an object of the proper type which I am now able to compare with the thread_id keyword.
Now I wonder if the boost::log::aux namespace is meant for boost internal use only? Some time ago I used to utilize some internal features of boost mutexes/locks, and after the next library update they changed everything and I couldn't even compile my code against that new version of the library. So now I don't want to repeat my past mistakes :)