aboutsummaryrefslogtreecommitdiff
path: root/gprofng/src/Table.cc
diff options
context:
space:
mode:
authorVladimir Mezentsev <vladimir.mezentsev@oracle.com>2022-03-11 08:58:31 +0000
committerNick Clifton <nickc@redhat.com>2022-03-11 08:58:31 +0000
commitbb368aad297fe3ad40cf397e6fc85aa471429a28 (patch)
tree0ab25909b8fe789d676bbdb00d501d4d485e4afe /gprofng/src/Table.cc
parenta655f19af95eb685ba64f48ee8fc2b3b7a3d886a (diff)
downloadbinutils-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.cc1687
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);
+}
+