]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.common/src/org/simantics/db/common/CommandMetadata.java
Improve performance of CommandMetadata (de)serialization
[simantics/platform.git] / bundles / org.simantics.db.common / src / org / simantics / db / common / CommandMetadata.java
1 package org.simantics.db.common;
2
3 import java.io.IOException;
4 import java.nio.charset.StandardCharsets;
5 import java.util.ArrayList;
6 import java.util.List;
7
8 import org.simantics.databoard.Bindings;
9 import org.simantics.databoard.binding.Binding;
10 import org.simantics.databoard.serialization.Serializer;
11 import org.simantics.db.Metadata;
12 import org.simantics.db.Session;
13 import org.simantics.db.WriteGraph;
14 import org.simantics.db.exception.DatabaseException;
15 import org.simantics.db.service.Bytes;
16 import org.slf4j.Logger;
17 import org.slf4j.LoggerFactory;
18
19 import gnu.trove.list.array.TByteArrayList;
20
21 public final class CommandMetadata implements Metadata {
22
23     private static final Logger LOGGER = LoggerFactory.getLogger(CommandMetadata.class);
24
25     public static final boolean DEBUG = false;
26     public static final String RESET_COMMAND = "// RESET";
27
28     private static final Binding BINDING = 
29             Bindings.getBindingUnchecked(CommandMetadata.class);
30     private static final Serializer SERIALIZER = 
31             Bindings.getSerializerUnchecked(BINDING);
32
33     public List<Command> commands;
34
35     public static final class Command {
36         public long modelId;
37         public String command;
38
39         public Command() {
40         }
41
42         public Command(long modelId, String command) {
43             super();
44             this.modelId = modelId;
45             this.command = command;
46         }
47     }
48
49     public CommandMetadata() {
50     }
51
52     @Override
53     public byte[] serialise(Session session) {
54         try {
55             TByteArrayList commandsSerialized = new TByteArrayList(4096);
56             byte[] bytes = new byte[8];
57
58             int commandsSize = commands.size();
59             Bytes.writeLE(bytes, 0, commandsSize);
60             commandsSerialized.add(bytes, 0, 4);
61
62             for (Command command : commands) {
63                 Bytes.writeLE8(bytes, 0, command.modelId);
64                 commandsSerialized.add(bytes);
65                 byte[] commandBytes = command.command.getBytes(StandardCharsets.UTF_8);
66                 Bytes.writeLE(bytes, 0, commandBytes.length);
67                 commandsSerialized.add(bytes, 0, 4);
68                 commandsSerialized.add(commandBytes);
69             }
70             return commandsSerialized.toArray();
71         } catch (Exception ee) {
72             // Ok, backwards compatibility required
73             // This is rather slow operation hence the new implementation above
74             try {
75                 return SERIALIZER.serialize(this);
76             } catch (IOException e) {
77                 LOGGER.error("Could not serialize", e);
78                 LOGGER.error("Original exception for new serialisation", ee);
79                 throw new RuntimeException(e);
80             }
81         }
82     }
83
84     public static CommandMetadata deserialise(Session session, byte[] input) {
85         if(input == null) {
86             CommandMetadata metadata = new CommandMetadata();
87             metadata.commands = new ArrayList<Command>();
88             return metadata;
89         }
90         try {
91             int byteIndex = 0;
92             int commandsSize = Bytes.readLE4(input, byteIndex);
93             byteIndex += 4;
94             
95             List<Command> commands = new ArrayList<>(commandsSize);
96             for (int i = 0; i < commandsSize; i++) {
97                 long modelId = Bytes.readLE8(input, byteIndex);
98                 byteIndex += 8;
99                 int commandsLength = Bytes.readLE4(input, byteIndex);
100                 byteIndex += 4;
101                 
102                 String command = new String(input, byteIndex, commandsLength);
103                 byteIndex += commandsLength;
104                 Command comm = new Command(modelId, command);
105                 commands.add(comm);
106             }
107             CommandMetadata metadata = new CommandMetadata();
108             metadata.commands = commands;
109             return metadata;
110         } catch (Exception ee) {
111             // Ok, backwards compatibility required
112             // This is rather slow operation hence the new implementation above
113             try {
114                 return (CommandMetadata)SERIALIZER.deserialize(input);
115             } catch (Exception e) {
116                 LOGGER.error("Could not deserialise", e);
117                 LOGGER.error("Original exception for new deserialisation", ee);
118             }
119             return null;
120         }
121     }
122
123     public CommandMetadata add(Command command) {
124         commands.add(command);
125         return this;
126     }
127     
128     public List<Command> getCommands() {
129         return commands;
130     }
131
132     public static void add(WriteGraph graph, long modelId, String command) throws DatabaseException {
133         if(DEBUG) {
134             System.out.println("-------------------------------------------------------------");
135             System.out.println(command);
136         }
137         graph.addMetadata(graph.getMetadata(CommandMetadata.class).add(
138                 new Command(modelId, command)));
139     }
140     
141     public static void addReset(WriteGraph graph, long modelId) throws DatabaseException {
142         graph.addMetadata(graph.getMetadata(CommandMetadata.class).add(
143                 new Command(modelId, RESET_COMMAND)));
144     }
145 }