VisiTelcoLog Guide : Advanced features

Advanced features
This section covers the following advanced topics:
Log duration
Setting a log duration interval allows users to create a coarse-grained time interval (window) during which an unlocked and enabled log object is functional. When the log duration is set the log object will only allow writing log records or events to the log within the specified time interval.
The log duration time interval is set and retrieved with the following methods:
set_interval(in DsLogAdmin::TimeInterval interval);
and
DsLogAdmin::TimeInterval get_interval();
The input parameter and return value are an IDL structure defined as:
module DsLogAdmin {
typedef TimeBase::TimeT TimeT;
struct TimeInterval {
TimeT start;
TimeT stop;
};
};
The start and stop fields of a time interval are of type CORBA::ULongLong. Their values are numbers of 10-7 seconds (or 100 nanoseconds) counted from 00:00:00, Oct. 15, 1582 using Greenwich Mean Time (GMT).
Although the start and stop time unit is specified by OMG as 10-7 second, the actual time resolution supported by VisiTelcoLog is in seconds. Start and stop values specified in set_interval() will be rounded to the nearest value of full seconds by the VisiTelcoLog Service.
If the start and stop values are both set to 0 (zero), or rounded to zero seconds, the log will always be in a functional state.
To retrieve the current log duration setting, users can call the get_interval() operation on the target log.
Log scheduling
Log scheduling allows users to set a series of fine-grained weekly time intervals (weekly masks) on a given log object. When scheduling is set up the log object will only allow writing log records or events to the log within these time intervals, if it is within a log duration (see “Log duration”), and the log is in an unlocked and enabled state.
Log scheduling time intervals are set and retrieved via the following methods:
set_week_mask(in DsLogAdmin::WeekMask weekmask);
and
DsLogAdmin::WeekMask get_week_mask();
The input parameter and return value of above methods are an IDL sequence of an IDL structure WeekMaskItem. They are defined as:
module DsLogAdmin {
struct Time24 {
unsigned short hour; // 0 - 23
unsigned short minute; // 0 - 59
};

struct Time24Interval {
Time24 start;
Time24 stop;
};

typedef sequence<Time24Interval> IntervalsOfDay;
typedef unsigned short DaysOfWeek;

struct WeekMaskItem {
DaysOfWeek days;
IntervalsOfDay intervals;
};

typedef sequence<WeekMaskItem> WeekMask;
};
Greenwich Mean Time zone (GMT) is used by default. The user can choose to use the local time zone of the log server by starting the VisiTelcoLog Service with the following property setting:
vbroker.dslog.scheduleByServerLocalTime=true
For diagnostic purposes the log schedule setting changes and active behavior can be observed on the Console stdout by starting the VisiTelcoLog Service with the following property setting:
vbroker.dslog.timerDebug=true
VisiTelcoLog Service is shipped with an example of log schedule in the following directory:
<install_dir>/examples/vbe/telcolog/primitive_cpp/scheduler.C
The following C++ code snippet illustrates how to use set_week_mask():
// 7:30 am to 12:00 am
DsLogAdmin::Time24Interval morning = {{7,30},{12,0}};

// 13:30 (1:30 pm) to 17:30 (5:30 pm)
DsLogAdmin::Time24Interval afternoon = {{13,30},{17,30}};

// 21:00 (9:00 pm) to 23:30 (11:30 pm)
DsLogAdmin::Time24Interval night = {{21,0},{23,30}};

// 19:30 (7:30 pm) to 22:30 (11:30 pm)
DsLogAdmin::Time24Interval evening = {{19,30},{22,30}};

// 9:00 am to 16:30 (4:30 pm)
DsLogAdmin::Time24Interval wkend_day = {{9,0},{16,30}};

DsLogAdmin::WeekMask new_weekmask;
new_weekmask.length(2);

// weekday schedule in the 0th weekmask item
new_weekmask[0].days = (DsLogAdmin::Monday
| DsLogAdmin::Tuesday
| DsLogAdmin::Wednesday
| DsLogAdmin::Thursday
| DsLogAdmin::Friday );

new_weekmask[0].intervals.length(3); // 3 intervals
new_weekmask[0].intervals[0] = morning;
new_weekmask[0].intervals[1] = afternoon;
new_weekmask[0].intervals[2] = night;

// weekend schedule in the 1st weekmask item
new_weekmask[1].days = (DsLogAdmin::Sunday
| DsLogAdmin::Saturday );

new_weekmask[1].intervals.length(2); // 2 intervals
new_weekmask[1].intervals[0] = wkend_day;
new_weekmask[1].intervals[1] = evening;

// set new week mask on the log
log->set_week_mask(new_weekmask);
The following C++ code snippet illustrates how to use get_week_mask() and process the result:
// retrieve current week mask from the log
DsLogAdmin::WeekMask_var holder;
holder = log->get_week_mask();

const char* day_names[7] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};

const DsLogAdmin::WeekMask& mask = holder.in();
CORBA::Short day, daybit;
CORBA::ULong i, j;

// print retrieved schedule by days.
for(day=0,daybit=1;day<7;daybit = daybit*2, day++) {
cout << " " << day_names[day] << ": ";
for(i=0;i<mask.length();i++) {
const DsLogAdmin::WeekMaskItem& item = mask[i];

if( (daybit & item.days) == 0 ) {
continue;
}

for(j=0;j<item.intervals.length();j++) {
const DsLogAdmin::Time24Interval& interval =
item.intervals[j];
char buf[32];

sprintf(buf, "[%02u:%02u-%02u:%02u] ",
interval.start.hour,
interval.start.minute,
interval.stop.hour,
interval.stop.minute);

cout << buf;
}
}

cout << endl;
}
}
On processing set_week_mask() requests, the log object server validates the input weekly mask parameter. Exceptions that are raised on set_week_mask() and their corresponding weekly mask setting errors are explained in the following table.
Case 1: Start time is later than stop time. Therefore, an interval starting at midnight and stopping after midnight is not supported. The effect of an interval that spans days should be done using two intervals: one that stops before just before midnight (23:59) and another that starts just after midnight on the next day (00:00).
Case 2: Time intervals overlap. Start or stop time of one scheduled interval is within the bounds of another scheduled interval in the same weekly mask parameter.
On failure of set_week_mask() due to errors, the log's existing weekly mask will remain and a DsLogNotification::ProcessingErrorAlarm log event (see “Log generated events”) will be sent. On success of set_week_mask() the existing weekly mask will be completely replaced by the new weekly mask. Therefore, to completely erase an existing weekly mask, the application can invoke set_week_mask() with an empty weekly mask that is a weekly mask of length zero. A log with an empty weekly mask will accept logging during the whole week.
Log generated events
According to the OMG Telecom Log Service specification, event-aware Log factories and logs can generate events on log object creation and deletion, state and attribute change, threshold crossover, and processing error. A value-added extension of the VisiTelcoLog Service allows a BasicLog object to generate these events. These log generated events are called log events. Therefore, in VisiTelcoLog Service, a log factory (Basic, Event, TypedEvent, Notify, or TypedNotify factory) is a CosNotifyChannelAdmin::ConsumerAdmin.
Figure 3
The purpose of LogFactory “is a” ConsumerAdmin is to expose downstream or consumer-side functionality of an event channel inside each log factory. This event channel is called a log event channel. Log events generated from a log factory and from its logs are all sent to the log event channel of this factory. To receive log events an application can create consumer-side proxies on the log factory through its operations inherited from ConsumerAdmin and connect to these proxies.
The following C++ code (also located in <install_dir>/examples/vbe/telcolog/primitive_cpp/logEventReceiver.C) illustrates how to connect an event consumer to log event channel of a NotifyLogFactory:
int main(int argc, char** argv)
{
CORBA::ORB_ptr orb = CORBA::ORB_init(argc, argv);

// get service reference (the Notify Log Factory)
CORBA::Object_var service
= orb->resolve_initial_references(
"NotifyLogService");

// directly narrow the factory to consumer admin.
CosNotifyChannelAdmin::ConsumerAdmin_var admin
= CosNotifyChannelAdmin::ConsumerAdmin
::_narrow(service);

CosNotifyChannelAdmin::ProxyID proxy_id;

// create a proxy
CosNotifyChannelAdmin::ProxySupplier_var proxy
= admin->obtain_notification_push_supplier(
CosNotifyChannelAdmin::ANY_EVENT, proxy_id);

CosNotifyChannelAdmin::ProxyPushSupplier_var supplier;
supplier = CosNotifyChannelAdmin::ProxyPushSupplier
::_narrow(proxy);

// allocate the consumer implementation
PushConsumerImpl* servant = new PushConsumerImpl;

// activate it on root poa
CORBA::Object_var obj
= orb->resolve_initial_references("RootPOA");
PortableServer::POA_var poa
= PortableServer::POA::_narrow(obj);
poa->activate_object(servant);

// activate the root poa
PortableServer::POAManager_var poa_manager
= poa->the_POAManager();
poa_manager->activate();

// get consumer object reference
CORBA::Object_var ref
= poa->servant_to_reference(servant);
CosNotifyComm::PushConsumer_var consumer =
CosNotifyComm::PushConsumer::_narrow(ref);

// connect the consumer to the supplier proxy
supplier->connect_any_push_consumer(consumer);

cout << "log event receiver is ready" << endl;

// work loop
orb->run();
}
catch(CORBA::Exception& e) {
cout << "caught exception:" << endl << e << endl;
}

return 0;
}
 
 
The following Java code illustrates how to connect an event consumer to a log event channel of a NotifyLogFactory:
import org.omg.CosNotifyChannelAdmin.*;
import org.omg.PortableServer.*;
import org.omg.CosNotifyComm.*;

public class logEventReceiver {

public static void main(String[] args) {
try {
org.omg.CORBA.ORB orb
= org.omg.CORBA.ORB.init(args, null);

// get service reference (the Notify Log Factory)
org.omg.CORBA.Object service
= orb.resolve_initial_references(
"NotifyLogService");

// directly narrow factory to a consumer admin.
ConsumerAdmin admin
= ConsumerAdminHelper.narrow(service);

org.omg.CORBA.IntHolder proxy_id
= new org.omg.CORBA.IntHolder();

// create a proxy
ProxySupplier proxy
= admin.obtain_notification_push_supplier(
ClientType.ANY_EVENT, proxy_id);
ProxyPushSupplier supplier
= ProxyPushSupplierHelper.narrow(proxy);

// allocate the consumer implementation
PushConsumerImpl servant = new PushConsumerImpl();

// activate it on root poa
org.omg.CORBA.Object obj
= orb.resolve_initial_references("RootPOA");
POA poa = POAHelper.narrow(obj);
poa.activate_object(servant);

// activate the root poa
POAManager poa_manager = poa.the_POAManager();
poa_manager.activate();

// get consumer object reference
org.omg.CORBA.Object ref
= poa.servant_to_reference(servant);
PushConsumer consumer
= PushConsumerHelper.narrow(ref);

// connect the consumer to the supplier proxy
supplier.connect_any_push_consumer(consumer);

System.out.println("untyped push consumer is ready");

// work loop
orb.run();
} catch(Exception e) {
e.printStackTrace();
}
}
}
Possible log events and their meanings have been specified by OMG as described in the following sections.
Object Creation Event
This event is emitted from a log factory itself on a successful log object creation. The new log ID and the log creation time is encapsulated in the CORBA Any event body as an IDL structure defined as:
module DsNotification {
struct ObjectCreation
{
LogId id;
TimeT time;
};
};
Object Deletion Event
This event is emitted from a log factory itself on a successful log object deletion. The deleted log ID and the log deletion time is encapsulated in the CORBA Any event body as an IDL structure defined as:
module DsNotification {
struct ObjectDeletion
{
LogId id;
TimeT time;
};
};
Attribute Value Change (AVC) Event
This event is emitted from a log on a successful log attribute value change. Information about the attribute value change is encapsulated in the CORBA Any event body as an IDL structure defined as:
module DsNotification {
struct AttributeValueChange
{
Log logref;
LogId id;
TimeT time;
AttributeType type;
Any old_value;
Any new_value;
};
};
In this structure
logref is the reference of the log object itself.
id is the log ID of the log object.
time is the time the attribute value change was made.
type indicates the type of the changed attribute. See discussion below.
old_value encapsulates the original value of the attribute before the change.
new_value encapsulates the new value of the attribute after the change.
OMG specifies following attribute types of log object:
This type of AVC event is triggered by a successful set_capacity_thresholds() invocation on a log object and changes its previous capacity alarm threshold setting.
This type of AVC event is triggered by a successful set_full_action() invocation on a log object and changes its previous log full action setting.
This type of AVC event is triggered by a successful set_max_size() invocation on a log object and changes its previous log max size setting.
This type of AVC event is triggered by a successful set_interval() invocation on a log object and changes its log interval start time setting.
This type of AVC event is triggered by a successful set_interval() invocation on a log object and changes its log interval stop time setting.
This type of AVC event is triggered by a successful set_week_mask() invocation on a log object.
This type of AVC event is triggered by a successful set_filter() invocation on a log object and changes its filter.
This type of AVC event is triggered by a successful set_max_record_life() invocation on a log object and changes its max record life setting.
This type of AVC event is triggered by a successful set_log_qos() invocation on a log object and changes its log QoS setting.
State Change Event
This event is emitted from a log on OMG specified log state change. Information about the state change is encapsulated in the CORBA Any event body as an IDL structure defined as:
module DsNotification {
struct StateChange
{
Log logref;
LogId id;
TimeT time;
StateType type;
Any new_value;
};
};
In this structure
logref is the reference of the log object itself.
id is the log id of the log object.
time is the time of the state change.
type indicates the type of the changed state. See discussion below.
new_value encapsulates the new state value after the change.
OMG specifies the following state change event types for a log object:
This type of state change event is triggered by a successful set_administrative_state() invocation on a log object and changes its administrative state, allowing or disallowing log record write operations (insert, update, delete, etc.).
This type of state change event is triggered by a successful set_forwarding_state() invocation on a log object and changes its forwarding state, which enables or disables event forwarding.
Threshold Alarm Event
This event is emitted from a log object when a log write operation causes the log to grow beyond its size threshold. Information about the attribute value change is encapsulated in the CORBA Any event body as an IDL structure defined as:
module DsNotification {
struct ThresholdAlarm
{
Log logref;
LogId id;
TimeT time;
Threshold crossed_value;
Threshold observed_value;
PerceivedSeverityType perceived_severity;
};
};
In this structure
logref is the reference of the log object itself.
id is the log ID of the log object.
time is the time of the occurrence.
crossed_value the threshold value just being crossed.
observed_value the current log space usage percentage.
perceived_severity critical(0), minor(1) and cleared(2).
Processing Error Alarm Event
This event is emitted from a log factory or a log object when a problem occurs within the factory or log object. Information about the attribute value change is encapsulated in the CORBA Any event body as an IDL structure defined as:
module DsNotification {
struct ProcessingErrorAlarm
{
long error_num;
string error_string;
};
};
In this structure
error_num is the highest 20 bits of this field which are reserved for vendor-specific error ids.
error_string is the text string that explains the error.