diff options
author | Vladimir Mezentsev <vladimir.mezentsev@oracle.com> | 2022-03-11 08:58:31 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2022-03-11 08:58:31 +0000 |
commit | bb368aad297fe3ad40cf397e6fc85aa471429a28 (patch) | |
tree | 0ab25909b8fe789d676bbdb00d501d4d485e4afe /gprofng/src/Table.cc | |
parent | a655f19af95eb685ba64f48ee8fc2b3b7a3d886a (diff) | |
download | binutils-bb368aad297fe3ad40cf397e6fc85aa471429a28.zip binutils-bb368aad297fe3ad40cf397e6fc85aa471429a28.tar.gz binutils-bb368aad297fe3ad40cf397e6fc85aa471429a28.tar.bz2 |
gprofng: a new GNU profiler
top-level
* Makefile.def: Add gprofng module.
* configure.ac: Add --enable-gprofng option.
* src-release.sh: Add gprofng.
* Makefile.in: Regenerate.
* configure: Regenerate.
* gprofng: New directory.
binutils
* MAINTAINERS: Add gprofng maintainer.
* README-how-to-make-a-release: Add gprofng.
include.
* collectorAPI.h: New file.
* libcollector.h: New file.
* libfcollector.h: New file.
Diffstat (limited to 'gprofng/src/Table.cc')
-rw-r--r-- | gprofng/src/Table.cc | 1687 |
1 files changed, 1687 insertions, 0 deletions
diff --git a/gprofng/src/Table.cc b/gprofng/src/Table.cc new file mode 100644 index 0000000..afe44bd --- /dev/null +++ b/gprofng/src/Table.cc @@ -0,0 +1,1687 @@ +/* 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); +} + |