source: Sophya/trunk/SophyaLib/HiStats/swppfdtable.cc@ 4064

Last change on this file since 4064 was 3392, checked in by ansari, 18 years ago

Implementation NTuple::Fill(), BaseDataTable:;AddRow()/GetRow() thread-safe - Reza 22/11/2007

File size: 11.1 KB
RevLine 
[2696]1#include "swppfdtable.h"
2#include "pexceptions.h"
[3392]3#include "thsafeop.h"
[2696]4
[3392]5namespace SOPHYA {
[2696]6
7/*!
[3392]8 \class SwPPFDataTable
[2696]9 \ingroup HiStats
10 This class can be used to organize data in table (row-column) form.
11 Each column holds homogeneous data (same data type), while different
[2808]12 columns can be used for different data types
13 (integer, float, string ...).
14 A PPF stream is used as swap space. Due to limitations in the current
15 implementation of PPF streams, read operations (acces to table data) cannot
16 be performed when a table is being filled.
17
18 \warning
19 - When creating a table, the output PPF stream (POutPersist) must not be closed
[2831]20 (destroyed) before the SwPPFDataTable object is written to the stream.
21 - It is not possible to make a complete (deep) copy of a SwPPFDataTable
[2808]22 Copy constructor and equal operator shares the data.
[2831]23 - The destructor DOES NOT save the table object itself to the swap
24 stream. The << operator should be used on the output PPF stream being
25 used as swap in order to save the table.
[2808]26
[2696]27 \sa SOPHYA::MuTyV
[2849]28 \sa SOPHYA::DataTableRow
[2808]29 \sa SOPHYA::DataTable
30 \sa SOPHYA::SwSegDataBlock SOPHYA::PPFDataSwapper
[2696]31
32 \code
33 #include "swppfdtable.h"
34 // ...
[2808]35 {
36 // ---- Creation of the table
37 // Create the swap stream
38 POutPersist so("myswtable.ppf");
39 SwPPFDataTable dt(so, 64);
40 // define table columns
[2696]41 dt.AddFloatColumn("X0_f");
42 dt.AddFloatColumn("X1_f");
43 dt.AddDoubleColumn("X0X0pX1X1_d");
[2808]44 // Fill the table
[2891]45 r_8 x[5];
[2696]46 for(int i=0; i<63; i++) {
47 x[0] = (i%9)-4.; x[1] = (i/9)-3.; x[2] = x[0]*x[0]+x[1]*x[1];
[2891]48 dt.AddRow(x);
[2696]49 }
50 // Printing table info
51 cout << dt ;
[2808]52 // Swap out all data and write the table structure to the PPF stream
53 so << dt ;
54 // ....
55 }
56 {
57 // ---- Accessing information from a previously created table
58 SwPPFDataTable dt;
59 PInPersist si("myswtable.ppf");
60 si >> dt;
61 // Printing table info
62 cout << dt ;
63 }
[2696]64 \endcode
65*/
[2808]66//! Default constructor with optional specification of block (or segment) size
[2696]67SwPPFDataTable::SwPPFDataTable(sa_size_t segsz)
68 : BaseDataTable(segsz),
69 mSwOut(NULL), mSwIn(NULL)
70{
71}
72/*! Constructor with the specification of the output swap stream -
73 and optional specification of block (or segment) size
74*/
75SwPPFDataTable::SwPPFDataTable(POutPersist & os, sa_size_t segsz)
76 : BaseDataTable(segsz) ,
[2699]77 mSwOut(&os), mSwIn(NULL),
[2827]78 mISwapper(os), mLSwapper(os), mFSwapper(os), mDSwapper(os),
79 mYSwapper(os), mZSwapper(os), mSSwapper(os)
[2696]80{
81}
82//! Protected constructor for creation from a swap stream
83SwPPFDataTable::SwPPFDataTable(PInPersist & is, sa_size_t segsz)
84 : BaseDataTable(segsz) ,
[2699]85 mSwOut(NULL), mSwIn(NULL)
[2696]86{
[2699]87 PInPersist* pis = new PInPersist(is.FileName(), false);
88 mSwIn = new St_InSwap;
89 mSwIn->pis = pis; mSwIn->refcnt = 1;
90 mISwapper.SetInStream(*pis);
91 mLSwapper.SetInStream(*pis);
92 mFSwapper.SetInStream(*pis);
93 mDSwapper.SetInStream(*pis);
[2827]94 mYSwapper.SetInStream(*pis);
95 mZSwapper.SetInStream(*pis);
[2831]96 mSSwapper.SetInStream(*pis);
[2696]97}
98
[3392]99//! copy constructor - shares the data (and copies the thread safety state)
100
[2696]101SwPPFDataTable::SwPPFDataTable(SwPPFDataTable const & a)
102 : BaseDataTable(a.SegmentSize()),
103 mSwOut(NULL), mSwIn(NULL)
104{
105 Share(a);
106}
[2699]107//! Destructor - Deletes / closes the input PPF swap stream
108SwPPFDataTable::~SwPPFDataTable()
109{
110 if (mSwIn) {
111 mSwIn->refcnt--;
112 if (mSwIn->refcnt == 0) {
113 delete mSwIn->pis;
114 delete mSwIn;
115 mSwIn = NULL;
116 }
117 }
118}
[2696]119
120void SwPPFDataTable::Share(SwPPFDataTable const & a)
121{
122 // Recopie (attention !) brutale des swappers et les streams associes
123 mISwapper = a.mISwapper;
124 mLSwapper = a.mLSwapper;
125 mFSwapper = a.mFSwapper;
126 mDSwapper = a.mDSwapper;
[2827]127 mYSwapper = a.mYSwapper;
128 mZSwapper = a.mZSwapper;
[2696]129 mSSwapper = a.mSSwapper;
130
131 mSwOut = a.mSwOut;
132 mSwIn = a.mSwIn;
[2699]133 if (mSwIn) mSwIn->refcnt++; // comptage de reference pour le stream input
[2696]134
135 // On recopie la taille de segment
136 mSegSz = a.SegmentSize();
137 if (a.NVar() == 0) return; // Table sans colonne
138
139 // On copie la structure de table
140 CopyStructure(a);
[3392]141 if (a.IsThreadSafe()) SetThreadSafe(true);
142 else SetThreadSafe(false);
[2696]143
144 //
145 // Update nombre d'entree, ...
146 mNEnt = a.mNEnt;
147 mNSeg = a.mNSeg;
148 if (a.mInfo) mInfo = new DVList(*(a.mInfo));
149
150 // mis a jour des tableax min-max
151 mMin = a.mMin;
152 mMax = a.mMax;
153 mMinMaxNEnt = a.mMinMaxNEnt;
154
155 // Et on partage les donnees des colonnes
156 for (size_t kk=0; kk<mNames.size(); kk++) {
157 sa_size_t sk = mNames[kk].ser;
158 sa_size_t ska = a.mNames[kk].ser;
159 switch (mNames[kk].type) {
160 case IntegerField :
161 mICols[sk] = a.mICols[ska];
162 break;
163 case LongField :
164 mLCols[sk] = a.mLCols[ska];
165 break;
166 case FloatField :
167 mFCols[sk] = a.mFCols[ska];
168 break;
169 case DoubleField :
[2831]170 case DateTimeField :
[2696]171 mDCols[sk] = a.mDCols[ska];
172 break;
[2827]173 case ComplexField :
174 mYCols[sk] = a.mYCols[ska];
175 break;
176 case DoubleComplexField :
177 mZCols[sk] = a.mZCols[ska];
178 break;
[2696]179 case StringField :
180 mSCols[sk] = a.mSCols[ska];
181 break;
182 default:
183 throw ForbiddenError("SwPPFDataTable::Share() : unknown column type ");
184 break;
185 }
186 }
187}
188void SwPPFDataTable::SwapOutAll() const
189{
190 // Et on vide les buffers de swap
191 for (size_t kk=0; kk<mNames.size(); kk++) {
192 sa_size_t sk = mNames[kk].ser;
193 switch (mNames[kk].type) {
194 case IntegerField :
195 mICols[sk].SwapOutBuffer();
196 break;
197 case LongField :
198 mLCols[sk].SwapOutBuffer();
199 break;
200 case FloatField :
201 mFCols[sk].SwapOutBuffer();
202 break;
203 case DoubleField :
[2831]204 case DateTimeField :
[2696]205 mDCols[sk].SwapOutBuffer();
206 break;
[2827]207 case ComplexField :
208 mYCols[sk].SwapOutBuffer();
209 break;
210 case DoubleComplexField :
211 mZCols[sk].SwapOutBuffer();
212 break;
[2696]213 case StringField :
214 mSCols[sk].SwapOutBuffer();
215 break;
216 default:
217 throw ForbiddenError("SwPPFDataTable::Share() : unknown column type ");
218 break;
219 }
220 }
221}
222
223void SwPPFDataTable::Clear()
224{
225 if ( (NVar() == 0) && (NEntry() == 0)) return;
226 mNEnt = 0;
227 mNSeg = 0;
228 if (mVarD) delete[] mVarD;
229 mVarD = NULL;
230 if (mVarMTV) delete[] mVarMTV;
231 mVarMTV = NULL;
232 mNames.clear();
233 if (mInfo) delete mInfo;
234 mInfo = NULL;
[3392]235 if (mThS) delete mThS;
236 mThS = NULL;
[2696]237 mMin.clear();
238 mMax.clear();
239 mMinMaxNEnt.clear();
240 mIColsP.clear();
241 mLColsP.clear();
242 mFColsP.clear();
243 mDColsP.clear();
[2827]244 mYColsP.clear();
245 mZColsP.clear();
[2696]246 mSColsP.clear();
247
248 mIColIdx.clear();
249 mLColIdx.clear();
250 mFColIdx.clear();
251 mDColIdx.clear();
[2827]252 mYColIdx.clear();
253 mZColIdx.clear();
[2696]254 mSColIdx.clear();
255
256 mICols.clear();
257 mLCols.clear();
258 mFCols.clear();
259 mDCols.clear();
[2827]260 mYCols.clear();
261 mZCols.clear();
[2696]262 mSCols.clear();
263}
264
265
[2808]266/*!
267 Implements the action defined in the BaseDataTable interface.
268 In the current implementation, throws an exception (ParmError)
269 if the table contains some data already.
270*/
[2696]271sa_size_t SwPPFDataTable::AddColumn(FieldType ft, string const & cnom)
272{
273 if (NEntry() > 0)
274 throw ParmError("SwPPFDataTable::AddColumn() Table contains already data ");
275 CheckColName(cnom);
276 sa_size_t ser;
277 sa_size_t idx = NVar();
278 switch (ft) {
279 case IntegerField :
280 ser = mICols.size();
281 mICols.push_back(SwSegDataBlock<int_4>(mISwapper, mSegSz));
282 mIColIdx.push_back(idx);
283 mIColsP.push_back(NULL);
284 for(sa_size_t kk=0; kk<mICols.size(); kk++)
285 mIColsP[kk] = &(mICols[kk]);
286 break;
287 case LongField :
288 ser = mLCols.size();
289 mLCols.push_back(SwSegDataBlock<int_8>(mLSwapper, mSegSz));
290 mLColIdx.push_back(idx);
291 mLColsP.push_back(NULL);
292 for(sa_size_t kk=0; kk<mLCols.size(); kk++)
293 mLColsP[kk] = &(mLCols[kk]);
294 break;
295 case FloatField :
296 ser = mFCols.size();
297 mFCols.push_back(SwSegDataBlock<r_4>(mFSwapper, mSegSz));
298 mFColIdx.push_back(idx);
299 mFColsP.push_back(NULL);
300 for(sa_size_t kk=0; kk<mFCols.size(); kk++)
301 mFColsP[kk] = &(mFCols[kk]);
302 break;
303 case DoubleField :
[2831]304 case DateTimeField :
[2696]305 ser = mDCols.size();
306 mDCols.push_back(SwSegDataBlock<r_8>( mDSwapper,mSegSz));
307 mDColIdx.push_back(idx);
308 mDColsP.push_back(NULL);
309 for(sa_size_t kk=0; kk<mDCols.size(); kk++)
310 mDColsP[kk] = &(mDCols[kk]);
311 break;
[2827]312 case ComplexField :
313 ser = mYCols.size();
314 mYCols.push_back(SwSegDataBlock< complex<r_4> >(mYSwapper, mSegSz));
315 mYColIdx.push_back(idx);
316 mYColsP.push_back(NULL);
317 for(sa_size_t kk=0; kk<mYCols.size(); kk++)
318 mYColsP[kk] = &(mYCols[kk]);
319 break;
320 case DoubleComplexField :
321 ser = mZCols.size();
322 mZCols.push_back(SwSegDataBlock< complex<r_8> >(mZSwapper, mSegSz));
323 mZColIdx.push_back(idx);
324 mZColsP.push_back(NULL);
325 for(sa_size_t kk=0; kk<mZCols.size(); kk++)
326 mZColsP[kk] = &(mZCols[kk]);
327 break;
[2696]328 case StringField :
[2831]329 ser = mSCols.size();
[2696]330 mSCols.push_back(SwSegDataBlock<string>(mSSwapper, mSegSz));
331 mSColIdx.push_back(idx);
332 mSColsP.push_back(NULL);
333 for(sa_size_t kk=0; kk<mSCols.size(); kk++)
334 mSColsP[kk] = &(mSCols[kk]);
335 break;
336 default:
337 throw ParmError("SwPPFDataTable::AddColumn() unknown field type ");
338 break;
339 }
340 colst col;
341 col.nom = cnom;
342 col.type = ft;
343 col.ser = ser;
344 mNames.push_back(col);
345 // On est oblige de calculer les min-max lors du remplissage
346 // On ne peut pas en effet 'relire' le swap pendant l'ecriture
[2831]347 mMin.push_back(9.E39);
348 mMax.push_back(-9.E39);
[2696]349 mMinMaxNEnt.push_back(0);
350
351 return NVar();
352}
353
[2891]354//! Adds a row (or line to the table) with r_8* input data.
[2808]355/*!
356 The min/max values for each column is updated, in addition
[2891]357 to the actions performed by the base class AddRow()
[2808]358*/
[2891]359sa_size_t SwPPFDataTable::AddRow(const r_8* data)
[2696]360{
361 // On est oblige de calculer les min-max lors du remplissage
362 // On ne peut pas en effet 'relire' le swap pendant l'ecriture
[3392]363 if (mThS) mThS->lock(); // tread-safety
[2696]364 for(sa_size_t k=0; k<NVar(); k++) {
365 double x = data[k];
366 if (x < mMin[k]) mMin[k] = x;
367 if (x > mMax[k]) mMax[k] = x;
368 mMinMaxNEnt[k]++;
369 }
[3392]370 if (mThS) mThS->unlock(); // tread-safety
[2891]371 return BaseDataTable::AddRow(data);
[2696]372}
373
[2891]374//! Adds a row (or line to the table) with input data as an array of MuTyV
[2808]375/*!
376 The min/max values for each column is updated, in addition
[3031]377 to the actions performed by the base class AddRow()
[2808]378*/
[2891]379sa_size_t SwPPFDataTable::AddRow(const MuTyV * data)
[2696]380{
381 // On est oblige de calculer les min-max lors du remplissage
382 // On ne peut pas en effet 'relire' le swap pendant l'ecriture
[3392]383 if (mThS) mThS->lock(); // tread-safety
[2696]384 for(sa_size_t k=0; k<NVar(); k++) {
385 double x = (double)data[k];
386 if (x < mMin[k]) mMin[k] = x;
387 if (x > mMax[k]) mMax[k] = x;
388 mMinMaxNEnt[k]++;
389 }
[3392]390 if (mThS) mThS->unlock(); // tread-safety
[2891]391 return BaseDataTable::AddRow(data);
[2696]392}
393
[3031]394
395//! Adds a row (or line) to the table with input data as DataTableRow object
396/*!
397 The min/max values for each column is updated, in addition
398 to the actions performed by the base class AddRow()
399*/
400sa_size_t SwPPFDataTable::AddRow(DataTableRow const& data)
401{
402 if ( data.Size() != NCols() )
403 throw SzMismatchError(" SwPPFDataTable::AddRow() - data.Size() != NCols() ");
404 return AddRow(data.MTVPtr());
405}
[3392]406
407} // FIN namespace SOPHYA
Note: See TracBrowser for help on using the repository browser.