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, 2005, 2006 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
|