| /* Copyright (C) 2021-2024 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); | |
| } | |