1/* Copyright (C) 2021 Free Software Foundation, Inc.
2   Contributed by Oracle.
3
4   This file is part of GNU Binutils.
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 3, or (at your option)
9   any later version.
10
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with this program; if not, write to the Free Software
18   Foundation, 51 Franklin Street - Fifth Floor, Boston,
19   MA 02110-1301, USA.  */
20
21#include "config.h"
22#include <stdio.h>
23
24#include "IndexMap2D.h"
25#include "DbeSession.h"
26#include "FilterExp.h"
27#include "Table.h"
28#include "util.h"
29#include "i18n.h"
30
31char *
32get_prof_data_type_name (int t)
33{
34  switch (t)
35    {
36    case DATA_SAMPLE:   return NTXT("PROFDATA_TYPE_SAMPLE");
37    case DATA_GCEVENT:  return NTXT("PROFDATA_TYPE_GCEVENT");
38    case DATA_HEAPSZ:   return NTXT("PROFDATA_TYPE_HEAPSZ");
39    case DATA_CLOCK:    return NTXT("PROFDATA_TYPE_CLOCK");
40    case DATA_HWC:      return NTXT("PROFDATA_TYPE_HWC");
41    case DATA_SYNCH:    return NTXT("PROFDATA_TYPE_SYNCH");
42    case DATA_HEAP:     return NTXT("PROFDATA_TYPE_HEAP");
43    case DATA_OMP:      return NTXT("PROFDATA_TYPE_OMP");
44    case DATA_OMP2:     return NTXT("PROFDATA_TYPE_OMP2");
45    case DATA_OMP3:     return NTXT("PROFDATA_TYPE_OMP3");
46    case DATA_OMP4:     return NTXT("PROFDATA_TYPE_OMP4");
47    case DATA_OMP5:     return NTXT("PROFDATA_TYPE_OMP5");
48    case DATA_IOTRACE:  return NTXT("PROFDATA_TYPE_IOTRACE");
49    default: abort ();
50      return NTXT ("PROFDATA_TYPE_ERROR");
51    }
52}
53
54char *
55get_prof_data_type_uname (int t)
56{
57  switch (t)
58    {
59    case DATA_SAMPLE:   return GTXT("Process-wide Resource Utilization");
60    case DATA_GCEVENT:  return GTXT("Java Garbage Collection Events");
61    case DATA_HEAPSZ:   return GTXT("Heap Size");
62    case DATA_CLOCK:    return GTXT("Clock Profiling");
63    case DATA_HWC:      return GTXT("HW Counter Profiling");
64    case DATA_SYNCH:    return GTXT("Synchronization Tracing");
65    case DATA_HEAP:     return GTXT("Heap Tracing");
66    case DATA_OMP:      return GTXT("OpenMP Profiling");
67    case DATA_OMP2:     return GTXT("OpenMP Profiling");
68    case DATA_OMP3:     return GTXT("OpenMP Profiling");
69    case DATA_OMP4:     return GTXT("OpenMP Profiling");
70    case DATA_OMP5:     return GTXT("OpenMP Profiling");
71    case DATA_IOTRACE:  return GTXT("IO Tracing");
72    default: abort ();
73      return NTXT ("PROFDATA_TYPE_ERROR");
74    }
75}
76
77int assert_level = 0; // set to 1 to bypass problematic asserts
78
79#define ASSERT_SKIP (assert_level)
80
81/*
82 *    class PropDescr
83 */
84
85PropDescr::PropDescr (int _propID, const char *_name)
86{
87  propID = _propID;
88  name = strdup (_name ? _name : NTXT (""));
89  uname = NULL;
90  vtype = TYPE_NONE;
91  flags = 0;
92  stateNames = NULL;
93  stateUNames = NULL;
94}
95
96PropDescr::~PropDescr ()
97{
98  free (name);
99  free (uname);
100  if (stateNames)
101    {
102      stateNames->destroy ();
103      delete stateNames;
104    }
105  if (stateUNames)
106    {
107      stateUNames->destroy ();
108      delete stateUNames;
109    }
110}
111
112void
113PropDescr::addState (int value, const char *stname, const char *stuname)
114{
115  if (value < 0 || stname == NULL)
116    return;
117  if (stateNames == NULL)
118    stateNames = new Vector<char*>;
119  stateNames->store (value, strdup (stname));
120  if (stateUNames == NULL)
121    stateUNames = new Vector<char*>;
122  stateUNames->store (value, strdup (stuname));
123}
124
125char *
126PropDescr::getStateName (int value)
127{
128  if (stateNames && value >= 0 && value < stateNames->size ())
129    return stateNames->fetch (value);
130  return NULL;
131}
132
133char *
134PropDescr::getStateUName (int value)
135{
136  if (stateUNames && value >= 0 && value < stateUNames->size ())
137    return stateUNames->fetch (value);
138  return NULL;
139}
140
141/*
142 *    class FieldDescr
143 */
144
145FieldDescr::FieldDescr (int _propID, const char *_name)
146{
147  propID = _propID;
148  name = _name ? strdup (_name) : NULL;
149  offset = 0;
150  vtype = TYPE_NONE;
151  format = NULL;
152}
153
154FieldDescr::~FieldDescr ()
155{
156  free (name);
157  free (format);
158}
159
160/*
161 *    class PacketDescriptor
162 */
163
164PacketDescriptor::PacketDescriptor (DataDescriptor *_ddscr)
165{
166  ddscr = _ddscr;
167  fields = new Vector<FieldDescr*>;
168}
169
170PacketDescriptor::~PacketDescriptor ()
171{
172  fields->destroy ();
173  delete fields;
174}
175
176void
177PacketDescriptor::addField (FieldDescr *fldDscr)
178{
179  if (fldDscr == NULL)
180    return;
181  fields->append (fldDscr);
182}
183
184/*
185 *    class Data
186 */
187
188/* Check compatibility between Datum and Data */
189static void
190checkCompatibility (VType_type v1, VType_type v2)
191{
192  switch (v1)
193    {
194    case TYPE_NONE:
195    case TYPE_STRING:
196    case TYPE_DOUBLE:
197    case TYPE_OBJ:
198    case TYPE_DATE:
199      assert (v1 == v2);
200      break;
201    case TYPE_INT32:
202    case TYPE_UINT32:
203      assert (v2 == TYPE_INT32 ||
204	      v2 == TYPE_UINT32);
205      break;
206    case TYPE_INT64:
207    case TYPE_UINT64:
208      assert (v2 == TYPE_INT64 ||
209	      v2 == TYPE_UINT64);
210      break;
211    default:
212      assert (0);
213    }
214}
215
216class DataINT32 : public Data
217{
218public:
219
220  DataINT32 ()
221  {
222    data = new Vector<int32_t>;
223  }
224
225  virtual
226  ~DataINT32 ()
227  {
228    delete data;
229  }
230
231  virtual VType_type
232  type ()
233  {
234    return TYPE_INT32;
235  }
236
237  virtual void
238  reset ()
239  {
240    data->reset ();
241  }
242
243  virtual long
244  getSize ()
245  {
246    return data->size ();
247  }
248
249  virtual int
250  fetchInt (long i)
251  {
252    return (int) data->fetch (i);
253  }
254
255  virtual unsigned long long
256  fetchULong (long i)
257  {
258    return (unsigned long long) data->fetch (i);
259  }
260
261  virtual long long
262  fetchLong (long i)
263  {
264    return (long long) data->fetch (i);
265  }
266
267  virtual char *
268  fetchString (long i)
269  {
270    return dbe_sprintf (NTXT ("%d"), data->fetch (i));
271  }
272
273  virtual double
274  fetchDouble (long i)
275  {
276    return (double) data->fetch (i);
277  }
278
279  virtual void *
280  fetchObject (long)
281  {
282    assert (ASSERT_SKIP);
283    return NULL;
284  }
285
286  virtual void
287  setDatumValue (long idx, const Datum *val)
288  {
289    data->store (idx, val->i);
290  }
291
292  virtual void
293  setValue (long idx, uint64_t val)
294  {
295    data->store (idx, (int32_t) val);
296  }
297
298  virtual void
299  setObjValue (long, void*)
300  {
301    assert (ASSERT_SKIP);
302    return;
303  }
304
305  virtual int
306  cmpValues (long idx1, long idx2)
307  {
308    int32_t i1 = data->fetch (idx1);
309    int32_t i2 = data->fetch (idx2);
310    return i1 < i2 ? -1 : i1 > i2 ? 1 : 0;
311  }
312
313  virtual int
314  cmpDatumValue (long idx, const Datum *val)
315  {
316    int32_t i1 = data->fetch (idx);
317    int32_t i2 = val->i;
318    return i1 < i2 ? -1 : i1 > i2 ? 1 : 0;
319  }
320
321private:
322  Vector<int32_t> *data;
323};
324
325class DataUINT32 : public Data
326{
327public:
328
329  DataUINT32 ()
330  {
331    data = new Vector<uint32_t>;
332  }
333
334  virtual
335  ~DataUINT32 ()
336  {
337    delete data;
338  }
339
340  virtual VType_type
341  type ()
342  {
343    return TYPE_UINT32;
344  }
345
346  virtual void
347  reset ()
348  {
349    data->reset ();
350  }
351
352  virtual long
353  getSize ()
354  {
355    return data->size ();
356  }
357
358  virtual int
359  fetchInt (long i)
360  {
361    return (int) data->fetch (i);
362  }
363
364  virtual unsigned long long
365  fetchULong (long i)
366  {
367    return (unsigned long long) data->fetch (i);
368  }
369
370  virtual long long
371  fetchLong (long i)
372  {
373    return (long long) data->fetch (i);
374  }
375
376  virtual char *
377  fetchString (long i)
378  {
379    return dbe_sprintf (NTXT ("%u"), data->fetch (i));
380  }
381
382  virtual double
383  fetchDouble (long i)
384  {
385    return (double) data->fetch (i);
386  }
387
388  virtual void *
389  fetchObject (long)
390  {
391    assert (ASSERT_SKIP);
392    return NULL;
393  }
394
395  virtual void
396  setDatumValue (long idx, const Datum *val)
397  {
398    data->store (idx, val->i);
399  }
400
401  virtual void
402  setValue (long idx, uint64_t val)
403  {
404    data->store (idx, (uint32_t) val);
405  }
406
407  virtual void
408  setObjValue (long, void*)
409  {
410    assert (ASSERT_SKIP);
411    return;
412  }
413
414  virtual int
415  cmpValues (long idx1, long idx2)
416  {
417    uint32_t u1 = data->fetch (idx1);
418    uint32_t u2 = data->fetch (idx2);
419    return u1 < u2 ? -1 : u1 > u2 ? 1 : 0;
420  }
421
422  virtual int
423  cmpDatumValue (long idx, const Datum *val)
424  {
425    uint32_t u1 = data->fetch (idx);
426    uint32_t u2 = (uint32_t) val->i;
427    return u1 < u2 ? -1 : u1 > u2 ? 1 : 0;
428  }
429
430private:
431  Vector<uint32_t> *data;
432};
433
434class DataINT64 : public Data
435{
436public:
437
438  DataINT64 ()
439  {
440    data = new Vector<int64_t>;
441  }
442
443  virtual
444  ~DataINT64 ()
445  {
446    delete data;
447  }
448
449  virtual VType_type
450  type ()
451  {
452    return TYPE_INT64;
453  }
454
455  virtual void
456  reset ()
457  {
458    data->reset ();
459  }
460
461  virtual long
462  getSize ()
463  {
464    return data->size ();
465  }
466
467  virtual int
468  fetchInt (long i)
469  {
470    return (int) data->fetch (i);
471  }
472
473  virtual unsigned long long
474  fetchULong (long i)
475  {
476    return (unsigned long long) data->fetch (i);
477  }
478
479  virtual long long
480  fetchLong (long i)
481  {
482    return (long long) data->fetch (i);
483  }
484
485  virtual char *
486  fetchString (long i)
487  {
488    return dbe_sprintf (NTXT ("%lld"), (long long) data->fetch (i));
489  }
490
491  virtual double
492  fetchDouble (long i)
493  {
494    return (double) data->fetch (i);
495  }
496
497  virtual void *
498  fetchObject (long)
499  {
500    assert (ASSERT_SKIP);
501    return NULL;
502  }
503
504  virtual void
505  setDatumValue (long idx, const Datum *val)
506  {
507    data->store (idx, val->ll);
508  }
509
510  virtual void
511  setValue (long idx, uint64_t val)
512  {
513    data->store (idx, (int64_t) val);
514  }
515
516  virtual void
517  setObjValue (long, void*)
518  {
519    assert (ASSERT_SKIP);
520    return;
521  }
522
523  virtual int
524  cmpValues (long idx1, long idx2)
525  {
526    int64_t i1 = data->fetch (idx1);
527    int64_t i2 = data->fetch (idx2);
528    return i1 < i2 ? -1 : i1 > i2 ? 1 : 0;
529  }
530
531  virtual int
532  cmpDatumValue (long idx, const Datum *val)
533  {
534    int64_t i1 = data->fetch (idx);
535    int64_t i2 = val->ll;
536    return i1 < i2 ? -1 : i1 > i2 ? 1 : 0;
537  }
538
539private:
540  Vector<int64_t> *data;
541};
542
543class DataUINT64 : public Data
544{
545public:
546
547  DataUINT64 ()
548  {
549    data = new Vector<uint64_t>;
550  }
551
552  virtual
553  ~DataUINT64 ()
554  {
555    delete data;
556  }
557
558  virtual VType_type
559  type ()
560  {
561    return TYPE_UINT64;
562  }
563
564  virtual void
565  reset ()
566  {
567    data->reset ();
568  }
569
570  virtual long
571  getSize ()
572  {
573    return data->size ();
574  }
575
576  virtual int
577  fetchInt (long i)
578  {
579    return (int) data->fetch (i);
580  }
581
582  virtual unsigned long long
583  fetchULong (long i)
584  {
585    return (unsigned long long) data->fetch (i);
586  }
587
588  virtual long long
589  fetchLong (long i)
590  {
591    return (long long) data->fetch (i);
592  }
593
594  virtual char *
595  fetchString (long i)
596  {
597    return dbe_sprintf (NTXT ("%llu"), (long long) data->fetch (i));
598  }
599
600  virtual double
601  fetchDouble (long i)
602  {
603    return (double) data->fetch (i);
604  }
605
606  virtual void *
607  fetchObject (long)
608  {
609    assert (ASSERT_SKIP);
610    return NULL;
611  }
612
613  virtual void
614  setDatumValue (long idx, const Datum *val)
615  {
616    data->store (idx, val->ll);
617  }
618
619  virtual void
620  setValue (long idx, uint64_t val)
621  {
622    data->store (idx, val);
623  }
624
625  virtual void
626  setObjValue (long, void*)
627  {
628    assert (ASSERT_SKIP);
629    return;
630  }
631
632  virtual int
633  cmpValues (long idx1, long idx2)
634  {
635    uint64_t u1 = data->fetch (idx1);
636    uint64_t u2 = data->fetch (idx2);
637    return u1 < u2 ? -1 : u1 > u2 ? 1 : 0;
638  }
639
640  virtual int
641  cmpDatumValue (long idx, const Datum *val)
642  {
643    uint64_t u1 = data->fetch (idx);
644    uint64_t u2 = (uint64_t) val->ll;
645    return u1 < u2 ? -1 : u1 > u2 ? 1 : 0;
646  }
647
648private:
649  Vector<uint64_t> *data;
650};
651
652class DataOBJECT : public Data
653{
654public:
655
656  DataOBJECT ()
657  {
658    dtype = TYPE_OBJ;
659    data = new Vector<void*>;
660  }
661
662  DataOBJECT (VType_type _dtype)
663  {
664    dtype = _dtype;
665    data = new Vector<void*>;
666  }
667
668  virtual
669  ~DataOBJECT ()
670  {
671    delete data;
672  }
673
674  virtual VType_type
675  type ()
676  {
677    return dtype;
678  }
679
680  virtual void
681  reset ()
682  {
683    data->reset ();
684  }
685
686  virtual long
687  getSize ()
688  {
689    return data->size ();
690  }
691
692  virtual int
693  fetchInt (long)
694  {
695    assert (ASSERT_SKIP);
696    return 0;
697  }
698
699  virtual unsigned long long
700  fetchULong (long)
701  {
702    assert (ASSERT_SKIP);
703    return 0LL;
704  }
705
706  virtual long long
707  fetchLong (long)
708  {
709    assert (ASSERT_SKIP);
710    return 0LL;
711  }
712
713  virtual char *
714  fetchString (long i)
715  {
716    return dbe_sprintf (NTXT ("%lu"), (unsigned long) data->fetch (i));
717  }
718
719  virtual double
720  fetchDouble (long)
721  {
722    assert (ASSERT_SKIP);
723    return 0.0;
724  }
725
726  virtual void *
727  fetchObject (long i)
728  {
729    return data->fetch (i);
730  }
731
732  virtual void
733  setDatumValue (long idx, const Datum *val)
734  {
735    data->store (idx, val->p);
736  }
737
738  virtual void
739  setValue (long, uint64_t)
740  {
741    assert (ASSERT_SKIP);
742    return;
743  }
744
745  virtual void
746  setObjValue (long idx, void *p)
747  {
748    data->store (idx, p);
749  }
750
751  virtual int
752  cmpValues (long, long)
753  {
754    return 0;
755  }
756
757  virtual int
758  cmpDatumValue (long, const Datum *)
759  {
760    return 0;
761  }
762
763private:
764  VType_type dtype;
765  Vector<void*> *data;
766};
767
768class DataSTRING : public Data
769{
770public:
771
772  DataSTRING ()
773  {
774    data = new Vector<char*>;
775  }
776
777  virtual
778  ~DataSTRING ()
779  {
780    data->destroy ();
781    delete data;
782  }
783
784  virtual VType_type
785  type ()
786  {
787    return TYPE_STRING;
788  }
789
790  virtual void
791  reset ()
792  {
793    data->reset ();
794  }
795
796  virtual long
797  getSize ()
798  {
799    return data->size ();
800  }
801
802  virtual int
803  fetchInt (long)
804  {
805    return 0;
806  }
807
808  virtual unsigned long long
809  fetchULong (long)
810  {
811    return 0LL;
812  }
813
814  virtual long long
815  fetchLong (long)
816  {
817    return 0LL;
818  }
819
820  virtual char *
821  fetchString (long i)
822  {
823    return strdup (data->fetch (i));
824  }
825
826  virtual double
827  fetchDouble (long)
828  {
829    return 0.0;
830  }
831
832  virtual void *
833  fetchObject (long i)
834  {
835    return data->fetch (i);
836  }
837
838  virtual void
839  setDatumValue (long idx, const Datum *val)
840  {
841    data->store (idx, val->l);
842  }
843
844  virtual void
845  setValue (long, uint64_t)
846  {
847    return;
848  }
849
850  virtual void
851  setObjValue (long idx, void *p)
852  {
853    data->store (idx, (char*) p);
854  }
855
856  virtual int
857  cmpValues (long, long)
858  {
859    return 0;
860  }
861
862  virtual int
863  cmpDatumValue (long, const Datum *)
864  {
865    return 0;
866  }
867
868private:
869  Vector<char*> *data;
870};
871
872class DataDOUBLE : public Data
873{
874public:
875
876  DataDOUBLE ()
877  {
878    data = new Vector<double>;
879  }
880
881  virtual
882  ~DataDOUBLE ()
883  {
884    delete data;
885  }
886
887  virtual VType_type
888  type ()
889  {
890    return TYPE_DOUBLE;
891  }
892
893  virtual void
894  reset ()
895  {
896    data->reset ();
897  }
898
899  virtual long
900  getSize ()
901  {
902    return data->size ();
903  }
904
905  virtual int
906  fetchInt (long i)
907  {
908    return (int) data->fetch (i);
909  }
910
911  virtual unsigned long long
912  fetchULong (long i)
913  {
914    return (unsigned long long) data->fetch (i);
915  }
916
917  virtual long long
918  fetchLong (long i)
919  {
920    return (long long) data->fetch (i);
921  }
922
923  virtual char *
924  fetchString (long i)
925  {
926    return dbe_sprintf (NTXT ("%f"), data->fetch (i));
927  }
928
929  virtual double
930  fetchDouble (long i)
931  {
932    return data->fetch (i);
933  }
934
935  virtual void
936  setDatumValue (long idx, const Datum *val)
937  {
938    data->store (idx, val->d);
939  }
940
941  virtual void
942  setValue (long idx, uint64_t val)
943  {
944    data->store (idx, (double) val);
945  }
946
947  virtual void
948  setObjValue (long, void*)
949  {
950    return;
951  }
952
953  virtual void *
954  fetchObject (long)
955  {
956    return NULL;
957  }
958
959  virtual int
960  cmpValues (long idx1, long idx2)
961  {
962    double d1 = data->fetch (idx1);
963    double d2 = data->fetch (idx2);
964    return d1 < d2 ? -1 : d1 > d2 ? 1 : 0;
965  }
966
967  virtual int
968  cmpDatumValue (long idx, const Datum *val)
969  {
970    double d1 = data->fetch (idx);
971    double d2 = val->d;
972    return d1 < d2 ? -1 : d1 > d2 ? 1 : 0;
973  }
974
975private:
976  Vector<double> *data;
977};
978
979Data *
980Data::newData (VType_type vtype)
981{
982  switch (vtype)
983    {
984    case TYPE_INT32:
985      return new DataINT32;
986    case TYPE_UINT32:
987      return new DataUINT32;
988    case TYPE_INT64:
989      return new DataINT64;
990    case TYPE_UINT64:
991      return new DataUINT64;
992    case TYPE_OBJ:
993      return new DataOBJECT;
994    case TYPE_STRING:
995      return new DataSTRING;
996    case TYPE_DOUBLE:
997      return new DataDOUBLE;
998    default:
999      return NULL;
1000    }
1001}
1002
1003/*
1004 *    class DataDescriptor
1005 */
1006DataDescriptor::DataDescriptor (int _id, const char *_name, const char *_uname,
1007				int _flags)
1008{
1009  isMaster = true;
1010  id = _id;
1011  name = _name ? strdup (_name) : strdup (NTXT (""));
1012  uname = _uname ? strdup (_uname) : strdup (NTXT (""));
1013  flags = _flags;
1014
1015  // master data, shared with reference copies:
1016  master_size = 0;
1017  master_resolveFrameInfoDone = false;
1018  props = new Vector<PropDescr*>;
1019  data = new Vector<Data*>;
1020  setsTBR = new Vector<Vector<long long>*>;
1021
1022  // master references point to self:
1023  ref_size = &master_size;
1024  ref_resolveFrameInfoDone = &master_resolveFrameInfoDone;
1025}
1026
1027DataDescriptor::DataDescriptor (int _id, const char *_name, const char *_uname,
1028				DataDescriptor* dDscr)
1029{
1030  isMaster = false;
1031  id = _id;
1032  name = _name ? strdup (_name) : strdup (NTXT (""));
1033  uname = _uname ? strdup (_uname) : strdup (NTXT (""));
1034  flags = dDscr->flags;
1035
1036  // references point to master DataDescriptor
1037  ref_size = &dDscr->master_size;
1038  ref_resolveFrameInfoDone = &dDscr->master_resolveFrameInfoDone;
1039  props = dDscr->props;
1040  data = dDscr->data;
1041  setsTBR = dDscr->setsTBR;
1042
1043  // data that should never be accessed in reference copy
1044  master_size = -1;
1045  master_resolveFrameInfoDone = false;
1046}
1047
1048DataDescriptor::~DataDescriptor ()
1049{
1050  free (name);
1051  free (uname);
1052  if (!isMaster)
1053    return;
1054  props->destroy ();
1055  delete props;
1056  data->destroy ();
1057  delete data;
1058  setsTBR->destroy ();
1059  delete setsTBR;
1060}
1061
1062void
1063DataDescriptor::reset ()
1064{
1065  if (!isMaster)
1066    return;
1067  for (int i = 0; i < data->size (); i++)
1068    {
1069      Data *d = data->fetch (i);
1070      if (d != NULL)
1071	d->reset ();
1072      Vector<long long> *set = setsTBR->fetch (i);
1073      if (set != NULL)
1074	set->reset ();
1075    }
1076  master_size = 0;
1077}
1078
1079PropDescr *
1080DataDescriptor::getProp (int prop_id)
1081{
1082  for (int i = 0; i < props->size (); i++)
1083    {
1084      PropDescr *propDscr = props->fetch (i);
1085      if (propDscr->propID == prop_id)
1086	return propDscr;
1087    }
1088  return NULL;
1089}
1090
1091Data *
1092DataDescriptor::getData (int prop_id)
1093{
1094  if (prop_id < 0 || prop_id >= data->size ())
1095    return NULL;
1096  return data->fetch (prop_id);
1097}
1098
1099void
1100DataDescriptor::addProperty (PropDescr *propDscr)
1101{
1102  if (propDscr == NULL)
1103    return;
1104  if (propDscr->propID < 0)
1105    return;
1106  PropDescr *oldProp = getProp (propDscr->propID);
1107  if (oldProp != NULL)
1108    {
1109      checkCompatibility (propDscr->vtype, oldProp->vtype); //YXXX depends on experiment correctness
1110      delete propDscr;
1111      return;
1112    }
1113  props->append (propDscr);
1114  data->store (propDscr->propID, Data::newData (propDscr->vtype));
1115  setsTBR->store (propDscr->propID, NULL);
1116}
1117
1118long
1119DataDescriptor::addRecord ()
1120{
1121  if (!isMaster)
1122    return -1;
1123  return master_size++;
1124}
1125
1126static void
1127checkEntity (Vector<long long> *set, long long val)
1128{
1129  // Binary search
1130  int lo = 0;
1131  int hi = set->size () - 1;
1132  while (lo <= hi)
1133    {
1134      int md = (lo + hi) / 2;
1135      long long ent = set->fetch (md);
1136      if (ent < val)
1137	lo = md + 1;
1138      else if (ent > val)
1139	hi = md - 1;
1140      else
1141	return;
1142    }
1143  set->insert (lo, val);
1144}
1145
1146void
1147DataDescriptor::setDatumValue (int prop_id, long idx, const Datum *val)
1148{
1149  if (idx >= *ref_size)
1150    return;
1151  Data *d = getData (prop_id);
1152  if (d != NULL)
1153    {
1154      VType_type datum_type = val->type;
1155      VType_type data_type = d->type ();
1156      checkCompatibility (datum_type, data_type);
1157      d->setDatumValue (idx, val);
1158      Vector<long long> *set = setsTBR->fetch (prop_id);
1159      if (set != NULL)// Sets are maintained
1160	checkEntity (set, d->fetchLong (idx));
1161    }
1162}
1163
1164void
1165DataDescriptor::setValue (int prop_id, long idx, uint64_t val)
1166{
1167  if (idx >= *ref_size)
1168    return;
1169  Data *d = getData (prop_id);
1170  if (d != NULL)
1171    {
1172      d->setValue (idx, val);
1173      Vector<long long> *set = setsTBR->fetch (prop_id);
1174      if (set != NULL)// Sets are maintained
1175	checkEntity (set, d->fetchLong (idx));
1176    }
1177}
1178
1179void
1180DataDescriptor::setObjValue (int prop_id, long idx, void *val)
1181{
1182  if (idx >= *ref_size)
1183    return;
1184  Data *d = getData (prop_id);
1185  if (d != NULL)
1186    d->setObjValue (idx, val);
1187}
1188
1189DataView *
1190DataDescriptor::createView ()
1191{
1192  return new DataView (this);
1193}
1194
1195DataView *
1196DataDescriptor::createImmutableView ()
1197{
1198  return new DataView (this, DataView::DV_IMMUTABLE);
1199}
1200
1201DataView *
1202DataDescriptor::createExtManagedView ()
1203{
1204  return new DataView (this, DataView::DV_EXT_MANAGED);
1205}
1206
1207int
1208DataDescriptor::getIntValue (int prop_id, long idx)
1209{
1210  Data *d = getData (prop_id);
1211  if (d == NULL || idx >= d->getSize ())
1212    return 0;
1213  return d->fetchInt (idx);
1214}
1215
1216unsigned long long
1217DataDescriptor::getULongValue (int prop_id, long idx)
1218{
1219  Data *d = getData (prop_id);
1220  if (d == NULL || idx >= d->getSize ())
1221    return 0L;
1222  return d->fetchULong (idx);
1223}
1224
1225long long
1226DataDescriptor::getLongValue (int prop_id, long idx)
1227{
1228  Data *d = getData (prop_id);
1229  if (d == NULL || idx >= d->getSize ())
1230    return 0L;
1231  return d->fetchLong (idx);
1232}
1233
1234void *
1235DataDescriptor::getObjValue (int prop_id, long idx)
1236{
1237  Data *d = getData (prop_id);
1238  if (d == NULL || idx >= d->getSize ())
1239    return NULL;
1240  return d->fetchObject (idx);
1241}
1242
1243static int
1244pcmp (const void *p1, const void *p2, const void *arg)
1245{
1246  long idx1 = *(long*) p1; // index1 into Data
1247  long idx2 = *(long*) p2; // index2 into Data
1248  for (Data **dsorted = (Data**) arg; *dsorted != DATA_SORT_EOL; dsorted++)
1249    {
1250      Data *data = *dsorted;
1251      if (data == NULL)// sort property not in this data, skip this criteria
1252	continue;
1253      int res = data->cmpValues (idx1, idx2);
1254      if (res)
1255	return res;
1256    }
1257  // Provide stable sort
1258  return idx1 < idx2 ? -1 : idx1 > idx2 ? 1 : 0;
1259}
1260
1261Vector<long long> *
1262DataDescriptor::getSet (int prop_id)
1263{
1264  if (prop_id < 0 || prop_id >= setsTBR->size ())
1265    return NULL;
1266  Vector<long long> *set = setsTBR->fetch (prop_id);
1267  if (set != NULL)
1268    return set;
1269
1270  Data *d = getData (prop_id);
1271  if (d == NULL)
1272    return NULL;
1273  set = new Vector<long long>;
1274  for (long i = 0; i<*ref_size; ++i)
1275    checkEntity (set, d->fetchLong (i));
1276  setsTBR->store (prop_id, set);
1277
1278  return set;
1279}
1280
1281/*
1282 *    class DataView
1283 */
1284DataView::DataView (DataDescriptor *_ddscr)
1285{
1286  init (_ddscr, DV_NORMAL);
1287}
1288
1289DataView::DataView (DataDescriptor *_ddscr, DataViewType _type)
1290{
1291  init (_ddscr, _type);
1292}
1293
1294void
1295DataView::init (DataDescriptor *_ddscr, DataViewType _type)
1296{
1297  ddscr = _ddscr;
1298  type = _type;
1299  switch (type)
1300    {
1301    case DV_IMMUTABLE:
1302      ddsize = ddscr->getSize ();
1303      index = NULL;
1304      break;
1305    case DV_NORMAL:
1306    case DV_EXT_MANAGED:
1307      ddsize = 0;
1308      index = new Vector<long>;
1309      break;
1310    }
1311  for (int ii = 0; ii < (MAX_SORT_DIMENSIONS + 1); ii++)
1312    sortedBy[ii] = DATA_SORT_EOL;
1313  filter = NULL;
1314}
1315
1316DataView::~DataView ()
1317{
1318  delete filter;
1319  delete index;
1320}
1321
1322void
1323DataView::appendDataDescriptorId (long pkt_id /* ddscr index */)
1324{
1325  if (type != DV_EXT_MANAGED)
1326    return; // updates allowed only on externally managed DataViews
1327  long curr_ddsize = ddscr->getSize ();
1328  if (pkt_id < 0 || pkt_id >= curr_ddsize)
1329    return; // error!
1330  index->append (pkt_id);
1331}
1332
1333void
1334DataView::setDataDescriptorValue (int prop_id, long pkt_id, uint64_t val)
1335{
1336  ddscr->setValue (prop_id, pkt_id, val);
1337}
1338
1339long long
1340DataView::getDataDescriptorValue (int prop_id, long pkt_id)
1341{
1342  return ddscr->getLongValue (prop_id, pkt_id);
1343}
1344
1345Vector<PropDescr*>*
1346DataView::getProps ()
1347{
1348  return ddscr->getProps ();
1349};
1350
1351PropDescr*
1352DataView::getProp (int prop_id)
1353{
1354  return ddscr->getProp (prop_id);
1355};
1356
1357void
1358DataView::filter_in_chunks (fltr_dbe_ctx *dctx)
1359{
1360  Expression::Context *e_ctx = new Expression::Context (dctx->fltr->ctx->dbev, dctx->fltr->ctx->exp);
1361  Expression *n_expr = dctx->fltr->expr->copy ();
1362  bool noParFilter = dctx->fltr->noParFilter;
1363  FilterExp *nFilter = new FilterExp (n_expr, e_ctx, noParFilter);
1364  long iter = dctx->begin;
1365  long end = dctx->end;
1366  long orig_ddsize = dctx->orig_ddsize;
1367  while (iter < end)
1368    {
1369      nFilter->put (dctx->tmpView, iter);
1370      if (nFilter->passes ())
1371	dctx->idxArr[iter - orig_ddsize] = 1;
1372      iter += 1;
1373    }
1374  delete nFilter;
1375}
1376
1377bool
1378DataView::checkUpdate ()
1379{
1380  long newSize = ddscr->getSize ();
1381  if (ddsize == newSize)
1382    return false;
1383  if (index == NULL)
1384    return false;
1385  if (type == DV_EXT_MANAGED)
1386    return false;
1387  bool updated = false;
1388  if (filter)
1389    {
1390      DataView *tmpView = ddscr->createImmutableView ();
1391      assert (tmpView->getSize () == newSize);
1392      while (ddsize < newSize)
1393	{
1394	  filter->put (tmpView, ddsize);
1395	  if (filter->passes ())
1396	    index->append (ddsize);
1397	  ddsize += 1;
1398	}
1399      delete tmpView;
1400      return updated;
1401    }
1402  while (ddsize < newSize)
1403    {
1404      index->append (ddsize);
1405      updated = true;
1406      ddsize += 1;
1407    }
1408  return updated;
1409}
1410
1411long
1412DataView::getSize ()
1413{
1414  if (checkUpdate () && sortedBy[0] != DATA_SORT_EOL)
1415    // note: after new filter is set, getSize() incurs cost of
1416    // sorting even if caller isn't interested in sort
1417    index->sort ((CompareFunc) pcmp, sortedBy);
1418
1419  if (index == NULL)
1420    return ddscr->getSize ();
1421  return index->size ();
1422}
1423
1424void
1425DataView::setDatumValue (int prop_id, long idx, const Datum *val)
1426{
1427  ddscr->setDatumValue (prop_id, getIdByIdx (idx), val);
1428}
1429
1430void
1431DataView::setValue (int prop_id, long idx, uint64_t val)
1432{
1433  ddscr->setValue (prop_id, getIdByIdx (idx), val);
1434}
1435
1436void
1437DataView::setObjValue (int prop_id, long idx, void *val)
1438{
1439  ddscr->setObjValue (prop_id, getIdByIdx (idx), val);
1440}
1441
1442int
1443DataView::getIntValue (int prop_id, long idx)
1444{
1445  return ddscr->getIntValue (prop_id, getIdByIdx (idx));
1446}
1447
1448unsigned long long
1449DataView::getULongValue (int prop_id, long idx)
1450{
1451  return ddscr->getULongValue (prop_id, getIdByIdx (idx));
1452}
1453
1454long long
1455DataView::getLongValue (int prop_id, long idx)
1456{
1457  return ddscr->getLongValue (prop_id, getIdByIdx (idx));
1458}
1459
1460void *
1461DataView::getObjValue (int prop_id, long idx)
1462{
1463  return ddscr->getObjValue (prop_id, getIdByIdx (idx));
1464}
1465
1466void
1467DataView::sort (const int props[], int prop_count)
1468{
1469  if (index == NULL)
1470    {
1471      assert (ASSERT_SKIP);
1472      return;
1473    }
1474  assert (prop_count >= 0 && prop_count < MAX_SORT_DIMENSIONS);
1475  bool sort_changed = false; // see if sort has changed...
1476  for (int ii = 0; ii <= prop_count; ii++)
1477    { // sortedBy size is prop_count+1
1478      Data *data;
1479      if (ii == prop_count)
1480	data = DATA_SORT_EOL; // special end of array marker
1481      else
1482	data = ddscr->getData (props[ii]);
1483      if (sortedBy[ii] != data)
1484	{
1485	  sortedBy[ii] = data;
1486	  sort_changed = true;
1487	}
1488    }
1489  if (!checkUpdate () && !sort_changed)
1490    return;
1491  index->sort ((CompareFunc) pcmp, sortedBy);
1492}
1493
1494void
1495DataView::sort (int prop0)
1496{
1497  sort (&prop0, 1);
1498}
1499
1500void
1501DataView::sort (int prop0, int prop1)
1502{
1503  int props[2] = {prop0, prop1};
1504  sort (props, 2);
1505}
1506
1507void
1508DataView::sort (int prop0, int prop1, int prop2)
1509{
1510  int props[3] = {prop0, prop1, prop2};
1511  sort (props, 3);
1512}
1513
1514void
1515DataView::setFilter (FilterExp *f)
1516{
1517  if (index == NULL)
1518    {
1519      assert (ASSERT_SKIP);
1520      return;
1521    }
1522  delete filter;
1523  filter = f;
1524  index->reset ();
1525  ddsize = 0;
1526  checkUpdate ();
1527}
1528
1529long
1530DataView::getIdByIdx (long idx)
1531{
1532  if (index == NULL)
1533    return idx;
1534  return index->fetch (idx);
1535}
1536
1537static int
1538tvalcmp (long data_id, const Datum valColumns[], Data *sortedBy[])
1539{
1540  for (int ii = 0; ii < MAX_SORT_DIMENSIONS; ii++)
1541    {
1542      if (sortedBy[ii] == DATA_SORT_EOL)
1543	break;
1544      Data *d = sortedBy[ii];
1545      if (d == NULL)// property doesn't exist in data; compare always matches
1546	continue;
1547      const Datum *tvalue = &valColumns[ii];
1548      int res = d->cmpDatumValue (data_id, tvalue);
1549      if (res)
1550	return res;
1551    }
1552  return 0;
1553}
1554
1555static void
1556checkSortTypes (const Datum valColumns[], Data *sortedBy[])
1557{
1558#ifndef NDEBUG
1559  for (int ii = 0; ii < MAX_SORT_DIMENSIONS; ii++)
1560    {
1561      if (sortedBy[ii] == DATA_SORT_EOL)
1562	break;
1563      Data *d = sortedBy[ii];
1564      if (d == NULL)// property doesn't exist in data; compare always matches
1565	continue;
1566      VType_type datum_type = valColumns[ii].type;
1567      VType_type data_type = d->type ();
1568      checkCompatibility (datum_type, data_type);
1569    }
1570#endif
1571}
1572
1573bool
1574DataView::idxRootDimensionsMatch (long idx, const Datum valColumns[])
1575{
1576  // compares idx vs. valColumns[] - If all dimensions match
1577  // (except sort leaf), then the leaf value is valid => return true.
1578  // Otherwise, return false.
1579  checkSortTypes (valColumns, sortedBy);
1580  if (idx < 0 || idx >= index->size ()) // fell off end of array
1581    return false;
1582  long data_id = index->fetch (idx);
1583
1584  // we will check all dimensions for a match except the "leaf" dimension
1585  for (int ii = 0; ii < (MAX_SORT_DIMENSIONS - 1); ii++)
1586    {
1587      if (sortedBy[ii + 1] == DATA_SORT_EOL)
1588	break; // we are at leaf dimension, don't care about it's value
1589      if (sortedBy[ii] == DATA_SORT_EOL)
1590	break; // end of list
1591      Data *d = sortedBy[ii];
1592      if (d == NULL) // property doesn't exist in data; compare always matches
1593	continue;
1594      const Datum *tvalue = &valColumns[ii];
1595      int res = d->cmpDatumValue (data_id, tvalue);
1596      if (res)
1597	return false;
1598    }
1599  return true;
1600}
1601
1602long
1603DataView::getIdxByVals (const Datum valColumns[], Relation rel)
1604{
1605  // checks sortedBy[] columns for match; relation only used on last column
1606  return getIdxByVals (valColumns, rel, -1, -1);
1607}
1608
1609long
1610DataView::getIdxByVals (const Datum valColumns[], Relation rel,
1611			long minIdx, long maxIdx)
1612{
1613  // checks sortedBy[] columns for match; relation only used on last column
1614  checkSortTypes (valColumns, sortedBy);
1615  if (index == NULL || sortedBy[0] == DATA_SORT_EOL)
1616    return -1;
1617
1618  long lo;
1619  if (minIdx < 0)
1620    lo = 0;
1621  else
1622    lo = minIdx;
1623
1624  long hi;
1625  if (maxIdx < 0 || maxIdx >= index->size ())
1626    hi = index->size () - 1;
1627  else
1628    hi = maxIdx;
1629
1630  long md = -1;
1631  while (lo <= hi)
1632    {
1633      md = (lo + hi) / 2;
1634      int cmp = tvalcmp (index->fetch (md), valColumns, sortedBy);
1635      if (cmp < 0)
1636	{
1637	  lo = md + 1;
1638	  continue;
1639	}
1640      else if (cmp > 0)
1641	{
1642	  hi = md - 1;
1643	  continue;
1644	}
1645
1646      // cmp == 0, we have an exact match
1647      switch (rel)
1648	{
1649	case REL_LT:
1650	  hi = md - 1; // continue searching
1651	  break;
1652	case REL_GT:
1653	  lo = md + 1; // continue searching
1654	  break;
1655	case REL_LTEQ:
1656	case REL_GTEQ:
1657	case REL_EQ:
1658	  // note: "md" may not be deterministic if multiple matches exist
1659	  return md; // a match => done.
1660	}
1661    }
1662
1663  // no exact match found
1664  switch (rel)
1665    {
1666    case REL_LT:
1667    case REL_LTEQ:
1668      md = hi;
1669      break;
1670    case REL_GT:
1671    case REL_GTEQ:
1672      md = lo;
1673      break;
1674    case REL_EQ:
1675      return -1;
1676    }
1677  if (idxRootDimensionsMatch (md, valColumns))
1678    return md;
1679  return -1;
1680}
1681
1682void
1683DataView::removeDbeViewIdx (long idx)
1684{
1685  index->remove (idx);
1686}
1687
1688