tape/player.c

Go to the documentation of this file.
00001 
00034 #include <stdlib.h>
00035 #include <stdio.h>
00036 #include <errno.h>
00037 #include <ctype.h>
00038 #include "gridlabd.h"
00039 #include "object.h"
00040 #include "aggregate.h"
00041 
00042 #include "tape.h"
00043 #include "file.h"
00044 #include "odbc.h"
00045 
00046 CLASS *player_class = NULL;
00047 static OBJECT *last_player = NULL;
00048 
00049 EXPORT int create_player(OBJECT **obj, OBJECT *parent)
00050 {
00051     *obj = gl_create_object(player_class,sizeof(struct player));
00052     if (*obj!=NULL)
00053     {
00054         struct player *my = OBJECTDATA(*obj,struct player);
00055         last_player = *obj;
00056         gl_set_parent(*obj,parent);
00057         strcpy(my->file,"");
00058         strcpy(my->filetype,"txt");
00059         strcpy(my->property,"(undefined)");
00060         my->next.ts = TS_ZERO;
00061         strcpy(my->next.value,"");
00062         my->loopnum = 0;
00063         my->loop = 0;
00064         my->status = TS_INIT;
00065         my->target = gl_get_property(*obj,my->property);
00066         return 1;
00067     }
00068     return 0;
00069 }
00070 
00071 static int player_open(OBJECT *obj)
00072 {
00073     char32 type="file";
00074     char1024 fname="";
00075     char32 flags="r";
00076     struct player *my = OBJECTDATA(obj,struct player);
00077     
00078     /* if prefix is omitted (no colons found) */
00079     if (sscanf(my->file,"%32[^:]:%1024[^:]:%[^:]",type,fname,flags)==1)
00080     {
00081         /* filename is file by default */
00082         strcpy(fname,my->file);
00083         strcpy(type,"file");
00084     }
00085 
00086     /* if no filename given */
00087     if (strcmp(fname,"")==0)
00088 
00089         /* use object name-id as default file name */
00090         sprintf(fname,"%s-%d.%s",obj->parent->oclass->name,obj->parent->id, my->filetype);
00091 
00092     /* if type is file or file is stdin */
00093     my->ops = get_ftable(type)->player;
00094     if(my->ops == NULL)
00095         return 0;
00096     else return (my->ops->open)(my, fname, flags);
00097 }
00098 
00099 static void rewind_player(struct player *my)
00100 {
00101     (*my->ops->rewind)(my);
00102 }
00103 
00104 static void close_player(struct player *my)
00105 {
00106     (my->ops->close)(my);
00107 }
00108 
00109 static TIMESTAMP player_read(OBJECT *obj)
00110 {
00111     char buffer[64];
00112     int Y,m,d,H,M,S;
00113     struct player *my = OBJECTDATA(obj,struct player);
00114     char unit[2];
00115     TIMESTAMP t1;
00116     char *result=NULL;
00117 Retry:
00118     result = my->ops->read(my, buffer, sizeof(buffer));
00119 
00120     if (result==NULL)
00121     {
00122         if (my->loopnum>0)
00123         {
00124             rewind_player(my);
00125             my->loopnum--;
00126             goto Retry;
00127         }
00128         else {
00129             close_player(my);
00130             my->status=TS_DONE;
00131             my->next.ts = TS_NEVER;
00132             goto Done;
00133         }
00134     }
00135     if (result[0]=='#' || result[0]=='\n') /* ignore comments and blank lines */
00136         goto Retry;
00137     if (sscanf(result,"%" FMT_INT64 "d,%31[^\n]", &t1,my->next.value)==2)
00138     {
00139         if (my->loop==my->loopnum) 
00140             my->next.ts = t1;
00141     }
00142     else if (sscanf(result,"%" FMT_INT64 "d%1[^,],%31[^\n]", &t1, unit, my->next.value)==3)
00143     {
00144         {
00145             int64 scale=1;
00146             switch(unit[0]) {
00147             case 's': scale=TS_SECOND; break;
00148             case 'm': scale=60*TS_SECOND; break;
00149             case 'h': scale=3600*TS_SECOND; break;
00150             case 'd': scale=86400*TS_SECOND; break;
00151             default: break;
00152             }
00153             t1 *= scale; 
00154             if (result[0]=='+') /* timeshifts have leading + */
00155                 my->next.ts += t1;
00156             else if (my->loop==my->loopnum) /* absolute times are ignored on all but first loops */
00157                 my->next.ts = t1;
00158         }
00159     }
00160     else if (sscanf(result,"%d-%d-%d %d:%d:%d,%31[^\n]",&Y,&m,&d,&H,&M,&S,my->next.value)==7)
00161     {
00162         struct tm dt = {S,M,H,d,m-1,Y-1900,0,0,0};
00163         t1 = (TIMESTAMP)mktime(&dt);
00164         if (t1!=TS_INVALID && my->loop==my->loopnum)
00165             my->next.ts = t1;
00166     }
00167 Done:
00168     return my->next.ts;
00169 }
00170 
00171 EXPORT TIMESTAMP sync_player(OBJECT *obj, TIMESTAMP t0, PASSCONFIG pass)
00172 {
00173     struct player *my = OBJECTDATA(obj,struct player);
00174     TIMESTAMP t1 = my->next.ts;
00175     if (my->status==TS_INIT && player_open(obj))
00176         t1 = player_read(obj);
00177     while (my->status==TS_OPEN && t1<=t0)
00178     {   /* post this value */
00179         if (my->target==NULL)
00180             my->target = gl_get_property(obj->parent,my->property);
00181         if (my->target!=NULL)
00182             gl_set_value(obj->parent,GETADDR(obj->parent,my->target),my->next.value,my->target); /* pointer => int64 */
00183         t1 = player_read(obj);
00184     }
00185     obj->clock = t0;
00186     return t1;
00187 }
00188 

GridLAB-DTM Version 1.0
An open-source project initiated by the US Department of Energy