(root)/
binutils-2.41/
gprofng/
src/
Table.h
       1  /* Copyright (C) 2021-2023 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  #ifndef _TABLE_H
      22  #define _TABLE_H
      23  
      24  #include "vec.h"
      25  #include "Map2D.h"
      26  
      27  #include "dbe_structs.h"
      28  
      29  class FilterExp;
      30  struct PropDescr;
      31  struct FieldDescr;
      32  class PacketDescriptor;
      33  class DataDescriptor;
      34  class DataView;
      35  
      36  // Note: order must match VTYPE_TYPE_NAMES, below
      37  
      38  enum VType_type
      39  {
      40    TYPE_NONE,
      41    TYPE_INT32,
      42    TYPE_UINT32,
      43    TYPE_INT64,
      44    TYPE_UINT64,
      45    TYPE_STRING,
      46    TYPE_DOUBLE,
      47    TYPE_OBJ,
      48    TYPE_DATE, // Used in FieldDescr only, mapped to TYPE_UINT64 in PropDescr
      49    TYPE_BOOL, // Used only to describe filter props
      50    TYPE_ENUM, // Used only to describe filter props
      51  
      52    TYPE_LAST
      53  };
      54  
      55  #define VTYPE_TYPE_NAMES \
      56  { \
      57      NTXT("NONE"), \
      58      NTXT("INT32"), \
      59      NTXT("UINT32"), \
      60      NTXT("INT64"), \
      61      NTXT("UINT64"), \
      62      NTXT("STRING"), \
      63      NTXT("DOUBLE"), \
      64      NTXT("OBJECT"), \
      65      NTXT("DATE"), \
      66      NTXT("BOOL"), \
      67      NTXT("ENUM") \
      68  }
      69  
      70  // Note: order must match PROFDATA_TYPE_NAMES and PROFDATA_TYPE_UNAMES, below
      71  
      72  enum ProfData_type
      73  { // a.k.a "data_id" (not the same as Pckt_type "kind")
      74    DATA_SAMPLE,      // Traditional collect "Samples"
      75    DATA_GCEVENT,     // Java Garbage Collection events
      76    DATA_HEAPSZ,      // heap size tracking based on heap tracing data
      77    DATA_CLOCK,       // clock profiling data
      78    DATA_HWC,         // hardware counter profiling data
      79    DATA_SYNCH,       // synchronization tracing data
      80    DATA_HEAP,        // heap tracing data
      81    DATA_MPI,         // MPI tracing data
      82    DATA_RACE,        // data race detection data
      83    DATA_DLCK,        // deadlock detection data
      84    DATA_OMP,         // OpenMP profiling data (fork events)
      85    DATA_OMP2,        // OpenMP profiling data (enter thread events)
      86    DATA_OMP3,        // OpenMP profiling data (enter task events)
      87    DATA_OMP4,        // OpenMP profiling data (parreg descriptions)
      88    DATA_OMP5,        // OpenMP profiling data (task descriptions)
      89    DATA_IOTRACE,     // IO tracing data
      90    DATA_LAST
      91  };
      92  
      93  extern char *get_prof_data_type_name (int t);
      94  extern char *
      95  get_prof_data_type_uname (int t);
      96  
      97  enum Prop_type
      98  {
      99    PROP_NONE,
     100    // commonly used properties (libcollector modules, er_print)
     101    PROP_ATSTAMP,     // hrtime_t, Filter: system HRT timestamp;
     102  		    // "Absolute TSTAMP"
     103    PROP_ETSTAMP,     // hrtime_t, Filter: nanoseconds from subexperiment start;
     104  		    // "subExperiment TSTAMP"
     105    PROP_TSTAMP,      // hrtime_t, Packet: system HRT timestamp
     106  		    // Filter: nanoseconds from founder start
     107    PROP_THRID,       // mapped to uint32_t by readPacket
     108    PROP_LWPID,       // mapped to uint32_t by readPacket
     109    PROP_CPUID,       // mapped to uint32_t by readPacket
     110    PROP_FRINFO,      // uint64_t	frinfo
     111    PROP_EVT_TIME,    // hrtime_t Filter: Time delta
     112    // If TSTAMP taken at end of event, EVT_TIME will be positive
     113    // If TSTAMP taken at start of event, EVT_TIME will be negative
     114    // Note: clock and hwc profile events set EVT_TIME=0
     115    //    except Solaris Microstate events where NTICK>1:
     116    //    These will use EVT_TIME=(NTICK-1)*<tick duration>
     117  
     118    // DATA_SAMPLE
     119    PROP_SAMPLE,      // uint64_t sample number
     120    PROP_SMPLOBJ,     // Sample*
     121  
     122    // DATA_GCEVENT
     123    PROP_GCEVENT,     // uint64_t event id
     124    PROP_GCEVENTOBJ,  // GCEvent*
     125  
     126    // DATA_CLOCK
     127    PROP_MSTATE,      // unsigned	ProfilePacket::mstate
     128    PROP_NTICK,       // unsigned	ProfilePacket::value
     129    PROP_OMPSTATE,    // int ProfilePacket::ompstate
     130    PROP_MPISTATE,    // int ProfilePacket::mpistate
     131  
     132    // DATA_SAMPLE     // see PrUsage class, see PROP_MSTATE - TBR?
     133    PROP_UCPU,
     134    PROP_SCPU,
     135    PROP_TRAP,
     136    PROP_TFLT,
     137    PROP_DFLT,
     138    PROP_KFLT,
     139    PROP_ULCK,
     140    PROP_TSLP,
     141    PROP_WCPU,
     142    PROP_TSTP,
     143  
     144    // DATA_SYNCH
     145    PROP_SRQST,       // hrtime_t SyncPacket::requested
     146    PROP_SOBJ,        // Vaddr SyncPacket::objp
     147  
     148    // DATA_HWC
     149    PROP_HWCTAG,      // uint32_t HWCntrPacket::tag;
     150    PROP_HWCINT,      // uint64_t HWCntrPacket::interval
     151    PROP_VADDR,       // Vaddr HWCntrPacket::dbeVA->eaddr
     152    PROP_PADDR,       // Vaddr HWCntrPacket::dbePA->eaddr
     153    PROP_HWCDOBJ,     // DataObject* HWCntrPacket::dobj
     154    PROP_VIRTPC,      // Vaddr HWCntrPacket::eventVPC
     155    PROP_PHYSPC,      // Vaddr HWCntrPacket::eventPPC
     156    PROP_EA_PAGESIZE, // uint32_t HWCntrPacket::ea_pagesize
     157    PROP_PC_PAGESIZE, // uint32_t HWCntrPacket::pc_pagesize
     158    PROP_EA_LGRP,     // uint32_t HWCntrPacket::ea_lgrp
     159    PROP_PC_LGRP,     // uint32_t HWCntrPacket::pc_lgrp
     160    PROP_LWP_LGRP_HOME, // uint32_t HWCntrPacket::lwp_lgrp_home
     161    PROP_PS_LGRP_HOME,  // uint32_t HWCntrPacket::ps_lgrp_home
     162    PROP_MEM_LAT,     // uint64_t HWCntrPacket::latency
     163    PROP_MEM_SRC,     // uint64_t HWCntrPacket::data_source
     164  
     165    // DATA_HEAP
     166    PROP_HTYPE,       // Heap_type HeapPacket::mtype
     167    PROP_HSIZE,       // Size HeapPacket::size (bytes alloc'd by this event)
     168    PROP_HVADDR,      // Vaddr HeapPacket::vaddr
     169    PROP_HOVADDR,     // Vaddr HeapPacket::ovaddr
     170    PROP_HLEAKED,     // Size HeapPacket::leaked (net bytes leaked)
     171    PROP_HMEM_USAGE,  // Size heap memory usage
     172    PROP_HFREED,      // Size (bytes freed by this event)
     173    PROP_HCUR_ALLOCS, // int64_t (net allocations running total.  Recomputed after each filter)
     174    PROP_HCUR_NET_ALLOC, // int64_t (net allocation for this packet.  Recomputed after each filter)
     175    PROP_HCUR_LEAKS,  // Size (net leaks running total.  Recomputed after each filter)
     176  
     177    // DATA_IOTRACE
     178    PROP_IOTYPE,      // IOTrace_type IOTracePacket::iotype
     179    PROP_IOFD,        // int32_t IOTracePacket::fd
     180    PROP_IONBYTE,     // Size_type IOTracePacket::nbyte
     181    PROP_IORQST,      // hrtime_t IOTracePacket::requested
     182    PROP_IOOFD,       // int32_t IOTracePacket::ofd
     183    PROP_IOFSTYPE,    // FileSystem_type IOTracePacket::fstype
     184    PROP_IOFNAME,     // char IOTracePacket::fname
     185    PROP_IOVFD,       // int32_t virtual file descriptor
     186  
     187    // DATA_MPI
     188    PROP_MPITYPE,     // MPI_type MPIPacket::mpitype
     189    PROP_MPISCOUNT,   // Size MPIPacket::scount
     190    PROP_MPISBYTES,   // Size MPIPacket::sbytes
     191    PROP_MPIRCOUNT,   // Size MPIPacket::rcount
     192    PROP_MPIRBYTES,   // Size MPIPacket::rbytes
     193  
     194    // DATA_OMP*
     195    PROP_CPRID,       // uint64_t (Note: not same as "PROP_CPRID" below)
     196    PROP_PPRID,       // uint64_t OMPPacket::omp_pprid
     197    PROP_TSKID,       // uint64_t (Note: not same as "PROP_CPRID" below)
     198    PROP_PTSKID,      // uint64_t OMPPacket::omp_ptskid
     199    PROP_PRPC,        // uint64_t OMPPacket::omp_prpc
     200  
     201    // DATA_RACE
     202    PROP_RTYPE,       // Race_type RacePacket::rtype
     203    PROP_RID,         // uint32_t RacePacket::id
     204    PROP_RVADDR,      // Vaddr RacePacket::vaddr
     205    PROP_RCNT,        // uint32_t RacePacket::count
     206    PROP_LEAFPC,      // Vaddr CommonPacket::leafpc
     207  
     208    // DATA_DLCK
     209    PROP_DID,         // uint32_t DeadlockPacket::id
     210    PROP_DTYPE,       // Deadlock_Lock_type DeadlockPacket::lock_type
     211    PROP_DLTYPE,      // Deadlock_type DeadlockPacket::dl_type
     212    PROP_DVADDR,      // Vaddr DeadlockPacket::lock_addr
     213  
     214    // Synthetic properties (queries only)
     215    PROP_STACKID,
     216    PROP_STACK,       // void* Generic; mapped to M, U, or XSTACK
     217    PROP_MSTACK,      // void* machine stack
     218    PROP_USTACK,      // void* user_stack
     219    PROP_XSTACK,      // void* expert_stack
     220    PROP_HSTACK,      // void* hide_stack
     221    //PROP_CPRID,       // void* (Note: not same as "PROP_CPRID" above)
     222    //PROP_TSKID,       // void* (Note: not same as "PROP_TSKID" above)
     223    PROP_JTHREAD,     // JThread* CommonPacket::jthread
     224    PROP_LEAF,        // uint64_t stack leaf function
     225    PROP_DOBJ,        // "DOBJ" DataObject*
     226    PROP_SAMPLE_MAP,  // Map events to SAMPLE using sample's time range
     227    PROP_GCEVENT_MAP, // Map events to GCEVENT using gcevent's time range
     228    PROP_PID,         // int unix getpid()
     229    PROP_EXPID,       // int Experiment->getUserExpId(), AKA process number, >=1.
     230    PROP_EXPID_CMP,   // int "Comparable PROP_EXPID".  In compare mode, if this
     231    //              process has been matched to another groups' process,
     232    //              returns PROP_EXPID of the matching process with the
     233    //              lowest PROP_EXPGRID value.  Otherwise returns PROP_EXPID.
     234    PROP_EXPGRID,     // int Comparison group number.  >=0, 0 is Baseline.
     235    PROP_PARREG,      // "PARREG" uint64_t (see 6436500) TBR?
     236    PROP_TSTAMP_LO,   // hrtime_t Filter: Event's low TSTAMP
     237    PROP_TSTAMP_HI,   // hrtime_t Filter: Event's high TSTAMP
     238    PROP_TSTAMP2,     // hrtime_t Filter: End TSTAMP (TSTAMP<=TSTAMP2)
     239    PROP_FREQ_MHZ,    // int frequency in MHZ (for converting HWC profiling cycles to time)
     240    PROP_NTICK_USEC,  // hrtime_t Clock profiling interval, microseconds (PROP_NTICK * Experiment->ptimer_usec)
     241    PROP_IOHEAPBYTES, // Size PROP_HSIZE or PROP_IONBYTE
     242    PROP_STACKL,      // void* Generic; mapped to M, U, or XSTACK for DbeLine
     243    PROP_MSTACKL,     // void* machine stack
     244    PROP_USTACKL,     // void* user_stack
     245    PROP_XSTACKL,     // void* expert_stack
     246    PROP_STACKI,      // void* Generic; mapped to M, U, or XSTACK for DbeInstr
     247    PROP_MSTACKI,     // void* machine stack
     248    PROP_USTACKI,     // void* user_stack
     249    PROP_XSTACKI,     // void* expert_stack
     250    PROP_DDSCR_LNK,   // long long index into DataDescriptor table for a related event
     251    PROP_VOIDP_OBJ,   // void* pointer to object containing metadata
     252    PROP_LAST
     253  };
     254  
     255  enum Prop_flag
     256  {
     257    PRFLAG_NOSHOW     = 0x40
     258  };
     259  
     260  struct PropDescr
     261  {
     262    PropDescr (int propID, const char *name);
     263    virtual ~PropDescr ();
     264  
     265    void addState (int value, const char *stname, const char *stuname);
     266    char *getStateName (int value);
     267    char *getStateUName (int value);
     268  
     269    int
     270    getMaxState ()
     271    {
     272      return stateNames ? stateNames->size () : 0;
     273    }
     274  
     275    int propID;
     276    char *name;
     277    char *uname;
     278    VType_type vtype;
     279    int flags;
     280  
     281  private:
     282    Vector<char*>*stateNames;
     283    Vector<char*>*stateUNames;
     284  };
     285  
     286  struct FieldDescr
     287  {
     288    FieldDescr (int propID, const char *name);
     289    virtual ~FieldDescr ();
     290  
     291    int propID;
     292    char *name;
     293    int offset;
     294    VType_type vtype;
     295    char *format;
     296  };
     297  
     298  class PacketDescriptor
     299  {
     300  public:
     301    PacketDescriptor (DataDescriptor*);
     302    virtual ~PacketDescriptor ();
     303  
     304    DataDescriptor *
     305    getDataDescriptor ()
     306    {
     307      return ddscr;
     308    }
     309  
     310    Vector<FieldDescr*> *
     311    getFields ()
     312    {
     313      return fields;
     314    }
     315  
     316    void addField (FieldDescr*);
     317  
     318  private:
     319    DataDescriptor *ddscr;
     320    Vector<FieldDescr*> *fields;
     321  };
     322  
     323  struct Datum
     324  {
     325  
     326    void
     327    setUINT32 (uint32_t vv)
     328    {
     329      type = TYPE_UINT32;
     330      i = vv;
     331    }
     332  
     333    void
     334    setUINT64 (uint64_t vv)
     335    {
     336      type = TYPE_UINT64;
     337      ll = vv;
     338    }
     339  
     340    void
     341    setSTRING (char* vv)
     342    {
     343      type = TYPE_STRING;
     344      l = vv;
     345    }
     346  
     347    void
     348    setDOUBLE (double vv)
     349    {
     350      type = TYPE_DOUBLE;
     351      d = vv;
     352    }
     353  
     354    void
     355    setOBJ (void* vv)
     356    {
     357      type = TYPE_OBJ;
     358      p = vv;
     359    }
     360  
     361    VType_type type;
     362    union
     363    {
     364      int i;
     365      double d;
     366      char *l;
     367      void *p;
     368      unsigned long long ll;
     369    };
     370  };
     371  
     372  class Data
     373  {
     374  public:
     375    static Data *newData (VType_type);
     376  
     377    virtual
     378    ~Data () { }
     379  
     380    virtual VType_type
     381    type ()
     382    {
     383      return TYPE_NONE;
     384    }
     385    virtual void reset () = 0;
     386    virtual long getSize () = 0;
     387    virtual int fetchInt (long i) = 0;
     388    virtual unsigned long long fetchULong (long i) = 0;
     389    virtual long long fetchLong (long i) = 0;
     390    virtual char *fetchString (long i) = 0;
     391    virtual double fetchDouble (long i) = 0;
     392    virtual void *fetchObject (long i) = 0;
     393    virtual void setDatumValue (long, const Datum*) = 0;
     394    virtual void setValue (long, uint64_t) = 0;
     395    virtual void setObjValue (long, void*) = 0;
     396    virtual int cmpValues (long idx1, long idx2) = 0;
     397    virtual int cmpDatumValue (long idx, const Datum *val) = 0;
     398  };
     399  
     400  enum Data_flag
     401  {
     402    DDFLAG_NOSHOW = 0x01
     403  };
     404  
     405  class DataDescriptor
     406  {
     407    /*
     408     * An instance of this class stores the data packets for a specific
     409     * type of profiling, for example, clock profiling.
     410     *
     411     * Each packet consists of values for various properties.
     412     * For example, a timestamp is a property which is accessed with PROP_TSTAMP.
     413     *
     414     * Ideally, DataDescriptor contents are considered immutable after the
     415     * data is read in.  setValue() should only be used during creation.
     416     * - The packets are in fixed order.  This allows DataDescriptor <pkt_id>
     417     *   to be treated as a stable handle.
     418     * - Sorting/filtering is handled by the DataView class
     419     * - In the future, if we need to add the ability to append new packets,
     420     *   we might add a flag to show when the class is immutable and/or appendible
     421     */
     422  public:
     423  
     424    DataDescriptor (int id, const char* name, const char* uname, int flags = 0); // master
     425    DataDescriptor (int id, const char* name, const char* uname, DataDescriptor*); // reference copy
     426    ~DataDescriptor ();
     427  
     428    // packets' descriptions
     429    int
     430    getId ()
     431    {
     432      return id;
     433    }
     434  
     435    char *
     436    getName ()
     437    {
     438      return name;
     439    }
     440  
     441    char *
     442    getUName ()
     443    {
     444      return uname;
     445    }
     446  
     447    Vector<PropDescr*> *
     448    getProps ()
     449    {
     450      return props;       // packet properties
     451    }
     452    PropDescr *getProp (int prop_id);     // packet property
     453  
     454    long
     455    getSize ()
     456    {
     457      return *ref_size;   // number of packets
     458    }
     459  
     460    long
     461    getFlags ()
     462    {
     463      return flags;
     464    }
     465  
     466    // class to provide sorting and filtering
     467    DataView *createView ();
     468    DataView *createImmutableView ();
     469    DataView *createExtManagedView ();
     470  
     471    // packet property values (<pkt_id> is stable packet handle)
     472    int getIntValue (int prop_id, long pkt_id);
     473    unsigned long long getULongValue (int prop_id, long pkt_id);
     474    long long getLongValue (int prop_id, long pkt_id);
     475    void *getObjValue (int prop_id, long pkt_id);
     476    Vector<long long> *getSet (int prop_id); // list of sorted, unique values
     477  
     478    // table creation/reset
     479    void addProperty (PropDescr*); // add property to all packets
     480    long addRecord ();            // add packet
     481    Data *getData (int prop_id);  // get all packets
     482    void setDatumValue (int prop_id, long pkt_id, const Datum *val);
     483    void setValue (int prop_id, long pkt_id, uint64_t val);
     484    void setObjValue (int prop_id, long pkt_id, void *val);
     485    void reset ();                // remove all packets (ym: TBR?)
     486  
     487    void
     488    setResolveFrInfoDone ()
     489    {
     490      *ref_resolveFrameInfoDone = true;
     491    }
     492  
     493    bool
     494    isResolveFrInfoDone ()
     495    {
     496      return *ref_resolveFrameInfoDone;
     497    }
     498  
     499  
     500  private:
     501    bool isMaster;
     502    int flags;        // see Data_flag enum
     503    int id;
     504    char *name;
     505    char *uname;
     506  
     507    // the following should only be accessed if parent==NULL
     508    long master_size;
     509    bool master_resolveFrameInfoDone;
     510  
     511    // the following point to the master DataDescriptor's fields
     512    long *ref_size;
     513    bool *ref_resolveFrameInfoDone;
     514    Vector<PropDescr*> *props;
     515    Vector<Data*> *data;
     516    Vector<Vector<long long>*> *setsTBR; // Sets of unique values
     517  };
     518  
     519  typedef struct
     520  {
     521    long begin;
     522    long end;
     523    long orig_ddsize;
     524    DataView *tmpView;
     525    long *idxArr;
     526    FilterExp *fltr;
     527  } fltr_dbe_ctx;
     528  
     529  class DataView
     530  {
     531    /*
     532     * Provides sorting and filtering of DataDescriptor packets
     533     */
     534  public:
     535  
     536    enum Relation
     537    {
     538      REL_LT,
     539      REL_LTEQ,
     540      REL_EQ,
     541      REL_GTEQ,
     542      REL_GT
     543    };
     544  
     545    enum DataViewType
     546    {
     547      DV_NORMAL,      // filterable, sortable
     548      DV_IMMUTABLE,   // reflects exact data in DataDescriptor
     549      DV_EXT_MANAGED  // sortable.  index[] entries managed externally.
     550    };
     551  
     552    DataView (DataDescriptor*);
     553    DataView (DataDescriptor*, DataViewType);
     554    virtual ~DataView ();
     555  
     556    Vector<PropDescr*> *getProps ();
     557    PropDescr *getProp (int prop_id);
     558    long getSize ();      // number of post-filter packets
     559  
     560    // packet property values accessed by sort index (not DataDescriptor pkt_id)
     561    int getIntValue (int prop_id, long idx);
     562    unsigned long long getULongValue (int prop_id, long idx);
     563    long long getLongValue (int prop_id, long idx);
     564    void *getObjValue (int prop_id, long idx);
     565    long getIdByIdx (long idx);   // returns DataDescriptor pkt_id
     566  
     567    // define sort/filter
     568    void sort (const int props[], int prop_count);
     569    void sort (int prop);
     570    void sort (int prop1, int prop2);
     571    void sort (int prop1, int prop2, int prop3);
     572    void setFilter (FilterExp*);
     573  
     574    // search packets
     575    // - sort must already be defined
     576    // - requires the user to provide all properties used in current sort.
     577    // - For a match, the all but the last sort property (the "leaf")
     578    //   must match exactly.
     579    long getIdxByVals (const Datum valColumns[], Relation rel);
     580    long getIdxByVals (const Datum valColumns[], Relation rel,
     581  		     long minIdx, long maxIdx); //limit idx search range
     582    bool idxRootDimensionsMatch (long idx, const Datum valColumns[]);
     583    // packet at idx matches all non-leaf values in valColumns
     584  
     585    // use during table creation, updates underlying DataDescriptor
     586    void setDatumValue (int prop_id, long idx, const Datum *val);
     587    void setValue (int prop_id, long idx, uint64_t val);
     588    void setObjValue (int prop_id, long idx, void *val);
     589  
     590    DataDescriptor *
     591    getDataDescriptor ()
     592    {
     593      return ddscr;
     594    }
     595  
     596    void removeDbeViewIdx (long idx);
     597  
     598    // for use with DV_EXT_MANAGED DataViews:
     599    void appendDataDescriptorId (long pkt_id);
     600    void setDataDescriptorValue (int prop_id, long pkt_id, uint64_t val);
     601    long long getDataDescriptorValue (int prop_id, long pkt_id);
     602  
     603  private:
     604    bool checkUpdate ();
     605    void init (DataDescriptor*, DataViewType);
     606  
     607    static void filter_in_chunks (fltr_dbe_ctx *dctx);
     608    DataDescriptor *ddscr;
     609    long ddsize;
     610    Vector<long> *index; // sorted vector of data_id (index into dDscr)
     611  #define MAX_SORT_DIMENSIONS 10
     612  #define DATA_SORT_EOL ((Data *) -1)     /* marks end of sortedBy[] array */
     613    Data *sortedBy[MAX_SORT_DIMENSIONS + 1]; // columns for sort
     614    FilterExp *filter;
     615    DataViewType type;
     616  };
     617  
     618  #endif /* _TABLE_H */