summaryrefslogtreecommitdiff
path: root/storage/ndb/include/ndbapi/NdbIndexStat.hpp
blob: cf457716dd98364d21f1d2960adc26ee8a9a2930 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/* Copyright (C) 2003 MySQL AB

   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; version 2 of the License.

   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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA */

#ifndef NdbIndexStat_H
#define NdbIndexStat_H

#include <ndb_global.h>
#include <NdbDictionary.hpp>
#include <NdbError.hpp>
class NdbIndexImpl;
class NdbIndexScanOperation;

/*
 * Statistics for an ordered index.
 */
class NdbIndexStat {
public:
  NdbIndexStat(const NdbDictionary::Index* index);
  ~NdbIndexStat();
  /*
   * Allocate memory for cache.  Argument is minimum number of stat
   * entries and applies to lower and upper bounds separately.  More
   * entries may fit (keys have variable size).  If not used, db is
   * contacted always.
   */
  int alloc_cache(Uint32 entries);
  /*
   * Flags for records_in_range.
   */
  enum {
    RR_UseDb = 1,       // contact db
    RR_NoUpdate = 2     // but do not update cache
  };
  /*
   * Estimate how many index records need to be scanned.  The scan
   * operation must be prepared with lock mode LM_CommittedRead and must
   * have the desired bounds set.  The routine may use local cache or
   * may contact db by executing the operation.
   *
   * If returned count is zero then db was contacted and the count is
   * exact.  Otherwise the count is approximate.  If cache is used then
   * caller must provide estimated number of table rows.  It will be
   * multiplied by a percentage obtained from the cache (result zero is
   * returned as 1).
   */
  int records_in_range(const NdbDictionary::Index* index,
                       NdbIndexScanOperation* op,
                       Uint64 table_rows,
                       Uint64* count,
                       int flags);
  /*
   * Get latest error.
   */
  const NdbError& getNdbError() const;

private:
  /*
   * There are 2 areas: start keys and end keys.  An area has pointers
   * at beginning and entries at end.  Pointers are sorted by key.
   *
   * A pointer contains entry offset and also entry timestamp.  An entry
   * contains the key and percentage of rows _not_ satisfying the bound
   * i.e. less than start key or greater than end key.
   *
   * A key is an array of index key bounds.  Each has type (0-4) in
   * first word followed by data with AttributeHeader.
   *
   * Stat update comes as pair of start and end key and associated
   * percentages.  Stat query takes best match of start and end key from
   * each area separately.  Rows in range percentage is then computed by
   * excluding the two i.e. as 100 - (start key pct + end key pct).
   *
   * TODO use more compact key format
   */
  struct Pointer;
  friend struct Pointer;
  struct Entry;
  friend struct Entry;
  struct Area;
  friend struct Area;
  struct Pointer {
    Uint16 m_pos;
    Uint16 m_seq;
  };
  struct Entry {
    float m_pct;
    Uint32 m_keylen;
  };
  STATIC_CONST( EntrySize = sizeof(Entry) >> 2 );
  STATIC_CONST( PointerSize = sizeof(Pointer) >> 2 );
  struct Area {
    Uint32* m_data;
    Uint32 m_offset;
    Uint32 m_free;
    Uint16 m_entries;
    Uint8 m_idir;
    Uint8 pad1;
    Area() {}
    Pointer& get_pointer(unsigned i) const {
      return *(Pointer*)&m_data[i];
    }
    Entry& get_entry(unsigned i) const {
      return *(Entry*)&m_data[get_pointer(i).m_pos];
    }
    Uint32 get_pos(const Entry& e) const {
      return (const Uint32*)&e - m_data;
    }
    unsigned get_firstpos() const {
      return PointerSize * m_entries + m_free;
    }
  };
  const NdbIndexImpl& m_index;
  Uint32 m_areasize;
  Uint16 m_seq;
  Area m_area[2];
  Uint32* m_cache;
  NdbError m_error;
#ifdef VM_TRACE
  void stat_verify();
#endif
  int stat_cmpkey(const Area& a, const Uint32* key1, Uint32 keylen1,
                  const Uint32* key2, Uint32 keylen2);
  int stat_search(const Area& a, const Uint32* key, Uint32 keylen,
                  Uint32* idx, bool* match);
  int stat_oldest(const Area& a);
  int stat_delete(Area& a, Uint32 k);
  int stat_update(const Uint32* key1, Uint32 keylen1,
                  const Uint32* key2, Uint32 keylen2, const float pct[2]);
  int stat_select(const Uint32* key1, Uint32 keylen1,
                  const Uint32* key2, Uint32 keylen2, float pct[2]);
  void set_error(int code);
};

#endif