1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.tikv.common.catalog;
19
20 import static org.tikv.common.codec.MetaCodec.KEY_DBs;
21
22 import com.fasterxml.jackson.core.JsonParseException;
23 import com.fasterxml.jackson.databind.JsonMappingException;
24 import com.fasterxml.jackson.databind.ObjectMapper;
25 import com.google.common.collect.ImmutableList;
26 import com.google.protobuf.ByteString;
27 import java.nio.charset.StandardCharsets;
28 import java.util.List;
29 import java.util.Objects;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32 import org.tikv.common.Snapshot;
33 import org.tikv.common.codec.CodecDataInput;
34 import org.tikv.common.codec.KeyUtils;
35 import org.tikv.common.codec.MetaCodec;
36 import org.tikv.common.exception.TiClientInternalException;
37 import org.tikv.common.meta.TiDBInfo;
38 import org.tikv.common.meta.TiTableInfo;
39 import org.tikv.common.util.Pair;
40
41 public class CatalogTransaction {
42 protected static final Logger logger = LoggerFactory.getLogger(CatalogTransaction.class);
43 private final Snapshot snapshot;
44
45 CatalogTransaction(Snapshot snapshot) {
46 this.snapshot = snapshot;
47 }
48
49 public static <T> T parseFromJson(ByteString json, Class<T> cls) {
50 Objects.requireNonNull(json, "json is null");
51 Objects.requireNonNull(cls, "cls is null");
52
53 logger.debug(String.format("Parse Json %s : %s", cls.getSimpleName(), json.toStringUtf8()));
54 ObjectMapper mapper = new ObjectMapper();
55 try {
56 return mapper.readValue(json.toStringUtf8(), cls);
57 } catch (JsonParseException | JsonMappingException e) {
58 String errMsg =
59 String.format(
60 "Invalid JSON value for Type %s: %s\n", cls.getSimpleName(), json.toStringUtf8());
61 throw new TiClientInternalException(errMsg, e);
62 } catch (Exception e1) {
63 throw new TiClientInternalException("Error parsing Json", e1);
64 }
65 }
66
67 long getLatestSchemaVersion() {
68 ByteString versionBytes = MetaCodec.bytesGet(MetaCodec.KEY_SCHEMA_VERSION, this.snapshot);
69 CodecDataInput cdi = new CodecDataInput(versionBytes.toByteArray());
70 return Long.parseLong(new String(cdi.toByteArray(), StandardCharsets.UTF_8));
71 }
72
73 public List<TiDBInfo> getDatabases() {
74 List<Pair<ByteString, ByteString>> fields =
75 MetaCodec.hashGetFields(MetaCodec.KEY_DBs, this.snapshot);
76 ImmutableList.Builder<TiDBInfo> builder = ImmutableList.builder();
77 for (Pair<ByteString, ByteString> pair : fields) {
78 builder.add(parseFromJson(pair.second, TiDBInfo.class));
79 }
80 return builder.build();
81 }
82
83 TiDBInfo getDatabase(long id) {
84 ByteString dbKey = MetaCodec.encodeDatabaseID(id);
85 ByteString json = MetaCodec.hashGet(KEY_DBs, dbKey, this.snapshot);
86 if (json == null || json.isEmpty()) {
87 return null;
88 }
89 return parseFromJson(json, TiDBInfo.class);
90 }
91
92 List<TiTableInfo> getTables(long dbId) {
93 ByteString dbKey = MetaCodec.encodeDatabaseID(dbId);
94 List<Pair<ByteString, ByteString>> fields = MetaCodec.hashGetFields(dbKey, this.snapshot);
95 ImmutableList.Builder<TiTableInfo> builder = ImmutableList.builder();
96 for (Pair<ByteString, ByteString> pair : fields) {
97 if (KeyUtils.hasPrefix(pair.first, ByteString.copyFromUtf8(MetaCodec.KEY_TABLE))) {
98 try {
99 TiTableInfo tableInfo = parseFromJson(pair.second, TiTableInfo.class);
100 if (!tableInfo.isSequence()) {
101 builder.add(tableInfo);
102 }
103 } catch (TiClientInternalException e) {
104 logger.warn("fail to parse table from json!", e);
105 }
106 }
107 }
108 return builder.build();
109 }
110 }