1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.tikv.common.region;
18
19 import static org.tikv.common.codec.KeyUtils.formatBytesUTF8;
20 import static org.tikv.common.util.KeyRangeUtils.makeRange;
21
22 import com.google.common.collect.RangeMap;
23 import com.google.common.collect.TreeRangeMap;
24 import com.google.protobuf.ByteString;
25 import java.util.ArrayList;
26 import java.util.HashMap;
27 import java.util.List;
28 import java.util.Map;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31 import org.tikv.common.key.Key;
32 import org.tikv.common.util.BackOffer;
33
34 public class RegionCache {
35 private static final Logger logger = LoggerFactory.getLogger(RegionCache.class);
36
37 private final Map<Long, TiRegion> regionCache;
38 private final Map<Long, TiStore> storeCache;
39 private final RangeMap<Key, Long> keyToRegionIdCache;
40
41 public RegionCache() {
42 regionCache = new HashMap<>();
43 storeCache = new HashMap<>();
44
45 keyToRegionIdCache = TreeRangeMap.create();
46 }
47
48 public synchronized void invalidateAll() {
49 regionCache.clear();
50 storeCache.clear();
51 keyToRegionIdCache.clear();
52 }
53
54 public synchronized TiRegion getRegionByKey(ByteString key, BackOffer backOffer) {
55 Long regionId;
56 if (key.isEmpty()) {
57
58 regionId = keyToRegionIdCache.get(Key.toRawKey(key, true));
59 } else {
60 regionId = keyToRegionIdCache.get(Key.toRawKey(key));
61 }
62 if (logger.isDebugEnabled()) {
63 logger.debug(
64 String.format("getRegionByKey key[%s] -> ID[%s]", formatBytesUTF8(key), regionId));
65 }
66
67 if (regionId == null) {
68 return null;
69 }
70 TiRegion region;
71 region = regionCache.get(regionId);
72 if (logger.isDebugEnabled()) {
73 logger.debug(String.format("getRegionByKey ID[%s] -> Region[%s]", regionId, region));
74 }
75 return region;
76 }
77
78 public synchronized TiRegion putRegion(TiRegion region) {
79 if (logger.isDebugEnabled()) {
80 logger.debug("putRegion: " + region);
81 }
82 TiRegion oldRegion = regionCache.get(region.getId());
83 if (oldRegion != null) {
84 if (oldRegion.getMeta().equals(region.getMeta())) {
85 return oldRegion;
86 } else {
87 invalidateRegion(oldRegion);
88 }
89 }
90 regionCache.put(region.getId(), region);
91 keyToRegionIdCache.put(makeRange(region.getStartKey(), region.getEndKey()), region.getId());
92 return region;
93 }
94
95 @Deprecated
96 public synchronized TiRegion getRegionById(long regionId) {
97 TiRegion region = regionCache.get(regionId);
98 if (logger.isDebugEnabled()) {
99 logger.debug(String.format("getRegionByKey ID[%s] -> Region[%s]", regionId, region));
100 }
101 return region;
102 }
103
104 private synchronized TiRegion getRegionFromCache(long regionId) {
105 return regionCache.get(regionId);
106 }
107
108
109 public synchronized void invalidateRegion(TiRegion region) {
110 try {
111 if (logger.isDebugEnabled()) {
112 logger.debug(String.format("invalidateRegion ID[%s]", region.getId()));
113 }
114 TiRegion oldRegion = regionCache.get(region.getId());
115 if (oldRegion != null && oldRegion == region) {
116 keyToRegionIdCache.remove(makeRange(region.getStartKey(), region.getEndKey()));
117 regionCache.remove(region.getId());
118 }
119 } catch (Exception ignore) {
120 }
121 }
122
123 public synchronized void insertRegionToCache(TiRegion region) {
124 try {
125 TiRegion oldRegion = regionCache.get(region.getId());
126 if (oldRegion != null) {
127 keyToRegionIdCache.remove(makeRange(oldRegion.getStartKey(), oldRegion.getEndKey()));
128 }
129 regionCache.put(region.getId(), region);
130 keyToRegionIdCache.put(makeRange(region.getStartKey(), region.getEndKey()), region.getId());
131 } catch (Exception ignore) {
132 }
133 }
134
135 public synchronized boolean updateRegion(TiRegion expected, TiRegion region) {
136 try {
137 if (logger.isDebugEnabled()) {
138 logger.debug(String.format("invalidateRegion ID[%s]", region.getId()));
139 }
140 TiRegion oldRegion = regionCache.get(region.getId());
141 if (!expected.getMeta().equals(oldRegion.getMeta())) {
142 return false;
143 } else {
144 if (oldRegion != null) {
145 keyToRegionIdCache.remove(makeRange(oldRegion.getStartKey(), oldRegion.getEndKey()));
146 }
147 regionCache.put(region.getId(), region);
148 keyToRegionIdCache.put(makeRange(region.getStartKey(), region.getEndKey()), region.getId());
149 return true;
150 }
151 } catch (Exception ignore) {
152 return false;
153 }
154 }
155
156 public synchronized boolean updateStore(TiStore oldStore, TiStore newStore) {
157 if (!newStore.isValid()) {
158 return false;
159 }
160 if (oldStore == null) {
161 storeCache.put(newStore.getId(), newStore);
162 return true;
163 }
164 TiStore originStore = storeCache.get(oldStore.getId());
165 if (originStore.equals(oldStore)) {
166 storeCache.put(newStore.getId(), newStore);
167 oldStore.markInvalid();
168 return true;
169 }
170 return false;
171 }
172
173 public synchronized void invalidateAllRegionForStore(TiStore store) {
174 TiStore oldStore = storeCache.get(store.getId());
175 if (oldStore != store) {
176 return;
177 }
178 List<TiRegion> regionToRemove = new ArrayList<>();
179 for (TiRegion r : regionCache.values()) {
180 if (r.getLeader().getStoreId() == store.getId()) {
181 if (logger.isDebugEnabled()) {
182 logger.debug(String.format("invalidateAllRegionForStore Region[%s]", r));
183 }
184 regionToRemove.add(r);
185 }
186 }
187
188 logger.warn(String.format("invalid store [%d]", store.getId()));
189
190 for (TiRegion r : regionToRemove) {
191 keyToRegionIdCache.remove(makeRange(r.getStartKey(), r.getEndKey()));
192 regionCache.remove(r.getId());
193 }
194 }
195
196 public synchronized void invalidateStore(long storeId) {
197 TiStore store = storeCache.remove(storeId);
198 if (store != null) {
199 store.markInvalid();
200 }
201 }
202
203 public synchronized TiStore getStoreById(long id) {
204 return storeCache.get(id);
205 }
206
207 public synchronized boolean putStore(long id, TiStore store) {
208 TiStore oldStore = storeCache.get(id);
209 if (oldStore != null) {
210 if (oldStore.equals(store)) {
211 return false;
212 } else {
213 oldStore.markInvalid();
214 }
215 }
216 storeCache.put(id, store);
217 return true;
218 }
219
220 public synchronized void clearAll() {
221 keyToRegionIdCache.clear();
222 regionCache.clear();
223 }
224 }