Statistics
| Branch: | Revision:

root / src / envir / fileoutvectormgr.cc @ 68da4f12

History | View | Annotate | Download (6.77 KB)

1 01873262 Georg Kunz
//==========================================================================
2
//  FILEOUTPUTVECTORMGR.CC - part of
3
//                     OMNeT++/OMNEST
4
//            Discrete System Simulation in C++
5
//
6
//  Author: Andras Varga
7
//
8
//==========================================================================
9
10
/*--------------------------------------------------------------*
11
  Copyright (C) 1992-2008 Andras Varga
12
  Copyright (C) 2006-2008 OpenSim Ltd.
13

14
  This file is distributed WITHOUT ANY WARRANTY. See the file
15
  `license' for details on this and other legal matters.
16
*--------------------------------------------------------------*/
17
18
#include "simkerneldefs.h"
19
20
#include <assert.h>
21
#include <string.h>
22
#include <fstream>
23
#include "opp_ctype.h"
24
#include "cconfigoption.h"
25
#include "fileutil.h"
26
#include "timeutil.h"
27
#include "platmisc.h"
28
#include "envirbase.h"
29
#include "csimulation.h"
30
#include "cmodule.h"
31
#include "fileoutvectormgr.h"
32
#include "ccomponenttype.h"
33
#include "stringutil.h"
34
35
USING_NAMESPACE
36
37
Register_Class(cFileOutputVectorManager);
38
39
#define VECTOR_FILE_VERSION 2
40
#define DEFAULT_PRECISION  "14"
41
42
#define LL  INT64_PRINTF_FORMAT
43
44
Register_PerRunConfigOption(CFGID_OUTPUT_VECTOR_FILE, "output-vector-file", CFG_FILENAME, "${resultdir}/${configname}-${runnumber}.vec", "Name for the output vector file.");
45
Register_PerRunConfigOption(CFGID_OUTPUT_VECTOR_PRECISION, "output-vector-precision", CFG_INT, DEFAULT_PRECISION, "The number of significant digits for recording data into the output vector file. The maximum value is ~15 (IEEE double precision). This setting has no effect on the \"time\" column of output vectors, which are represented as fixed-point numbers and always get recorded precisely.");
46
47
Register_PerObjectConfigOption(CFGID_VECTOR_RECORDING, "vector-recording", CFG_BOOL, "true", "Whether data written into an output vector should be recorded.");
48
Register_PerObjectConfigOption(CFGID_VECTOR_RECORD_EVENTNUMBERS, "vector-record-eventnumbers", CFG_BOOL, "true", "Whether to record event numbers for an output vector. Simulation time and value are always recorded. Event numbers are needed by the Sequence Chart Tool, for example.");
49
Register_PerObjectConfigOption(CFGID_VECTOR_RECORDING_INTERVALS, "vector-recording-intervals", CFG_CUSTOM, NULL, "Recording interval(s) for an output vector. Syntax: [<from>]..[<to>],... That is, both start and end of an interval are optional, and intervals are separated by comma. Example: ..100, 200..400, 900..");
50
51
#ifdef CHECK
52
#undef CHECK
53
#endif
54
#define CHECK(fprintf)    if (fprintf<0) throw cRuntimeError("Cannot write output vector file `%s'", fname.c_str())
55
56
57
cFileOutputVectorManager::cFileOutputVectorManager()
58
{
59
    nextid = 0;
60
    f = NULL;
61
    prec = ev.getConfig()->getAsInt(CFGID_OUTPUT_VECTOR_PRECISION);
62
}
63
64
cFileOutputVectorManager::~cFileOutputVectorManager()
65
{
66
    closeFile();
67
}
68
69
void cFileOutputVectorManager::openFile()
70
{
71
    mkPath(directoryOf(fname.c_str()).c_str());
72
    f = fopen(fname.c_str(),"a");
73
    if (f==NULL)
74
        throw cRuntimeError("Cannot open output vector file `%s'",fname.c_str());
75
}
76
77
void cFileOutputVectorManager::closeFile()
78
{
79
    if (f)
80
    {
81
        fclose(f);
82
        f = NULL;
83
    }
84
}
85
86
void cFileOutputVectorManager::writeRunData()
87
{
88
    run.initRun();
89
    run.writeRunData(f, fname);
90
}
91
92
void cFileOutputVectorManager::initVector(sVectorData *vp)
93
{
94
    if (!f)
95
    {
96
        openFile();
97
        if (!f) return;
98
99
        CHECK(fprintf(f, "version %d\n", VECTOR_FILE_VERSION));
100
    }
101
102
    if (!run.initialized)
103
    {
104
        // this is the first vector written in this run, write out run attributes
105
        writeRunData();
106
    }
107
108
    CHECK(fprintf(f,"vector %d  %s  %s  %s\n",
109
                  vp->id, QUOTE(vp->modulename.c_str()), QUOTE(vp->vectorname.c_str()), vp->getColumns()));
110
    for (opp_string_map::iterator it=vp->attributes.begin(); it!=vp->attributes.end(); it++)
111
        CHECK(fprintf(f,"attr %s  %s\n", QUOTE(it->first.c_str()), QUOTE(it->second.c_str())));
112
113
    vp->initialized = true;
114
}
115
116
void cFileOutputVectorManager::startRun()
117
{
118
    // clean up file from previous runs
119
    closeFile();
120
    fname = ev.getConfig()->getAsFilename(CFGID_OUTPUT_VECTOR_FILE).c_str();
121
    dynamic_cast<EnvirBase *>(&ev)->processFileName(fname);
122
    removeFile(fname.c_str(), "old output vector file");
123
124
    // clear run data
125
    run.reset();
126
}
127
128
void cFileOutputVectorManager::endRun()
129
{
130
    closeFile();
131
}
132
133
void cFileOutputVectorManager::getOutVectorConfig(const char *modname,const char *vecname,
134
                                                  bool& outEnabled, bool& outRecordEventNumbers,
135
                                                  Intervals& outIntervals)
136
{
137
    std::string vectorfullpath = std::string(modname) + "." + vecname;
138
    outEnabled = ev.getConfig()->getAsBool(vectorfullpath.c_str(), CFGID_VECTOR_RECORDING);
139
    outRecordEventNumbers = ev.getConfig()->getAsBool(vectorfullpath.c_str(), CFGID_VECTOR_RECORD_EVENTNUMBERS);
140
141
    // get interval string
142
    const char *text = ev.getConfig()->getAsCustom(vectorfullpath.c_str(), CFGID_VECTOR_RECORDING_INTERVALS);
143
    if (text)
144
        outIntervals.parse(text);
145
}
146
147
void *cFileOutputVectorManager::registerVector(const char *modulename, const char *vectorname)
148
{
149
    sVectorData *vp = createVectorData();
150
    vp->id = nextid++;
151
    vp->initialized = false;
152
    vp->modulename = modulename;
153
    vp->vectorname = vectorname;
154
    getOutVectorConfig(modulename, vectorname, vp->enabled, vp->recordEventNumbers, vp->intervals);
155
    return vp;
156
}
157
158
cFileOutputVectorManager::sVectorData *cFileOutputVectorManager::createVectorData()
159
{
160
    return new sVectorData;
161
}
162
163
void cFileOutputVectorManager::deregisterVector(void *vectorhandle)
164
{
165
    ASSERT(vectorhandle!=NULL);
166
    sVectorData *vp = (sVectorData *)vectorhandle;
167
    delete vp;
168
}
169
170
void cFileOutputVectorManager::setVectorAttribute(void *vectorhandle, const char *name, const char *value)
171
{
172
    ASSERT(vectorhandle!=NULL);
173
    sVectorData *vp = (sVectorData *)vectorhandle;
174
    vp->attributes[name] = value;
175
}
176
177
bool cFileOutputVectorManager::record(void *vectorhandle, simtime_t t, double value)
178
{
179
    static char buff[64];
180
181
    ASSERT(vectorhandle!=NULL);
182
    sVectorData *vp = (sVectorData *)vectorhandle;
183
184
    if (!vp->enabled)
185
        return false;
186
187
    if (vp->intervals.contains(t))
188
    {
189
        if (!vp->initialized)
190
            initVector(vp);
191
192
        assert(f!=NULL);
193
        if (vp->recordEventNumbers)
194
        {
195
            CHECK(fprintf(f,"%d\t%"LL"d\t%s\t%.*g\n", vp->id, simulation.getEventNumber(), SIMTIME_TTOA(buff, t), prec, value));
196
        }
197
        else
198
        {
199
            CHECK(fprintf(f,"%d\t%s\t%.*g\n", vp->id, SIMTIME_TTOA(buff, t), prec, value));
200
        }
201
        return true;
202
    }
203
    return false;
204
}
205
206
const char *cFileOutputVectorManager::getFileName() const
207
{
208
    return fname.c_str();
209
}
210
211
void cFileOutputVectorManager::flush()
212
{
213
    if (f)
214
        fflush(f);
215
}
216
217