Retro68/binutils/gprofng/src/Table.cc
Wolfgang Thaller f485e125c4 binutils 2.39
2022-10-27 20:45:45 +02:00

1688 lines
30 KiB
C++

/* Copyright (C) 2021 Free Software Foundation, Inc.
Contributed by Oracle.
This file is part of GNU Binutils.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
#include "config.h"
#include <stdio.h>
#include "IndexMap2D.h"
#include "DbeSession.h"
#include "FilterExp.h"
#include "Table.h"
#include "util.h"
#include "i18n.h"
char *
get_prof_data_type_name (int t)
{
switch (t)
{
case DATA_SAMPLE: return NTXT("PROFDATA_TYPE_SAMPLE");
case DATA_GCEVENT: return NTXT("PROFDATA_TYPE_GCEVENT");
case DATA_HEAPSZ: return NTXT("PROFDATA_TYPE_HEAPSZ");
case DATA_CLOCK: return NTXT("PROFDATA_TYPE_CLOCK");
case DATA_HWC: return NTXT("PROFDATA_TYPE_HWC");
case DATA_SYNCH: return NTXT("PROFDATA_TYPE_SYNCH");
case DATA_HEAP: return NTXT("PROFDATA_TYPE_HEAP");
case DATA_OMP: return NTXT("PROFDATA_TYPE_OMP");
case DATA_OMP2: return NTXT("PROFDATA_TYPE_OMP2");
case DATA_OMP3: return NTXT("PROFDATA_TYPE_OMP3");
case DATA_OMP4: return NTXT("PROFDATA_TYPE_OMP4");
case DATA_OMP5: return NTXT("PROFDATA_TYPE_OMP5");
case DATA_IOTRACE: return NTXT("PROFDATA_TYPE_IOTRACE");
default: abort ();
return NTXT ("PROFDATA_TYPE_ERROR");
}
}
char *
get_prof_data_type_uname (int t)
{
switch (t)
{
case DATA_SAMPLE: return GTXT("Process-wide Resource Utilization");
case DATA_GCEVENT: return GTXT("Java Garbage Collection Events");
case DATA_HEAPSZ: return GTXT("Heap Size");
case DATA_CLOCK: return GTXT("Clock Profiling");
case DATA_HWC: return GTXT("HW Counter Profiling");
case DATA_SYNCH: return GTXT("Synchronization Tracing");
case DATA_HEAP: return GTXT("Heap Tracing");
case DATA_OMP: return GTXT("OpenMP Profiling");
case DATA_OMP2: return GTXT("OpenMP Profiling");
case DATA_OMP3: return GTXT("OpenMP Profiling");
case DATA_OMP4: return GTXT("OpenMP Profiling");
case DATA_OMP5: return GTXT("OpenMP Profiling");
case DATA_IOTRACE: return GTXT("IO Tracing");
default: abort ();
return NTXT ("PROFDATA_TYPE_ERROR");
}
}
int assert_level = 0; // set to 1 to bypass problematic asserts
#define ASSERT_SKIP (assert_level)
/*
* class PropDescr
*/
PropDescr::PropDescr (int _propID, const char *_name)
{
propID = _propID;
name = strdup (_name ? _name : NTXT (""));
uname = NULL;
vtype = TYPE_NONE;
flags = 0;
stateNames = NULL;
stateUNames = NULL;
}
PropDescr::~PropDescr ()
{
free (name);
free (uname);
if (stateNames)
{
stateNames->destroy ();
delete stateNames;
}
if (stateUNames)
{
stateUNames->destroy ();
delete stateUNames;
}
}
void
PropDescr::addState (int value, const char *stname, const char *stuname)
{
if (value < 0 || stname == NULL)
return;
if (stateNames == NULL)
stateNames = new Vector<char*>;
stateNames->store (value, strdup (stname));
if (stateUNames == NULL)
stateUNames = new Vector<char*>;
stateUNames->store (value, strdup (stuname));
}
char *
PropDescr::getStateName (int value)
{
if (stateNames && value >= 0 && value < stateNames->size ())
return stateNames->fetch (value);
return NULL;
}
char *
PropDescr::getStateUName (int value)
{
if (stateUNames && value >= 0 && value < stateUNames->size ())
return stateUNames->fetch (value);
return NULL;
}
/*
* class FieldDescr
*/
FieldDescr::FieldDescr (int _propID, const char *_name)
{
propID = _propID;
name = _name ? strdup (_name) : NULL;
offset = 0;
vtype = TYPE_NONE;
format = NULL;
}
FieldDescr::~FieldDescr ()
{
free (name);
free (format);
}
/*
* class PacketDescriptor
*/
PacketDescriptor::PacketDescriptor (DataDescriptor *_ddscr)
{
ddscr = _ddscr;
fields = new Vector<FieldDescr*>;
}
PacketDescriptor::~PacketDescriptor ()
{
fields->destroy ();
delete fields;
}
void
PacketDescriptor::addField (FieldDescr *fldDscr)
{
if (fldDscr == NULL)
return;
fields->append (fldDscr);
}
/*
* class Data
*/
/* Check compatibility between Datum and Data */
static void
checkCompatibility (VType_type v1, VType_type v2)
{
switch (v1)
{
case TYPE_NONE:
case TYPE_STRING:
case TYPE_DOUBLE:
case TYPE_OBJ:
case TYPE_DATE:
assert (v1 == v2);
break;
case TYPE_INT32:
case TYPE_UINT32:
assert (v2 == TYPE_INT32 ||
v2 == TYPE_UINT32);
break;
case TYPE_INT64:
case TYPE_UINT64:
assert (v2 == TYPE_INT64 ||
v2 == TYPE_UINT64);
break;
default:
assert (0);
}
}
class DataINT32 : public Data
{
public:
DataINT32 ()
{
data = new Vector<int32_t>;
}
virtual
~DataINT32 ()
{
delete data;
}
virtual VType_type
type ()
{
return TYPE_INT32;
}
virtual void
reset ()
{
data->reset ();
}
virtual long
getSize ()
{
return data->size ();
}
virtual int
fetchInt (long i)
{
return (int) data->fetch (i);
}
virtual unsigned long long
fetchULong (long i)
{
return (unsigned long long) data->fetch (i);
}
virtual long long
fetchLong (long i)
{
return (long long) data->fetch (i);
}
virtual char *
fetchString (long i)
{
return dbe_sprintf (NTXT ("%d"), data->fetch (i));
}
virtual double
fetchDouble (long i)
{
return (double) data->fetch (i);
}
virtual void *
fetchObject (long)
{
assert (ASSERT_SKIP);
return NULL;
}
virtual void
setDatumValue (long idx, const Datum *val)
{
data->store (idx, val->i);
}
virtual void
setValue (long idx, uint64_t val)
{
data->store (idx, (int32_t) val);
}
virtual void
setObjValue (long, void*)
{
assert (ASSERT_SKIP);
return;
}
virtual int
cmpValues (long idx1, long idx2)
{
int32_t i1 = data->fetch (idx1);
int32_t i2 = data->fetch (idx2);
return i1 < i2 ? -1 : i1 > i2 ? 1 : 0;
}
virtual int
cmpDatumValue (long idx, const Datum *val)
{
int32_t i1 = data->fetch (idx);
int32_t i2 = val->i;
return i1 < i2 ? -1 : i1 > i2 ? 1 : 0;
}
private:
Vector<int32_t> *data;
};
class DataUINT32 : public Data
{
public:
DataUINT32 ()
{
data = new Vector<uint32_t>;
}
virtual
~DataUINT32 ()
{
delete data;
}
virtual VType_type
type ()
{
return TYPE_UINT32;
}
virtual void
reset ()
{
data->reset ();
}
virtual long
getSize ()
{
return data->size ();
}
virtual int
fetchInt (long i)
{
return (int) data->fetch (i);
}
virtual unsigned long long
fetchULong (long i)
{
return (unsigned long long) data->fetch (i);
}
virtual long long
fetchLong (long i)
{
return (long long) data->fetch (i);
}
virtual char *
fetchString (long i)
{
return dbe_sprintf (NTXT ("%u"), data->fetch (i));
}
virtual double
fetchDouble (long i)
{
return (double) data->fetch (i);
}
virtual void *
fetchObject (long)
{
assert (ASSERT_SKIP);
return NULL;
}
virtual void
setDatumValue (long idx, const Datum *val)
{
data->store (idx, val->i);
}
virtual void
setValue (long idx, uint64_t val)
{
data->store (idx, (uint32_t) val);
}
virtual void
setObjValue (long, void*)
{
assert (ASSERT_SKIP);
return;
}
virtual int
cmpValues (long idx1, long idx2)
{
uint32_t u1 = data->fetch (idx1);
uint32_t u2 = data->fetch (idx2);
return u1 < u2 ? -1 : u1 > u2 ? 1 : 0;
}
virtual int
cmpDatumValue (long idx, const Datum *val)
{
uint32_t u1 = data->fetch (idx);
uint32_t u2 = (uint32_t) val->i;
return u1 < u2 ? -1 : u1 > u2 ? 1 : 0;
}
private:
Vector<uint32_t> *data;
};
class DataINT64 : public Data
{
public:
DataINT64 ()
{
data = new Vector<int64_t>;
}
virtual
~DataINT64 ()
{
delete data;
}
virtual VType_type
type ()
{
return TYPE_INT64;
}
virtual void
reset ()
{
data->reset ();
}
virtual long
getSize ()
{
return data->size ();
}
virtual int
fetchInt (long i)
{
return (int) data->fetch (i);
}
virtual unsigned long long
fetchULong (long i)
{
return (unsigned long long) data->fetch (i);
}
virtual long long
fetchLong (long i)
{
return (long long) data->fetch (i);
}
virtual char *
fetchString (long i)
{
return dbe_sprintf (NTXT ("%lld"), (long long) data->fetch (i));
}
virtual double
fetchDouble (long i)
{
return (double) data->fetch (i);
}
virtual void *
fetchObject (long)
{
assert (ASSERT_SKIP);
return NULL;
}
virtual void
setDatumValue (long idx, const Datum *val)
{
data->store (idx, val->ll);
}
virtual void
setValue (long idx, uint64_t val)
{
data->store (idx, (int64_t) val);
}
virtual void
setObjValue (long, void*)
{
assert (ASSERT_SKIP);
return;
}
virtual int
cmpValues (long idx1, long idx2)
{
int64_t i1 = data->fetch (idx1);
int64_t i2 = data->fetch (idx2);
return i1 < i2 ? -1 : i1 > i2 ? 1 : 0;
}
virtual int
cmpDatumValue (long idx, const Datum *val)
{
int64_t i1 = data->fetch (idx);
int64_t i2 = val->ll;
return i1 < i2 ? -1 : i1 > i2 ? 1 : 0;
}
private:
Vector<int64_t> *data;
};
class DataUINT64 : public Data
{
public:
DataUINT64 ()
{
data = new Vector<uint64_t>;
}
virtual
~DataUINT64 ()
{
delete data;
}
virtual VType_type
type ()
{
return TYPE_UINT64;
}
virtual void
reset ()
{
data->reset ();
}
virtual long
getSize ()
{
return data->size ();
}
virtual int
fetchInt (long i)
{
return (int) data->fetch (i);
}
virtual unsigned long long
fetchULong (long i)
{
return (unsigned long long) data->fetch (i);
}
virtual long long
fetchLong (long i)
{
return (long long) data->fetch (i);
}
virtual char *
fetchString (long i)
{
return dbe_sprintf (NTXT ("%llu"), (long long) data->fetch (i));
}
virtual double
fetchDouble (long i)
{
return (double) data->fetch (i);
}
virtual void *
fetchObject (long)
{
assert (ASSERT_SKIP);
return NULL;
}
virtual void
setDatumValue (long idx, const Datum *val)
{
data->store (idx, val->ll);
}
virtual void
setValue (long idx, uint64_t val)
{
data->store (idx, val);
}
virtual void
setObjValue (long, void*)
{
assert (ASSERT_SKIP);
return;
}
virtual int
cmpValues (long idx1, long idx2)
{
uint64_t u1 = data->fetch (idx1);
uint64_t u2 = data->fetch (idx2);
return u1 < u2 ? -1 : u1 > u2 ? 1 : 0;
}
virtual int
cmpDatumValue (long idx, const Datum *val)
{
uint64_t u1 = data->fetch (idx);
uint64_t u2 = (uint64_t) val->ll;
return u1 < u2 ? -1 : u1 > u2 ? 1 : 0;
}
private:
Vector<uint64_t> *data;
};
class DataOBJECT : public Data
{
public:
DataOBJECT ()
{
dtype = TYPE_OBJ;
data = new Vector<void*>;
}
DataOBJECT (VType_type _dtype)
{
dtype = _dtype;
data = new Vector<void*>;
}
virtual
~DataOBJECT ()
{
delete data;
}
virtual VType_type
type ()
{
return dtype;
}
virtual void
reset ()
{
data->reset ();
}
virtual long
getSize ()
{
return data->size ();
}
virtual int
fetchInt (long)
{
assert (ASSERT_SKIP);
return 0;
}
virtual unsigned long long
fetchULong (long)
{
assert (ASSERT_SKIP);
return 0LL;
}
virtual long long
fetchLong (long)
{
assert (ASSERT_SKIP);
return 0LL;
}
virtual char *
fetchString (long i)
{
return dbe_sprintf (NTXT ("%lu"), (unsigned long) data->fetch (i));
}
virtual double
fetchDouble (long)
{
assert (ASSERT_SKIP);
return 0.0;
}
virtual void *
fetchObject (long i)
{
return data->fetch (i);
}
virtual void
setDatumValue (long idx, const Datum *val)
{
data->store (idx, val->p);
}
virtual void
setValue (long, uint64_t)
{
assert (ASSERT_SKIP);
return;
}
virtual void
setObjValue (long idx, void *p)
{
data->store (idx, p);
}
virtual int
cmpValues (long, long)
{
return 0;
}
virtual int
cmpDatumValue (long, const Datum *)
{
return 0;
}
private:
VType_type dtype;
Vector<void*> *data;
};
class DataSTRING : public Data
{
public:
DataSTRING ()
{
data = new Vector<char*>;
}
virtual
~DataSTRING ()
{
data->destroy ();
delete data;
}
virtual VType_type
type ()
{
return TYPE_STRING;
}
virtual void
reset ()
{
data->reset ();
}
virtual long
getSize ()
{
return data->size ();
}
virtual int
fetchInt (long)
{
return 0;
}
virtual unsigned long long
fetchULong (long)
{
return 0LL;
}
virtual long long
fetchLong (long)
{
return 0LL;
}
virtual char *
fetchString (long i)
{
return strdup (data->fetch (i));
}
virtual double
fetchDouble (long)
{
return 0.0;
}
virtual void *
fetchObject (long i)
{
return data->fetch (i);
}
virtual void
setDatumValue (long idx, const Datum *val)
{
data->store (idx, val->l);
}
virtual void
setValue (long, uint64_t)
{
return;
}
virtual void
setObjValue (long idx, void *p)
{
data->store (idx, (char*) p);
}
virtual int
cmpValues (long, long)
{
return 0;
}
virtual int
cmpDatumValue (long, const Datum *)
{
return 0;
}
private:
Vector<char*> *data;
};
class DataDOUBLE : public Data
{
public:
DataDOUBLE ()
{
data = new Vector<double>;
}
virtual
~DataDOUBLE ()
{
delete data;
}
virtual VType_type
type ()
{
return TYPE_DOUBLE;
}
virtual void
reset ()
{
data->reset ();
}
virtual long
getSize ()
{
return data->size ();
}
virtual int
fetchInt (long i)
{
return (int) data->fetch (i);
}
virtual unsigned long long
fetchULong (long i)
{
return (unsigned long long) data->fetch (i);
}
virtual long long
fetchLong (long i)
{
return (long long) data->fetch (i);
}
virtual char *
fetchString (long i)
{
return dbe_sprintf (NTXT ("%f"), data->fetch (i));
}
virtual double
fetchDouble (long i)
{
return data->fetch (i);
}
virtual void
setDatumValue (long idx, const Datum *val)
{
data->store (idx, val->d);
}
virtual void
setValue (long idx, uint64_t val)
{
data->store (idx, (double) val);
}
virtual void
setObjValue (long, void*)
{
return;
}
virtual void *
fetchObject (long)
{
return NULL;
}
virtual int
cmpValues (long idx1, long idx2)
{
double d1 = data->fetch (idx1);
double d2 = data->fetch (idx2);
return d1 < d2 ? -1 : d1 > d2 ? 1 : 0;
}
virtual int
cmpDatumValue (long idx, const Datum *val)
{
double d1 = data->fetch (idx);
double d2 = val->d;
return d1 < d2 ? -1 : d1 > d2 ? 1 : 0;
}
private:
Vector<double> *data;
};
Data *
Data::newData (VType_type vtype)
{
switch (vtype)
{
case TYPE_INT32:
return new DataINT32;
case TYPE_UINT32:
return new DataUINT32;
case TYPE_INT64:
return new DataINT64;
case TYPE_UINT64:
return new DataUINT64;
case TYPE_OBJ:
return new DataOBJECT;
case TYPE_STRING:
return new DataSTRING;
case TYPE_DOUBLE:
return new DataDOUBLE;
default:
return NULL;
}
}
/*
* class DataDescriptor
*/
DataDescriptor::DataDescriptor (int _id, const char *_name, const char *_uname,
int _flags)
{
isMaster = true;
id = _id;
name = _name ? strdup (_name) : strdup (NTXT (""));
uname = _uname ? strdup (_uname) : strdup (NTXT (""));
flags = _flags;
// master data, shared with reference copies:
master_size = 0;
master_resolveFrameInfoDone = false;
props = new Vector<PropDescr*>;
data = new Vector<Data*>;
setsTBR = new Vector<Vector<long long>*>;
// master references point to self:
ref_size = &master_size;
ref_resolveFrameInfoDone = &master_resolveFrameInfoDone;
}
DataDescriptor::DataDescriptor (int _id, const char *_name, const char *_uname,
DataDescriptor* dDscr)
{
isMaster = false;
id = _id;
name = _name ? strdup (_name) : strdup (NTXT (""));
uname = _uname ? strdup (_uname) : strdup (NTXT (""));
flags = dDscr->flags;
// references point to master DataDescriptor
ref_size = &dDscr->master_size;
ref_resolveFrameInfoDone = &dDscr->master_resolveFrameInfoDone;
props = dDscr->props;
data = dDscr->data;
setsTBR = dDscr->setsTBR;
// data that should never be accessed in reference copy
master_size = -1;
master_resolveFrameInfoDone = false;
}
DataDescriptor::~DataDescriptor ()
{
free (name);
free (uname);
if (!isMaster)
return;
props->destroy ();
delete props;
data->destroy ();
delete data;
setsTBR->destroy ();
delete setsTBR;
}
void
DataDescriptor::reset ()
{
if (!isMaster)
return;
for (int i = 0; i < data->size (); i++)
{
Data *d = data->fetch (i);
if (d != NULL)
d->reset ();
Vector<long long> *set = setsTBR->fetch (i);
if (set != NULL)
set->reset ();
}
master_size = 0;
}
PropDescr *
DataDescriptor::getProp (int prop_id)
{
for (int i = 0; i < props->size (); i++)
{
PropDescr *propDscr = props->fetch (i);
if (propDscr->propID == prop_id)
return propDscr;
}
return NULL;
}
Data *
DataDescriptor::getData (int prop_id)
{
if (prop_id < 0 || prop_id >= data->size ())
return NULL;
return data->fetch (prop_id);
}
void
DataDescriptor::addProperty (PropDescr *propDscr)
{
if (propDscr == NULL)
return;
if (propDscr->propID < 0)
return;
PropDescr *oldProp = getProp (propDscr->propID);
if (oldProp != NULL)
{
checkCompatibility (propDscr->vtype, oldProp->vtype); //YXXX depends on experiment correctness
delete propDscr;
return;
}
props->append (propDscr);
data->store (propDscr->propID, Data::newData (propDscr->vtype));
setsTBR->store (propDscr->propID, NULL);
}
long
DataDescriptor::addRecord ()
{
if (!isMaster)
return -1;
return master_size++;
}
static void
checkEntity (Vector<long long> *set, long long val)
{
// Binary search
int lo = 0;
int hi = set->size () - 1;
while (lo <= hi)
{
int md = (lo + hi) / 2;
long long ent = set->fetch (md);
if (ent < val)
lo = md + 1;
else if (ent > val)
hi = md - 1;
else
return;
}
set->insert (lo, val);
}
void
DataDescriptor::setDatumValue (int prop_id, long idx, const Datum *val)
{
if (idx >= *ref_size)
return;
Data *d = getData (prop_id);
if (d != NULL)
{
VType_type datum_type = val->type;
VType_type data_type = d->type ();
checkCompatibility (datum_type, data_type);
d->setDatumValue (idx, val);
Vector<long long> *set = setsTBR->fetch (prop_id);
if (set != NULL)// Sets are maintained
checkEntity (set, d->fetchLong (idx));
}
}
void
DataDescriptor::setValue (int prop_id, long idx, uint64_t val)
{
if (idx >= *ref_size)
return;
Data *d = getData (prop_id);
if (d != NULL)
{
d->setValue (idx, val);
Vector<long long> *set = setsTBR->fetch (prop_id);
if (set != NULL)// Sets are maintained
checkEntity (set, d->fetchLong (idx));
}
}
void
DataDescriptor::setObjValue (int prop_id, long idx, void *val)
{
if (idx >= *ref_size)
return;
Data *d = getData (prop_id);
if (d != NULL)
d->setObjValue (idx, val);
}
DataView *
DataDescriptor::createView ()
{
return new DataView (this);
}
DataView *
DataDescriptor::createImmutableView ()
{
return new DataView (this, DataView::DV_IMMUTABLE);
}
DataView *
DataDescriptor::createExtManagedView ()
{
return new DataView (this, DataView::DV_EXT_MANAGED);
}
int
DataDescriptor::getIntValue (int prop_id, long idx)
{
Data *d = getData (prop_id);
if (d == NULL || idx >= d->getSize ())
return 0;
return d->fetchInt (idx);
}
unsigned long long
DataDescriptor::getULongValue (int prop_id, long idx)
{
Data *d = getData (prop_id);
if (d == NULL || idx >= d->getSize ())
return 0L;
return d->fetchULong (idx);
}
long long
DataDescriptor::getLongValue (int prop_id, long idx)
{
Data *d = getData (prop_id);
if (d == NULL || idx >= d->getSize ())
return 0L;
return d->fetchLong (idx);
}
void *
DataDescriptor::getObjValue (int prop_id, long idx)
{
Data *d = getData (prop_id);
if (d == NULL || idx >= d->getSize ())
return NULL;
return d->fetchObject (idx);
}
static int
pcmp (const void *p1, const void *p2, const void *arg)
{
long idx1 = *(long*) p1; // index1 into Data
long idx2 = *(long*) p2; // index2 into Data
for (Data **dsorted = (Data**) arg; *dsorted != DATA_SORT_EOL; dsorted++)
{
Data *data = *dsorted;
if (data == NULL)// sort property not in this data, skip this criteria
continue;
int res = data->cmpValues (idx1, idx2);
if (res)
return res;
}
// Provide stable sort
return idx1 < idx2 ? -1 : idx1 > idx2 ? 1 : 0;
}
Vector<long long> *
DataDescriptor::getSet (int prop_id)
{
if (prop_id < 0 || prop_id >= setsTBR->size ())
return NULL;
Vector<long long> *set = setsTBR->fetch (prop_id);
if (set != NULL)
return set;
Data *d = getData (prop_id);
if (d == NULL)
return NULL;
set = new Vector<long long>;
for (long i = 0; i<*ref_size; ++i)
checkEntity (set, d->fetchLong (i));
setsTBR->store (prop_id, set);
return set;
}
/*
* class DataView
*/
DataView::DataView (DataDescriptor *_ddscr)
{
init (_ddscr, DV_NORMAL);
}
DataView::DataView (DataDescriptor *_ddscr, DataViewType _type)
{
init (_ddscr, _type);
}
void
DataView::init (DataDescriptor *_ddscr, DataViewType _type)
{
ddscr = _ddscr;
type = _type;
switch (type)
{
case DV_IMMUTABLE:
ddsize = ddscr->getSize ();
index = NULL;
break;
case DV_NORMAL:
case DV_EXT_MANAGED:
ddsize = 0;
index = new Vector<long>;
break;
}
for (int ii = 0; ii < (MAX_SORT_DIMENSIONS + 1); ii++)
sortedBy[ii] = DATA_SORT_EOL;
filter = NULL;
}
DataView::~DataView ()
{
delete filter;
delete index;
}
void
DataView::appendDataDescriptorId (long pkt_id /* ddscr index */)
{
if (type != DV_EXT_MANAGED)
return; // updates allowed only on externally managed DataViews
long curr_ddsize = ddscr->getSize ();
if (pkt_id < 0 || pkt_id >= curr_ddsize)
return; // error!
index->append (pkt_id);
}
void
DataView::setDataDescriptorValue (int prop_id, long pkt_id, uint64_t val)
{
ddscr->setValue (prop_id, pkt_id, val);
}
long long
DataView::getDataDescriptorValue (int prop_id, long pkt_id)
{
return ddscr->getLongValue (prop_id, pkt_id);
}
Vector<PropDescr*>*
DataView::getProps ()
{
return ddscr->getProps ();
};
PropDescr*
DataView::getProp (int prop_id)
{
return ddscr->getProp (prop_id);
};
void
DataView::filter_in_chunks (fltr_dbe_ctx *dctx)
{
Expression::Context *e_ctx = new Expression::Context (dctx->fltr->ctx->dbev, dctx->fltr->ctx->exp);
Expression *n_expr = dctx->fltr->expr->copy ();
bool noParFilter = dctx->fltr->noParFilter;
FilterExp *nFilter = new FilterExp (n_expr, e_ctx, noParFilter);
long iter = dctx->begin;
long end = dctx->end;
long orig_ddsize = dctx->orig_ddsize;
while (iter < end)
{
nFilter->put (dctx->tmpView, iter);
if (nFilter->passes ())
dctx->idxArr[iter - orig_ddsize] = 1;
iter += 1;
}
delete nFilter;
}
bool
DataView::checkUpdate ()
{
long newSize = ddscr->getSize ();
if (ddsize == newSize)
return false;
if (index == NULL)
return false;
if (type == DV_EXT_MANAGED)
return false;
bool updated = false;
if (filter)
{
DataView *tmpView = ddscr->createImmutableView ();
assert (tmpView->getSize () == newSize);
while (ddsize < newSize)
{
filter->put (tmpView, ddsize);
if (filter->passes ())
index->append (ddsize);
ddsize += 1;
}
delete tmpView;
return updated;
}
while (ddsize < newSize)
{
index->append (ddsize);
updated = true;
ddsize += 1;
}
return updated;
}
long
DataView::getSize ()
{
if (checkUpdate () && sortedBy[0] != DATA_SORT_EOL)
// note: after new filter is set, getSize() incurs cost of
// sorting even if caller isn't interested in sort
index->sort ((CompareFunc) pcmp, sortedBy);
if (index == NULL)
return ddscr->getSize ();
return index->size ();
}
void
DataView::setDatumValue (int prop_id, long idx, const Datum *val)
{
ddscr->setDatumValue (prop_id, getIdByIdx (idx), val);
}
void
DataView::setValue (int prop_id, long idx, uint64_t val)
{
ddscr->setValue (prop_id, getIdByIdx (idx), val);
}
void
DataView::setObjValue (int prop_id, long idx, void *val)
{
ddscr->setObjValue (prop_id, getIdByIdx (idx), val);
}
int
DataView::getIntValue (int prop_id, long idx)
{
return ddscr->getIntValue (prop_id, getIdByIdx (idx));
}
unsigned long long
DataView::getULongValue (int prop_id, long idx)
{
return ddscr->getULongValue (prop_id, getIdByIdx (idx));
}
long long
DataView::getLongValue (int prop_id, long idx)
{
return ddscr->getLongValue (prop_id, getIdByIdx (idx));
}
void *
DataView::getObjValue (int prop_id, long idx)
{
return ddscr->getObjValue (prop_id, getIdByIdx (idx));
}
void
DataView::sort (const int props[], int prop_count)
{
if (index == NULL)
{
assert (ASSERT_SKIP);
return;
}
assert (prop_count >= 0 && prop_count < MAX_SORT_DIMENSIONS);
bool sort_changed = false; // see if sort has changed...
for (int ii = 0; ii <= prop_count; ii++)
{ // sortedBy size is prop_count+1
Data *data;
if (ii == prop_count)
data = DATA_SORT_EOL; // special end of array marker
else
data = ddscr->getData (props[ii]);
if (sortedBy[ii] != data)
{
sortedBy[ii] = data;
sort_changed = true;
}
}
if (!checkUpdate () && !sort_changed)
return;
index->sort ((CompareFunc) pcmp, sortedBy);
}
void
DataView::sort (int prop0)
{
sort (&prop0, 1);
}
void
DataView::sort (int prop0, int prop1)
{
int props[2] = {prop0, prop1};
sort (props, 2);
}
void
DataView::sort (int prop0, int prop1, int prop2)
{
int props[3] = {prop0, prop1, prop2};
sort (props, 3);
}
void
DataView::setFilter (FilterExp *f)
{
if (index == NULL)
{
assert (ASSERT_SKIP);
return;
}
delete filter;
filter = f;
index->reset ();
ddsize = 0;
checkUpdate ();
}
long
DataView::getIdByIdx (long idx)
{
if (index == NULL)
return idx;
return index->fetch (idx);
}
static int
tvalcmp (long data_id, const Datum valColumns[], Data *sortedBy[])
{
for (int ii = 0; ii < MAX_SORT_DIMENSIONS; ii++)
{
if (sortedBy[ii] == DATA_SORT_EOL)
break;
Data *d = sortedBy[ii];
if (d == NULL)// property doesn't exist in data; compare always matches
continue;
const Datum *tvalue = &valColumns[ii];
int res = d->cmpDatumValue (data_id, tvalue);
if (res)
return res;
}
return 0;
}
static void
checkSortTypes (const Datum valColumns[], Data *sortedBy[])
{
#ifndef NDEBUG
for (int ii = 0; ii < MAX_SORT_DIMENSIONS; ii++)
{
if (sortedBy[ii] == DATA_SORT_EOL)
break;
Data *d = sortedBy[ii];
if (d == NULL)// property doesn't exist in data; compare always matches
continue;
VType_type datum_type = valColumns[ii].type;
VType_type data_type = d->type ();
checkCompatibility (datum_type, data_type);
}
#endif
}
bool
DataView::idxRootDimensionsMatch (long idx, const Datum valColumns[])
{
// compares idx vs. valColumns[] - If all dimensions match
// (except sort leaf), then the leaf value is valid => return true.
// Otherwise, return false.
checkSortTypes (valColumns, sortedBy);
if (idx < 0 || idx >= index->size ()) // fell off end of array
return false;
long data_id = index->fetch (idx);
// we will check all dimensions for a match except the "leaf" dimension
for (int ii = 0; ii < (MAX_SORT_DIMENSIONS - 1); ii++)
{
if (sortedBy[ii + 1] == DATA_SORT_EOL)
break; // we are at leaf dimension, don't care about it's value
if (sortedBy[ii] == DATA_SORT_EOL)
break; // end of list
Data *d = sortedBy[ii];
if (d == NULL) // property doesn't exist in data; compare always matches
continue;
const Datum *tvalue = &valColumns[ii];
int res = d->cmpDatumValue (data_id, tvalue);
if (res)
return false;
}
return true;
}
long
DataView::getIdxByVals (const Datum valColumns[], Relation rel)
{
// checks sortedBy[] columns for match; relation only used on last column
return getIdxByVals (valColumns, rel, -1, -1);
}
long
DataView::getIdxByVals (const Datum valColumns[], Relation rel,
long minIdx, long maxIdx)
{
// checks sortedBy[] columns for match; relation only used on last column
checkSortTypes (valColumns, sortedBy);
if (index == NULL || sortedBy[0] == DATA_SORT_EOL)
return -1;
long lo;
if (minIdx < 0)
lo = 0;
else
lo = minIdx;
long hi;
if (maxIdx < 0 || maxIdx >= index->size ())
hi = index->size () - 1;
else
hi = maxIdx;
long md = -1;
while (lo <= hi)
{
md = (lo + hi) / 2;
int cmp = tvalcmp (index->fetch (md), valColumns, sortedBy);
if (cmp < 0)
{
lo = md + 1;
continue;
}
else if (cmp > 0)
{
hi = md - 1;
continue;
}
// cmp == 0, we have an exact match
switch (rel)
{
case REL_LT:
hi = md - 1; // continue searching
break;
case REL_GT:
lo = md + 1; // continue searching
break;
case REL_LTEQ:
case REL_GTEQ:
case REL_EQ:
// note: "md" may not be deterministic if multiple matches exist
return md; // a match => done.
}
}
// no exact match found
switch (rel)
{
case REL_LT:
case REL_LTEQ:
md = hi;
break;
case REL_GT:
case REL_GTEQ:
md = lo;
break;
case REL_EQ:
return -1;
}
if (idxRootDimensionsMatch (md, valColumns))
return md;
return -1;
}
void
DataView::removeDbeViewIdx (long idx)
{
index->remove (idx);
}