1 /*
2 Copyright (C) 2003-2008 MySQL AB, 2008 Sun Microsystems, Inc.
3 All rights reserved. Use is subject to license terms.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License, version 2.0,
7 as published by the Free Software Foundation.
8
9 This program is also distributed with certain software (including
10 but not limited to OpenSSL) that is licensed under separate terms,
11 as designated in a particular file or component or in included license
12 documentation. The authors of MySQL hereby grant you an additional
13 permission to link the program and your derivative works with the
14 separately licensed software that they have included with MySQL.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License, version 2.0, for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 */
25
26 #ifndef NDB_OBJECT_ID_MAP_HPP
27 #define NDB_OBJECT_ID_MAP_HPP
28
29 #include <ndb_global.h>
30 #include <NdbOut.hpp>
31
32 #include <EventLogger.hpp>
33 extern EventLogger * g_eventLogger;
34
35 //#define DEBUG_OBJECTMAP
36
37 /**
38 * Global ObjectMap
39 */
40 class NdbObjectIdMap
41 {
42 public:
43 STATIC_CONST( InvalidId = 0x7fffffff );
44 NdbObjectIdMap(Uint32 initalSize, Uint32 expandSize);
45 ~NdbObjectIdMap();
46
47 Uint32 map(void * object);
48 void * unmap(Uint32 id, void *object);
49
50 void * getObject(Uint32 id);
51 private:
52 const Uint32 m_expandSize;
53 Uint32 m_size;
54 Uint32 m_firstFree;
55 /**
56 * We put released entries at the end of the free list. That way, we delay
57 * re-use of an object id as long as possible. This minimizes the chance
58 * of sending an incoming message to the wrong object because the recipient
59 * object id was reused.
60 */
61 Uint32 m_lastFree;
62
63 class MapEntry
64 {
65 public:
isFree() const66 bool isFree() const
67 {
68 return (m_val & 1) == 1;
69 }
70
getNext() const71 Uint32 getNext() const
72 {
73 assert(isFree());
74 return static_cast<Uint32>(m_val >> 1);
75 }
76
setNext(Uint32 next)77 void setNext(Uint32 next)
78 {
79 m_val = (next << 1) | 1;
80 }
81
getObj() const82 void* getObj() const
83 {
84 assert((m_val & 3) == 0);
85 return reinterpret_cast<void*>(m_val);
86 }
87
setObj(void * obj)88 void setObj(void* obj)
89 {
90 m_val = reinterpret_cast<UintPtr>(obj);
91 assert((m_val & 3) == 0);
92 }
93
94 private:
95 /**
96 * This holds either a pointer to a mapped object *or* the index of the
97 * next entry in the free list. If it is a pointer, then the two least
98 * significant bits should be zero (requiring all mapped objects to be
99 * four-byte aligned). If it is an index, then bit 0 should be set.
100 */
101 UintPtr m_val;
102 };
103
104 MapEntry* m_map;
105
106 int expand(Uint32 newSize);
107 // For debugging purposes.
108 bool checkConsistency();
109 };
110
111 inline
112 Uint32
map(void * object)113 NdbObjectIdMap::map(void * object)
114 {
115 if(m_firstFree == InvalidId && expand(m_expandSize))
116 return InvalidId;
117
118 const Uint32 ff = m_firstFree;
119 m_firstFree = m_map[ff].getNext();
120 m_map[ff].setObj(object);
121
122 DBUG_PRINT("info",("NdbObjectIdMap::map(0x%lx) %u", (long) object, ff<<2));
123
124 return ff<<2;
125 }
126
127 inline
128 void *
unmap(Uint32 id,void * object)129 NdbObjectIdMap::unmap(Uint32 id, void *object)
130 {
131 const Uint32 i = id>>2;
132
133 assert(i < m_size);
134 if(i < m_size)
135 {
136 void * const obj = m_map[i].getObj();
137 if (object == obj)
138 {
139 m_map[i].setNext(InvalidId);
140 if (m_firstFree == InvalidId)
141 {
142 m_firstFree = i;
143 }
144 else
145 {
146 m_map[m_lastFree].setNext(i);
147 }
148 m_lastFree = i;
149 }
150 else
151 {
152 g_eventLogger->error("NdbObjectIdMap::unmap(%u, 0x%lx) obj=0x%lx",
153 id, (long) object, (long) obj);
154 DBUG_PRINT("error",("NdbObjectIdMap::unmap(%u, 0x%lx) obj=0x%lx",
155 id, (long) object, (long) obj));
156 assert(false);
157 return 0;
158 }
159
160 DBUG_PRINT("info",("NdbObjectIdMap::unmap(%u) obj=0x%lx", id, (long) obj));
161
162 return obj;
163 }
164 return 0;
165 }
166
167 inline void *
getObject(Uint32 id)168 NdbObjectIdMap::getObject(Uint32 id)
169 {
170 // DBUG_PRINT("info",("NdbObjectIdMap::getObject(%u) obj=0x%x", id, m_map[id>>2].m_obj));
171 id >>= 2;
172 assert(id < m_size);
173 if(id < m_size)
174 {
175 if(m_map[id].isFree())
176 {
177 return 0;
178 }
179 else
180 {
181 return m_map[id].getObj();
182 }
183 }
184 return 0;
185 }
186 #endif
187