Commit 92d360e14b61115f5a62ef7a43de2502fd87640c
Committed by
Andrew Shvayka
1 parent
bd42cfc8
Refactoring of migration tool for new Thingsboard DB structure
Showing
8 changed files
with
225 additions
and
76 deletions
... | ... | @@ -56,8 +56,9 @@ |
56 | 56 | <artifactId>cassandra-all</artifactId> |
57 | 57 | </dependency> |
58 | 58 | <dependency> |
59 | - <groupId>com.datastax.oss</groupId> | |
60 | - <artifactId>java-driver-core</artifactId> | |
59 | + <groupId>com.datastax.cassandra</groupId> | |
60 | + <artifactId>cassandra-driver-core</artifactId> | |
61 | + <version>3.10.1</version> | |
61 | 62 | </dependency> |
62 | 63 | <dependency> |
63 | 64 | <groupId>commons-io</groupId> | ... | ... |
1 | +package org.thingsboard.client.tools.migrator; | |
2 | + | |
3 | +import org.apache.commons.io.FileUtils; | |
4 | +import org.apache.commons.io.LineIterator; | |
5 | +import org.apache.commons.lang3.StringUtils; | |
6 | + | |
7 | +import java.io.File; | |
8 | +import java.io.IOException; | |
9 | +import java.util.HashMap; | |
10 | +import java.util.Map; | |
11 | + | |
12 | +public class DictionaryParser { | |
13 | + private Map<String, String> dictionaryParsed = new HashMap<>(); | |
14 | + | |
15 | + public DictionaryParser(File sourceFile) throws IOException { | |
16 | + parseDictionaryDump(FileUtils.lineIterator(sourceFile)); | |
17 | + } | |
18 | + | |
19 | + public String getKeyByKeyId(String keyId) { | |
20 | + return dictionaryParsed.get(keyId); | |
21 | + } | |
22 | + | |
23 | + private boolean isBlockFinished(String line) { | |
24 | + return StringUtils.isBlank(line) || line.equals("\\."); | |
25 | + } | |
26 | + | |
27 | + private boolean isBlockStarted(String line) { | |
28 | + return line.startsWith("COPY public.ts_kv_dictionary ("); | |
29 | + } | |
30 | + | |
31 | + private void parseDictionaryDump(LineIterator iterator) { | |
32 | + String tempLine; | |
33 | + while(iterator.hasNext()) { | |
34 | + tempLine = iterator.nextLine(); | |
35 | + | |
36 | + if(isBlockStarted(tempLine)) { | |
37 | + processBlock(iterator); | |
38 | + } | |
39 | + } | |
40 | + } | |
41 | + | |
42 | + private void processBlock(LineIterator lineIterator) { | |
43 | + String tempLine; | |
44 | + String[] lineSplited; | |
45 | + while(lineIterator.hasNext()) { | |
46 | + tempLine = lineIterator.nextLine(); | |
47 | + if(isBlockFinished(tempLine)) { | |
48 | + return; | |
49 | + } | |
50 | + | |
51 | + lineSplited = tempLine.split("\t"); | |
52 | + dictionaryParsed.put(lineSplited[1], lineSplited[0]); | |
53 | + } | |
54 | + } | |
55 | +} | ... | ... |
... | ... | @@ -30,17 +30,25 @@ public class MigratorTool { |
30 | 30 | public static void main(String[] args) { |
31 | 31 | CommandLine cmd = parseArgs(args); |
32 | 32 | |
33 | - | |
34 | 33 | try { |
35 | - File latestSource = new File(cmd.getOptionValue("latestTelemetryFrom")); | |
36 | - File latestSaveDir = new File(cmd.getOptionValue("latestTelemetryOut")); | |
37 | - File tsSource = new File(cmd.getOptionValue("telemetryFrom")); | |
38 | - File tsSaveDir = new File(cmd.getOptionValue("telemetryOut")); | |
39 | - File partitionsSaveDir = new File(cmd.getOptionValue("partitionsOut")); | |
40 | 34 | boolean castEnable = Boolean.parseBoolean(cmd.getOptionValue("castEnable")); |
41 | - | |
42 | - PgCaLatestMigrator.migrateLatest(latestSource, latestSaveDir, castEnable); | |
43 | - PostgresToCassandraTelemetryMigrator.migrateTs(tsSource, tsSaveDir, partitionsSaveDir, castEnable); | |
35 | + File allTelemetrySource = new File(cmd.getOptionValue("telemetryFrom")); | |
36 | + | |
37 | + RelatedEntitiesParser allEntityIdsAndTypes = | |
38 | + new RelatedEntitiesParser(new File(cmd.getOptionValue("relatedEntities"))); | |
39 | + DictionaryParser dictionaryParser = new DictionaryParser(allTelemetrySource); | |
40 | + | |
41 | + if(cmd.getOptionValue("latestTelemetryOut") != null) { | |
42 | + File latestSaveDir = new File(cmd.getOptionValue("latestTelemetryOut")); | |
43 | + PgCaLatestMigrator.migrateLatest(allTelemetrySource, latestSaveDir, allEntityIdsAndTypes, dictionaryParser, castEnable); | |
44 | + } | |
45 | + if(cmd.getOptionValue("telemetryOut") != null) { | |
46 | + File tsSaveDir = new File(cmd.getOptionValue("telemetryOut")); | |
47 | + File partitionsSaveDir = new File(cmd.getOptionValue("partitionsOut")); | |
48 | + PostgresToCassandraTelemetryMigrator.migrateTs( | |
49 | + allTelemetrySource, tsSaveDir, partitionsSaveDir, allEntityIdsAndTypes, dictionaryParser, castEnable | |
50 | + ); | |
51 | + } | |
44 | 52 | |
45 | 53 | } catch (Throwable th) { |
46 | 54 | th.printStackTrace(); |
... | ... | @@ -52,30 +60,30 @@ public class MigratorTool { |
52 | 60 | private static CommandLine parseArgs(String[] args) { |
53 | 61 | Options options = new Options(); |
54 | 62 | |
55 | - Option latestTsOpt = new Option("latestFrom", "latestTelemetryFrom", true, "latest telemetry source file path"); | |
56 | - latestTsOpt.setRequired(true); | |
57 | - options.addOption(latestTsOpt); | |
63 | + Option telemetryAllFrom = new Option("telemetryFrom", "telemetryFrom", true, "telemetry source file"); | |
64 | + telemetryAllFrom.setRequired(true); | |
65 | + options.addOption(telemetryAllFrom); | |
58 | 66 | |
59 | 67 | Option latestTsOutOpt = new Option("latestOut", "latestTelemetryOut", true, "latest telemetry save dir"); |
60 | - latestTsOutOpt.setRequired(true); | |
68 | + latestTsOutOpt.setRequired(false); | |
61 | 69 | options.addOption(latestTsOutOpt); |
62 | 70 | |
63 | - Option tsOpt = new Option("tsFrom", "telemetryFrom", true, "telemetry source file path"); | |
64 | - tsOpt.setRequired(true); | |
65 | - options.addOption(tsOpt); | |
66 | - | |
67 | 71 | Option tsOutOpt = new Option("tsOut", "telemetryOut", true, "sstable save dir"); |
68 | - tsOutOpt.setRequired(true); | |
72 | + tsOutOpt.setRequired(false); | |
69 | 73 | options.addOption(tsOutOpt); |
70 | 74 | |
71 | 75 | Option partitionOutOpt = new Option("partitionsOut", "partitionsOut", true, "partitions save dir"); |
72 | - partitionOutOpt.setRequired(true); | |
76 | + partitionOutOpt.setRequired(false); | |
73 | 77 | options.addOption(partitionOutOpt); |
74 | 78 | |
75 | 79 | Option castOpt = new Option("castEnable", "castEnable", true, "cast String to Double if possible"); |
76 | 80 | castOpt.setRequired(true); |
77 | 81 | options.addOption(castOpt); |
78 | 82 | |
83 | + Option relatedOpt = new Option("relatedEntities", "relatedEntities", true, "related entities source file path"); | |
84 | + relatedOpt.setRequired(true); | |
85 | + options.addOption(relatedOpt); | |
86 | + | |
79 | 87 | HelpFormatter formatter = new HelpFormatter(); |
80 | 88 | CommandLineParser parser = new BasicParser(); |
81 | 89 | ... | ... |
... | ... | @@ -43,14 +43,21 @@ public class PgCaLatestMigrator { |
43 | 43 | private static long castedOk = 0; |
44 | 44 | |
45 | 45 | private static long currentWriterCount = 1; |
46 | - private static CQLSSTableWriter currentTsWriter = null; | |
47 | - | |
48 | - public static void migrateLatest(File sourceFile, File outDir, boolean castStringsIfPossible) throws IOException { | |
46 | + private static RelatedEntitiesParser allIdsAndTypes; | |
47 | + private static DictionaryParser keyPairs; | |
48 | + | |
49 | + public static void migrateLatest(File sourceFile, | |
50 | + File outDir, | |
51 | + RelatedEntitiesParser allEntityIdsAndTypes, | |
52 | + DictionaryParser dictionaryParser, | |
53 | + boolean castStringsIfPossible) throws IOException { | |
49 | 54 | long startTs = System.currentTimeMillis(); |
50 | 55 | long stepLineTs = System.currentTimeMillis(); |
51 | 56 | long stepOkLineTs = System.currentTimeMillis(); |
52 | 57 | LineIterator iterator = FileUtils.lineIterator(sourceFile); |
53 | - currentTsWriter = WriterBuilder.getTsWriter(outDir); | |
58 | + CQLSSTableWriter currentTsWriter = WriterBuilder.getLatestWriter(outDir); | |
59 | + allIdsAndTypes = allEntityIdsAndTypes; | |
60 | + keyPairs = dictionaryParser; | |
54 | 61 | |
55 | 62 | boolean isBlockStarted = false; |
56 | 63 | boolean isBlockFinished = false; |
... | ... | @@ -107,7 +114,7 @@ public class PgCaLatestMigrator { |
107 | 114 | } |
108 | 115 | |
109 | 116 | if (linesMigrated++ % LOG_BATCH == 0) { |
110 | - System.out.println(new Date() + " migrated = " + linesMigrated + " in " + (System.currentTimeMillis() - stepOkLineTs)); | |
117 | + System.out.println(new Date() + " migrated = " + linesMigrated + " in " + (System.currentTimeMillis() - stepOkLineTs) + " ms."); | |
111 | 118 | stepOkLineTs = System.currentTimeMillis(); |
112 | 119 | } |
113 | 120 | } catch (Exception ex) { |
... | ... | @@ -119,7 +126,7 @@ public class PgCaLatestMigrator { |
119 | 126 | |
120 | 127 | long endTs = System.currentTimeMillis(); |
121 | 128 | System.out.println(); |
122 | - System.out.println(new Date() + " Migrated rows " + linesMigrated + " in " + (endTs - startTs)); | |
129 | + System.out.println(new Date() + " Migrated rows " + linesMigrated + " in " + (endTs - startTs) + " ts"); | |
123 | 130 | |
124 | 131 | currentTsWriter.close(); |
125 | 132 | System.out.println(); |
... | ... | @@ -146,34 +153,31 @@ public class PgCaLatestMigrator { |
146 | 153 | |
147 | 154 | private static List<Object> toValues(List<String> raw) { |
148 | 155 | //expected Table structure: |
149 | -// COPY public.ts_kv_latest (entity_type, entity_id, key, ts, bool_v, str_v, long_v, dbl_v) FROM stdin; | |
150 | - | |
156 | + //COPY public.ts_kv_latest (entity_type, entity_id, key, ts, bool_v, str_v, long_v, dbl_v) FROM stdin; | |
151 | 157 | |
152 | 158 | List<Object> result = new ArrayList<>(); |
153 | - result.add(raw.get(0)); | |
154 | - result.add(fromString(raw.get(1))); | |
155 | - result.add(raw.get(2)); | |
159 | + result.add(allIdsAndTypes.getEntityType(raw.get(0))); | |
160 | + result.add(UUID.fromString(raw.get(0))); | |
161 | + result.add(keyPairs.getKeyByKeyId(raw.get(1))); | |
156 | 162 | |
157 | - long ts = Long.parseLong(raw.get(3)); | |
158 | - result.add(ts); | |
163 | + long ts = Long.parseLong(raw.get(2)); | |
164 | + result.add(3, ts); | |
159 | 165 | |
160 | - result.add(raw.get(4).equals("\\N") ? null : raw.get(4).equals("t") ? Boolean.TRUE : Boolean.FALSE); | |
161 | - result.add(raw.get(5).equals("\\N") ? null : raw.get(5)); | |
162 | - result.add(raw.get(6).equals("\\N") ? null : Long.parseLong(raw.get(6))); | |
163 | - result.add(raw.get(7).equals("\\N") ? null : Double.parseDouble(raw.get(7))); | |
164 | - return result; | |
165 | - } | |
166 | + result.add(raw.get(3).equals("\\N") ? null : raw.get(3).equals("t") ? Boolean.TRUE : Boolean.FALSE); | |
167 | + result.add(raw.get(4).equals("\\N") ? null : raw.get(4)); | |
168 | + result.add(raw.get(5).equals("\\N") ? null : Long.parseLong(raw.get(5))); | |
169 | + result.add(raw.get(6).equals("\\N") ? null : Double.parseDouble(raw.get(6))); | |
170 | + result.add(raw.get(7).equals("\\N") ? null : raw.get(7)); | |
166 | 171 | |
167 | - public static UUID fromString(String src) { | |
168 | - return UUID.fromString(src.substring(7, 15) + "-" + src.substring(3, 7) + "-1" | |
169 | - + src.substring(0, 3) + "-" + src.substring(15, 19) + "-" + src.substring(19)); | |
172 | + return result; | |
170 | 173 | } |
171 | 174 | |
172 | 175 | private static boolean isBlockStarted(String line) { |
173 | - return line.startsWith("COPY public.ts_kv_latest"); | |
176 | + return line.startsWith("COPY public.ts_kv_latest ("); | |
174 | 177 | } |
175 | 178 | |
176 | 179 | private static boolean isBlockFinished(String line) { |
177 | 180 | return StringUtils.isBlank(line) || line.equals("\\."); |
178 | 181 | } |
182 | + | |
179 | 183 | } | ... | ... |
... | ... | @@ -42,7 +42,6 @@ public class PostgresToCassandraTelemetryMigrator { |
42 | 42 | private static final long LOG_BATCH = 1000000; |
43 | 43 | private static final long rowPerFile = 1000000; |
44 | 44 | |
45 | - | |
46 | 45 | private static long linesProcessed = 0; |
47 | 46 | private static long linesMigrated = 0; |
48 | 47 | private static long castErrors = 0; |
... | ... | @@ -53,15 +52,23 @@ public class PostgresToCassandraTelemetryMigrator { |
53 | 52 | private static CQLSSTableWriter currentPartitionWriter = null; |
54 | 53 | |
55 | 54 | private static Set<String> partitions = new HashSet<>(); |
56 | - | |
57 | - | |
58 | - public static void migrateTs(File sourceFile, File outTsDir, File outPartitionDir, boolean castStringsIfPossible) throws IOException { | |
55 | + private static RelatedEntitiesParser entityIdsAndTypes; | |
56 | + private static DictionaryParser keyParser; | |
57 | + | |
58 | + public static void migrateTs(File sourceFile, | |
59 | + File outTsDir, | |
60 | + File outPartitionDir, | |
61 | + RelatedEntitiesParser allEntityIdsAndTypes, | |
62 | + DictionaryParser dictionaryParser, | |
63 | + boolean castStringsIfPossible) throws IOException { | |
59 | 64 | long startTs = System.currentTimeMillis(); |
60 | 65 | long stepLineTs = System.currentTimeMillis(); |
61 | 66 | long stepOkLineTs = System.currentTimeMillis(); |
62 | 67 | LineIterator iterator = FileUtils.lineIterator(sourceFile); |
63 | 68 | currentTsWriter = WriterBuilder.getTsWriter(outTsDir); |
64 | 69 | currentPartitionWriter = WriterBuilder.getPartitionWriter(outPartitionDir); |
70 | + entityIdsAndTypes = allEntityIdsAndTypes; | |
71 | + keyParser = dictionaryParser; | |
65 | 72 | |
66 | 73 | boolean isBlockStarted = false; |
67 | 74 | boolean isBlockFinished = false; |
... | ... | @@ -182,29 +189,24 @@ public class PostgresToCassandraTelemetryMigrator { |
182 | 189 | //expected Table structure: |
183 | 190 | // COPY public.ts_kv (entity_type, entity_id, key, ts, bool_v, str_v, long_v, dbl_v) FROM stdin; |
184 | 191 | |
185 | - | |
186 | 192 | List<Object> result = new ArrayList<>(); |
187 | - result.add(raw.get(0)); | |
188 | - result.add(fromString(raw.get(1))); | |
189 | - result.add(raw.get(2)); | |
193 | + result.add(entityIdsAndTypes.getEntityType(raw.get(0))); | |
194 | + result.add(UUID.fromString(raw.get(0))); | |
195 | + result.add(keyParser.getKeyByKeyId(raw.get(1))); | |
190 | 196 | |
191 | - long ts = Long.parseLong(raw.get(3)); | |
197 | + long ts = Long.parseLong(raw.get(2)); | |
192 | 198 | long partition = toPartitionTs(ts); |
193 | 199 | result.add(partition); |
194 | 200 | result.add(ts); |
195 | 201 | |
196 | - result.add(raw.get(4).equals("\\N") ? null : raw.get(4).equals("t") ? Boolean.TRUE : Boolean.FALSE); | |
197 | - result.add(raw.get(5).equals("\\N") ? null : raw.get(5)); | |
198 | - result.add(raw.get(6).equals("\\N") ? null : Long.parseLong(raw.get(6))); | |
199 | - result.add(raw.get(7).equals("\\N") ? null : Double.parseDouble(raw.get(7))); | |
202 | + result.add(raw.get(3).equals("\\N") ? null : raw.get(3).equals("t") ? Boolean.TRUE : Boolean.FALSE); | |
203 | + result.add(raw.get(4).equals("\\N") ? null : raw.get(4)); | |
204 | + result.add(raw.get(5).equals("\\N") ? null : Long.parseLong(raw.get(5))); | |
205 | + result.add(raw.get(6).equals("\\N") ? null : Double.parseDouble(raw.get(6))); | |
206 | + result.add(raw.get(7).equals("\\N") ? null : raw.get(7)); | |
200 | 207 | return result; |
201 | 208 | } |
202 | 209 | |
203 | - public static UUID fromString(String src) { | |
204 | - return UUID.fromString(src.substring(7, 15) + "-" + src.substring(3, 7) + "-1" | |
205 | - + src.substring(0, 3) + "-" + src.substring(15, 19) + "-" + src.substring(19)); | |
206 | - } | |
207 | - | |
208 | 210 | private static long toPartitionTs(long ts) { |
209 | 211 | LocalDateTime time = LocalDateTime.ofInstant(Instant.ofEpochMilli(ts), ZoneOffset.UTC); |
210 | 212 | return time.truncatedTo(ChronoUnit.DAYS).withDayOfMonth(1).toInstant(ZoneOffset.UTC).toEpochMilli(); |
... | ... | @@ -212,7 +214,7 @@ public class PostgresToCassandraTelemetryMigrator { |
212 | 214 | } |
213 | 215 | |
214 | 216 | private static boolean isBlockStarted(String line) { |
215 | - return line.startsWith("COPY public.ts_kv"); | |
217 | + return line.startsWith("COPY public.ts_kv ("); | |
216 | 218 | } |
217 | 219 | |
218 | 220 | private static boolean isBlockFinished(String line) { | ... | ... |
... | ... | @@ -21,15 +21,17 @@ It will generate single jar file with all required dependencies inside `target d |
21 | 21 | #### Dump data from the source Postgres Database |
22 | 22 | *Do not use compression if possible because Tool can only work with uncompressed file |
23 | 23 | |
24 | -1. Dump table `ts_kv` table: | |
24 | +*If you want to migrate just `ts_kv` without `ts_kv_latest` just don't dump an unnecessary table and when starting the tool don't use arguments (paths) for input dump and output files* | |
25 | 25 | |
26 | - `pg_dump -h localhost -U postgres -d thingsboard -t ts_kv > ts_kv.dmp` | |
27 | - | |
28 | -2. Dump table `ts_kv_latest` table: | |
29 | - | |
30 | - `pg_dump -h localhost -U postgres -d thingsboard -t ts_kv_latest > ts_kv_latest.dmp` | |
26 | +1. Dump related tables that need to correct save telemetry | |
27 | + | |
28 | + `pg_dump -h localhost -U postgres -d thingsboard -t tenant -t customer -t user -t dashboard -t asset -t device -t alarm -t rule_chain -t rule_node -t entity_view -t widgets_bundle -t widget_type -t tenant_profile -t device_profile -t api_usage_state -t tb_user > related_entities.dmp` | |
29 | + | |
30 | +2. Dump `ts_kv` and child: | |
31 | + | |
32 | + `pg_dump -h localhost -U postgres -d thingsboard --load-via-partition-root --data-only -t ts_kv* > ts_kv_all.dmp` | |
31 | 33 | |
32 | -3. [Optional] move table dumps to the instance where cassandra will be hosted | |
34 | +3. [Optional] Move table dumps to the instance where cassandra will be hosted | |
33 | 35 | |
34 | 36 | #### Prepare directory structure for SSTables |
35 | 37 | Tool use 3 different directories for saving SSTables - `ts_kv_cf`, `ts_kv_latest_cf`, `ts_kv_partitions_cf` |
... | ... | @@ -45,9 +47,8 @@ Create 3 empty directories. For example: |
45 | 47 | |
46 | 48 | ``` |
47 | 49 | java -jar ./tools-2.4.1-SNAPSHOT-jar-with-dependencies.jar |
48 | - -latestFrom ./source/ts_kv_latest.dmp | |
50 | + -telemetryFrom ./source/ts_kv_all.dmp | |
49 | 51 | -latestOut /home/ubunut/migration/ts_latest |
50 | - -tsFrom ./source/ts_kv.dmp | |
51 | 52 | -tsOut /home/ubunut/migration/ts |
52 | 53 | -partitionsOut /home/ubunut/migration/ts_partition |
53 | 54 | -castEnable false | ... | ... |
1 | +package org.thingsboard.client.tools.migrator; | |
2 | + | |
3 | +import org.apache.commons.io.FileUtils; | |
4 | +import org.apache.commons.io.LineIterator; | |
5 | +import org.apache.commons.lang3.StringUtils; | |
6 | +import org.thingsboard.server.common.data.EntityType; | |
7 | + | |
8 | +import java.io.File; | |
9 | +import java.io.IOException; | |
10 | +import java.util.HashMap; | |
11 | +import java.util.Map; | |
12 | + | |
13 | +public class RelatedEntitiesParser { | |
14 | + private final Map<String, String> allEntityIdsAndTypes = new HashMap<>(); | |
15 | + | |
16 | + public RelatedEntitiesParser(File source) throws IOException { | |
17 | + processAllTables(FileUtils.lineIterator(source)); | |
18 | + } | |
19 | + | |
20 | + public String getEntityType(String uuid) { | |
21 | + return this.allEntityIdsAndTypes.get(uuid); | |
22 | + } | |
23 | + | |
24 | + private boolean isBlockFinished(String line) { | |
25 | + return StringUtils.isBlank(line) || line.equals("\\."); | |
26 | + } | |
27 | + | |
28 | + private void processAllTables(LineIterator lineIterator) { | |
29 | + String currentLine; | |
30 | + while(lineIterator.hasNext()) { | |
31 | + currentLine = lineIterator.nextLine(); | |
32 | + if(currentLine.startsWith("COPY public.alarm")) { | |
33 | + processBlock(lineIterator, EntityType.ALARM); | |
34 | + } else if (currentLine.startsWith("COPY public.asset")) { | |
35 | + processBlock(lineIterator, EntityType.ASSET); | |
36 | + } else if (currentLine.startsWith("COPY public.customer")) { | |
37 | + processBlock(lineIterator, EntityType.CUSTOMER); | |
38 | + } else if (currentLine.startsWith("COPY public.dashboard")) { | |
39 | + processBlock(lineIterator, EntityType.DASHBOARD); | |
40 | + } else if (currentLine.startsWith("COPY public.device")) { | |
41 | + processBlock(lineIterator, EntityType.DEVICE); | |
42 | + } else if (currentLine.startsWith("COPY public.rule_chain")) { | |
43 | + processBlock(lineIterator, EntityType.RULE_CHAIN); | |
44 | + } else if (currentLine.startsWith("COPY public.rule_node")) { | |
45 | + processBlock(lineIterator, EntityType.RULE_NODE); | |
46 | + } else if (currentLine.startsWith("COPY public.tenant")) { | |
47 | + processBlock(lineIterator, EntityType.TENANT); | |
48 | + } else if (currentLine.startsWith("COPY public.tb_user")) { | |
49 | + processBlock(lineIterator, EntityType.USER); | |
50 | + } else if (currentLine.startsWith("COPY public.entity_view")) { | |
51 | + processBlock(lineIterator, EntityType.ENTITY_VIEW); | |
52 | + } else if (currentLine.startsWith("COPY public.widgets_bundle")) { | |
53 | + processBlock(lineIterator, EntityType.WIDGETS_BUNDLE); | |
54 | + } else if (currentLine.startsWith("COPY public.widget_type")) { | |
55 | + processBlock(lineIterator, EntityType.WIDGET_TYPE); | |
56 | + } else if (currentLine.startsWith("COPY public.tenant_profile")) { | |
57 | + processBlock(lineIterator, EntityType.TENANT_PROFILE); | |
58 | + } else if (currentLine.startsWith("COPY public.device_profile")) { | |
59 | + processBlock(lineIterator, EntityType.DEVICE_PROFILE); | |
60 | + } else if (currentLine.startsWith("COPY public.api_usage_state")) { | |
61 | + processBlock(lineIterator, EntityType.API_USAGE_STATE); | |
62 | + } | |
63 | + } | |
64 | + } | |
65 | + | |
66 | + private void processBlock(LineIterator lineIterator, EntityType entityType) { | |
67 | + String currentLine; | |
68 | + while(lineIterator.hasNext()) { | |
69 | + currentLine = lineIterator.nextLine(); | |
70 | + if(isBlockFinished(currentLine)) { | |
71 | + return; | |
72 | + } | |
73 | + allEntityIdsAndTypes.put(currentLine.split("\t")[0], entityType.name()); | |
74 | + } | |
75 | + } | |
76 | +} | ... | ... |
... | ... | @@ -31,6 +31,7 @@ public class WriterBuilder { |
31 | 31 | " str_v text,\n" + |
32 | 32 | " long_v bigint,\n" + |
33 | 33 | " dbl_v double,\n" + |
34 | + " json_v text,\n" + | |
34 | 35 | " PRIMARY KEY (( entity_type, entity_id, key, partition ), ts)\n" + |
35 | 36 | ");"; |
36 | 37 | |
... | ... | @@ -43,6 +44,7 @@ public class WriterBuilder { |
43 | 44 | " str_v text,\n" + |
44 | 45 | " long_v bigint,\n" + |
45 | 46 | " dbl_v double,\n" + |
47 | + " json_v text,\n" + | |
46 | 48 | " PRIMARY KEY (( entity_type, entity_id ), key)\n" + |
47 | 49 | ") WITH compaction = { 'class' : 'LeveledCompactionStrategy' };"; |
48 | 50 | |
... | ... | @@ -59,8 +61,8 @@ public class WriterBuilder { |
59 | 61 | return CQLSSTableWriter.builder() |
60 | 62 | .inDirectory(dir) |
61 | 63 | .forTable(tsSchema) |
62 | - .using("INSERT INTO thingsboard.ts_kv_cf (entity_type, entity_id, key, partition, ts, bool_v, str_v, long_v, dbl_v) " + | |
63 | - "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)") | |
64 | + .using("INSERT INTO thingsboard.ts_kv_cf (entity_type, entity_id, key, partition, ts, bool_v, str_v, long_v, dbl_v, json_v) " + | |
65 | + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)") | |
64 | 66 | .build(); |
65 | 67 | } |
66 | 68 | |
... | ... | @@ -68,8 +70,8 @@ public class WriterBuilder { |
68 | 70 | return CQLSSTableWriter.builder() |
69 | 71 | .inDirectory(dir) |
70 | 72 | .forTable(latestSchema) |
71 | - .using("INSERT INTO thingsboard.ts_kv_latest_cf (entity_type, entity_id, key, ts, bool_v, str_v, long_v, dbl_v) " + | |
72 | - "VALUES (?, ?, ?, ?, ?, ?, ?, ?)") | |
73 | + .using("INSERT INTO thingsboard.ts_kv_latest_cf (entity_type, entity_id, key, ts, bool_v, str_v, long_v, dbl_v, json_v) " + | |
74 | + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)") | |
73 | 75 | .build(); |
74 | 76 | } |
75 | 77 | ... | ... |