00001
00025 #include <stdlib.h>
00026 #include <stdio.h>
00027 #include <errno.h>
00028
00029 #include "metrics.h"
00030 #include "eventgen.h"
00031
00032 CLASS *eventgen::oclass = NULL;
00033 eventgen *eventgen::defaults = NULL;
00035 static PASSCONFIG passconfig = PC_PRETOPDOWN;
00036 static PASSCONFIG clockpass = PC_PRETOPDOWN;
00037
00038
00039 eventgen::eventgen(MODULE *module)
00040 {
00041 if (oclass==NULL)
00042 {
00043 oclass = gl_register_class(module,"eventgen",sizeof(eventgen),passconfig);
00044 if (oclass==NULL)
00045 GL_THROW("unable to register object class implemented by %s", __FILE__);
00046
00047 if (gl_publish_variable(oclass,
00048 PT_char256, "group", PADDR(group),
00049 PT_char256, "targets", PADDR(targets),
00050 PT_double, "frequency[1/yr]", PADDR(frequency),
00051 PT_double, "duration[s]", PADDR(duration),
00052 PT_char256, "values", PADDR(values),
00053 NULL)<1) GL_THROW("unable to publish properties in %s",__FILE__);
00054 defaults = this;
00055 memset(defaults,0,sizeof(eventgen));
00056 }
00057 }
00058
00059
00060 int eventgen::create(void)
00061 {
00062 memcpy(this,defaults,sizeof(eventgen));
00063 return 1;
00064 }
00065
00066
00067 int eventgen::init(OBJECT *parent)
00068 {
00069 objectlist = gl_find_objects(FL_GROUP,group);
00070 if (objectlist==NULL)
00071 gl_error("eventgen:%d group '%s' is empty", OBJECTHDR(this)->id, group);
00072 if (strcmp(parent->oclass->name,"metrics")!=0)
00073 gl_error("eventgen:%d parent must be a metrics object", OBJECTHDR(this)->id);
00074 if (duration<=1)
00075 gl_error("eventgen:%d duration must be greater than 1", OBJECTHDR(this)->id);
00076 return 1;
00077 }
00078
00079
00080 TIMESTAMP eventgen::presync(TIMESTAMP t0, TIMESTAMP t1)
00081 {
00082 TIMESTAMP t2 = TS_NEVER;
00083 metrics *pMetrics = (metrics*)OBJECTDATA(OBJECTHDR(this)->parent,metrics);
00084 EVENT *pEvent = pMetrics->get_event();
00085 if (pEvent==NULL)
00086 {
00087 MakeAnother:
00088 pEvent = new EVENT;
00089 pMetrics->add_event(pEvent);
00090 pEvent->event_time = t1 + (TIMESTAMP)(gl_random_exponential(1/(1/frequency*86400*365.24))*TS_SECOND);
00091 do {
00092 pEvent->ri = gl_random_pareto(1,1/(duration-1));
00093 } while (pEvent->ri>86400*5);
00094 t2 = pEvent->event_time;
00095 DATETIME dt;
00096 char buffer[64];
00097 gl_localtime(t2,&dt);
00098 if (gl_strtime(&dt,buffer,sizeof(buffer)))
00099 gl_verbose("event group '%s' will occur at %s", group, buffer);
00100 else
00101 gl_verbose("event group '%s' is scheduled to occur at an invalid time (t=%"FMT_INT64"d)", t2);
00102 }
00103 else if (event_object)
00104 {
00105 if (t1>=pEvent->event_time+(TIMESTAMP)(pEvent->ri*TS_SECOND))
00106 {
00107 pMetrics->end_event(event_object,targets,old_values);
00108 event_object = NULL;
00109 goto MakeAnother;
00110 }
00111 else
00112 t2 = pEvent->event_time+(TIMESTAMP)(pEvent->ri)*TS_SECOND;
00113 }
00114 else if (t1>=pEvent->event_time)
00115 {
00116 event_object = pMetrics->start_event(pEvent,objectlist,targets,values,old_values,sizeof(old_values));
00117 if (event_object)
00118 {
00119 gl_verbose("event lasts %.1f seconds", pEvent->ri);
00120 t2 = t1 + (TIMESTAMP)(pEvent->ri*TS_SECOND);
00121 }
00122 else
00123 {
00124 gl_error("unable to implement event!");
00125 pMetrics->del_event();
00126 delete pEvent;
00127 }
00128 }
00129 else
00130 {
00131 t2 = pEvent->event_time;
00132 }
00133 return -t2;
00134 }
00135
00137
00139
00140 EXPORT int create_eventgen(OBJECT **obj, OBJECT *parent)
00141 {
00142 try
00143 {
00144 *obj = gl_create_object(eventgen::oclass);
00145 if (*obj!=NULL)
00146 {
00147 eventgen *my = OBJECTDATA(*obj,eventgen);
00148 gl_set_parent(*obj,parent);
00149 return my->create();
00150 }
00151 }
00152 catch (char *msg)
00153 {
00154 gl_error("create_eventgen: %s", msg);
00155
00156 }
00157 return 1;
00158 }
00159
00160 EXPORT int init_eventgen(OBJECT *obj, OBJECT *parent)
00161 {
00162 try
00163 {
00164 if (obj!=NULL)
00165 return OBJECTDATA(obj,eventgen)->init(parent);
00166 }
00167 catch (char *msg)
00168 {
00169 gl_error("init_eventgen(obj=%d;%s): %s", obj->id, obj->name?obj->name:"unnamed", msg);
00170 }
00171 return 1;
00172 }
00173
00174 EXPORT TIMESTAMP sync_eventgen(OBJECT *obj, TIMESTAMP t1, PASSCONFIG pass)
00175 {
00176 TIMESTAMP t2 = TS_NEVER;
00177 eventgen *my = OBJECTDATA(obj,eventgen);
00178 try
00179 {
00180 switch (pass) {
00181 case PC_PRETOPDOWN:
00182 t2 = my->presync(obj->clock,t1);
00183 if ((t2<0?-t2:t2)<=t1)
00184 gl_warning("eventgen did not advanced the clock!");
00185 break;
00186 default:
00187 GL_THROW("invalid pass request (%d)", pass);
00188 break;
00189 }
00190 if (pass==clockpass)
00191 obj->clock = t1;
00192 }
00193 catch (char *msg)
00194 {
00195 gl_error("sync_eventgen(obj=%d;%s): %s", obj->id, obj->name?obj->name:"unnamed", msg);
00196 }
00197 return t2;
00198 }
00199