blob: 6d3d45edaeb34707ea7a3cf8c85419399b1e0ea1 [file] [log] [blame]
Yuta HIGUCHI60731cb2014-11-11 01:34:46 -08001/*
2 * Copyright 2014 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onlab.onos.store.service.impl;
17
18import static com.google.common.base.Preconditions.checkArgument;
19import static com.google.common.base.Preconditions.checkNotNull;
20import static org.slf4j.LoggerFactory.getLogger;
21
22import java.io.File;
23import java.io.IOException;
24import java.util.HashMap;
25import java.util.HashSet;
26import java.util.Iterator;
27import java.util.Map;
28import java.util.Map.Entry;
29import java.util.Set;
30
31import org.onlab.onos.cluster.DefaultControllerNode;
32import org.onlab.onos.cluster.NodeId;
33import org.onlab.packet.IpAddress;
34import org.slf4j.Logger;
35
36import com.fasterxml.jackson.core.JsonEncoding;
37import com.fasterxml.jackson.core.JsonFactory;
38import com.fasterxml.jackson.databind.JsonNode;
39import com.fasterxml.jackson.databind.ObjectMapper;
40import com.fasterxml.jackson.databind.node.ArrayNode;
41import com.fasterxml.jackson.databind.node.ObjectNode;
42
43/**
44 * Allows for reading and writing tablet definition as a JSON file.
45 */
46public class TabletDefinitionStore {
47
48 private final Logger log = getLogger(getClass());
49
50 private final File file;
51
52 /**
53 * Creates a reader/writer of the tablet definition file.
54 *
55 * @param filePath location of the definition file
56 */
57 public TabletDefinitionStore(String filePath) {
58 file = new File(filePath);
59 }
60
61 /**
62 * Creates a reader/writer of the tablet definition file.
63 *
64 * @param filePath location of the definition file
65 */
66 public TabletDefinitionStore(File filePath) {
67 file = checkNotNull(filePath);
68 }
69
70 /**
71 * Returns the Map from tablet name to set of initial member nodes.
72 *
73 * @return Map from tablet name to set of initial member nodes
74 * @throws IOException when I/O exception of some sort has occurred.
75 */
76 public Map<String, Set<DefaultControllerNode>> read() throws IOException {
77
78 final Map<String, Set<DefaultControllerNode>> tablets = new HashMap<>();
79
80 final ObjectMapper mapper = new ObjectMapper();
81 final ObjectNode tabletNodes = (ObjectNode) mapper.readTree(file);
82 final Iterator<Entry<String, JsonNode>> fields = tabletNodes.fields();
83 while (fields.hasNext()) {
84 final Entry<String, JsonNode> next = fields.next();
85 final Set<DefaultControllerNode> nodes = new HashSet<>();
86 final Iterator<JsonNode> elements = next.getValue().elements();
87 while (elements.hasNext()) {
88 ObjectNode nodeDef = (ObjectNode) elements.next();
89 nodes.add(new DefaultControllerNode(new NodeId(nodeDef.get("id").asText()),
90 IpAddress.valueOf(nodeDef.get("ip").asText()),
91 nodeDef.get("tcpPort").asInt(9876)));
92 }
93
94 tablets.put(next.getKey(), nodes);
95 }
96 return tablets;
97 }
98
99 /**
100 * Updates the Map from tablet name to set of member nodes.
101 *
102 * @param tabletName name of the tablet to update
103 * @param nodes set of initial member nodes
104 * @throws IOException when I/O exception of some sort has occurred.
105 */
106 public void write(String tabletName, Set<DefaultControllerNode> nodes) throws IOException {
107 checkNotNull(tabletName);
108 checkArgument(tabletName.isEmpty(), "Tablet name cannot be empty");
109 // TODO should validate if tabletName is allowed in JSON
110
111 // load current
112 Map<String, Set<DefaultControllerNode>> config;
113 try {
114 config = read();
115 } catch (IOException e) {
116 log.info("Reading tablet config failed, assuming empty definition.");
117 config = new HashMap<>();
118 }
119 // update with specified
120 config.put(tabletName, nodes);
121
122 // write back to file
123 final ObjectMapper mapper = new ObjectMapper();
124 final ObjectNode tabletNodes = mapper.createObjectNode();
125 for (Entry<String, Set<DefaultControllerNode>> tablet : config.entrySet()) {
126 ArrayNode nodeDefs = mapper.createArrayNode();
127 tabletNodes.set(tablet.getKey(), nodeDefs);
128
129 for (DefaultControllerNode node : tablet.getValue()) {
130 ObjectNode nodeDef = mapper.createObjectNode();
131 nodeDef.put("id", node.id().toString())
132 .put("ip", node.ip().toString())
133 .put("tcpPort", node.tcpPort());
134 nodeDefs.add(nodeDef);
135 }
136 }
137 mapper.writeTree(new JsonFactory().createGenerator(file, JsonEncoding.UTF8),
138 tabletNodes);
139 }
140
141}