This is a start to make use of Schema based Table management instead of static class as defined today.
Signed-off-by: Madhu Venugopal <mavenugo@gmail.com>
\r
public class ColumnSchema {\r
@JsonProperty("type")\r
- public OvsdbType type;\r
+ private OvsdbType type;\r
@JsonProperty("ephemeral")\r
- public Boolean ephemeral;\r
+ private Boolean ephemeral;\r
@JsonProperty("mutable")\r
- public Boolean mutable;\r
-\r
+ private Boolean mutable;\r
+ public OvsdbType getType() {\r
+ return type;\r
+ }\r
+ public Boolean getEphemeral() {\r
+ return ephemeral;\r
+ }\r
+ public Boolean getMutable() {\r
+ return mutable;\r
+ }\r
+ @Override\r
+ public String toString() {\r
+ return "ColumnSchema [type=" + type + ", ephemeral=" + ephemeral\r
+ + ", mutable=" + mutable + "]";\r
+ }\r
}\r
\r
public class DatabaseSchema {\r
@JsonProperty("name")\r
- public String name;\r
+ private String name;\r
@JsonProperty("version")\r
- public String version;\r
+ private String version;\r
@JsonProperty("cksum")\r
- public String cksum;\r
+ private String cksum;\r
@JsonProperty("tables")\r
- public Map<String, TableSchema> tables;\r
+ private Map<String, TableSchema> tables;\r
+ public String getName() {\r
+ return name;\r
+ }\r
+ public String getVersion() {\r
+ return version;\r
+ }\r
+ public String getCksum() {\r
+ return cksum;\r
+ }\r
+ public Map<String, TableSchema> getTables() {\r
+ return tables;\r
+ }\r
+ @Override\r
+ public String toString() {\r
+ return "DatabaseSchema [name=" + name + ", version=" + version\r
+ + ", cksum=" + cksum + ", tables=" + tables + "]";\r
+ }\r
}\r
package org.opendaylight.ovsdb.lib.database;\r
\r
+import java.util.Arrays;\r
+\r
import com.fasterxml.jackson.annotation.JsonProperty;\r
\r
\r
public Integer maxLength;\r
public String refTable;\r
public String refType;\r
+ @Override\r
+ public String toString() {\r
+ return "BaseType [type=" + type + ", ovsdbEnum="\r
+ + Arrays.toString(ovsdbEnum) + ", minInteger=" + minInteger\r
+ + ", maxInteger=" + maxInteger + ", minReal=" + minReal\r
+ + ", maxReal=" + maxReal + ", minLength=" + minLength\r
+ + ", maxLength=" + maxLength + ", refTable=" + refTable\r
+ + ", refType=" + refType + "]";\r
+ }\r
}\r
\r
-\r
+ @Override\r
+ public String toString() {\r
+ return "OvsdbType [key=" + key + ", value=" + value + ", min=" + min\r
+ + ", max=" + max + "]";\r
+ }\r
}\r
\r
public class TableSchema {\r
@JsonProperty("columns")\r
- public Map<String, ColumnSchema> columns;\r
+ private Map<String, ColumnSchema> columns;\r
@JsonProperty("maxRows")\r
- public Integer maxRows;\r
+ private Integer maxRows;\r
@JsonProperty("isRoot")\r
- public Boolean isRoot;\r
+ private Boolean isRoot;\r
@JsonProperty("indexes")\r
- public Object indexes;\r
+ private Object indexes;\r
\r
public Map<String, ColumnSchema> getColumns(){\r
return this.columns;\r
}\r
+\r
+ public Integer getMaxRows() {\r
+ return maxRows;\r
+ }\r
+\r
+ public Boolean getIsRoot() {\r
+ return isRoot;\r
+ }\r
+\r
+ public Object getIndexes() {\r
+ return indexes;\r
+ }\r
+\r
+ @Override\r
+ public String toString() {\r
+ return "TableSchema [columns=" + columns + ", maxRows=" + maxRows\r
+ + ", isRoot=" + isRoot + ", indexes=" + indexes + "]";\r
+ }\r
}\r
// each of the Operations covered by Transaction (Insert, Update, Delete, Mutate, etc...)
// It is better to have the OperationResult as an abstract parent class with individual
// concrete child classes for each of the operation response.
-// But this needs proper response handling
+// TODO : But this needs proper response handling
// https://trello.com/c/mfTTS86k/28-generic-response-error-handling-especially-for-transact
// As a temporary measure, adding all the expected responses under the same response.
package org.opendaylight.ovsdb.lib.message.operations;
+import java.util.List;
+
+import org.opendaylight.ovsdb.lib.notation.Condition;
+
public class SelectOperation extends Operation {
+ String table;
+ List<Condition> where;
+ List<String> columns;
+ public SelectOperation(String table, List<Condition> where, List<String> columns) {
+ super();
+ super.setOp("select");
+ this.table = table;
+ this.where = where;
+ this.columns = columns;
+ }
+ public String getTable() {
+ return table;
+ }
+ public void setTable(String table) {
+ this.table = table;
+ }
+ public List<Condition> getWhere() {
+ return where;
+ }
+ public void setWhere(List<Condition> where) {
+ this.where = where;
+ }
+ public List<String> getColumns() {
+ return columns;
+ }
+ public void setColumns(List<String> columns) {
+ this.columns = columns;
+ }
+ @Override
+ public String toString() {
+ return "SelectOperation [table=" + table + ", where=" + where
+ + ", columns=" + columns + "]";
+ }
}
public class Bridge extends Table<Bridge> {
public static final Name<Bridge> NAME = new Name<Bridge>("Bridge"){};
- public enum Column implements org.opendaylight.ovsdb.lib.table.internal.Column<Bridge>{ controller, fail_mode, name, ports}
+ public enum Column implements org.opendaylight.ovsdb.lib.table.internal.Column<Bridge>{controller, fail_mode, name, ports}
private String name;
private OvsDBSet<UUID> ports;
public abstract Name<E> getTableName();
public abstract String toString();
+ public Column<E> getColumns() {
+ return null;
+ }
public static abstract class Name<E extends Table> {
String name;
import org.opendaylight.controller.sal.core.Node;
import org.opendaylight.controller.sal.utils.Status;
import org.opendaylight.controller.sal.utils.StatusCode;
+import org.opendaylight.ovsdb.lib.database.DatabaseSchema;
import org.opendaylight.ovsdb.lib.jsonrpc.JsonRpcDecoder;
import org.opendaylight.ovsdb.lib.jsonrpc.JsonRpcEndpoint;
import org.opendaylight.ovsdb.lib.jsonrpc.JsonRpcServiceBinderHandler;
import org.opendaylight.ovsdb.lib.message.OvsdbRPC;
import org.opendaylight.ovsdb.lib.message.TableUpdates;
import org.opendaylight.ovsdb.lib.message.UpdateNotification;
+import org.opendaylight.ovsdb.lib.table.Open_vSwitch;
import org.opendaylight.ovsdb.lib.table.internal.Table;
import org.opendaylight.ovsdb.lib.table.internal.Tables;
import org.slf4j.Logger;
import com.google.common.util.concurrent.ListenableFuture;
import java.net.InetAddress;
+import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public void initChannel(SocketChannel channel) throws Exception {
if (handlers == null) {
channel.pipeline().addLast(
- new LoggingHandler(LogLevel.INFO),
+ //new LoggingHandler(LogLevel.INFO),
new JsonRpcDecoder(100000),
new StringEncoder(CharsetUtil.UTF_8));
} else {
inventoryServiceInternal.addNodeProperty(connection.getNode(), addressProp);
inventoryServiceInternal.addNodeProperty(connection.getNode(), l4Port);
+ List<String> dbNames = Arrays.asList(Open_vSwitch.NAME.getName());
+ ListenableFuture<DatabaseSchema> dbSchemaF = connection.getRpc().get_schema(dbNames);
+ DatabaseSchema databaseSchema = dbSchemaF.get();
+ inventoryServiceInternal.updateDatabaseSchema(connection.getNode(), databaseSchema);
+
MonitorRequestBuilder monitorReq = new MonitorRequestBuilder();
for (Table<?> table : Tables.getTables()) {
monitorReq.monitor(table);
import org.opendaylight.controller.sal.core.NodeConnector;
import org.opendaylight.controller.sal.core.Property;
import org.opendaylight.controller.sal.inventory.IPluginInInventoryService;
+import org.opendaylight.ovsdb.lib.database.DatabaseSchema;
import org.opendaylight.ovsdb.lib.message.TableUpdate;
import org.opendaylight.ovsdb.lib.message.TableUpdate.Row;
import org.opendaylight.ovsdb.lib.message.TableUpdates;
private ConcurrentMap<Node, Map<String, Property>> nodeProps;
private ConcurrentMap<NodeConnector, Map<String, Property>> nodeConnectorProps;
- private Map<Node, NodeDB<Table<?>>> dbCache = Maps.newHashMap();
+ private Map<Node, NodeDB> dbCache = Maps.newHashMap();
/**
* Function called by the dependency manager when all the required
@Override
public Map<String, Map<String, Table<?>>> getCache(Node n) {
- NodeDB<Table<?>> db = dbCache.get(n);
+ NodeDB db = dbCache.get(n);
if (db == null) return null;
return db.getTableCache();
}
@Override
public Map<String, Table<?>> getTableCache(Node n, String tableName) {
- NodeDB<Table<?>> db = dbCache.get(n);
+ NodeDB db = dbCache.get(n);
if (db == null) return null;
return db.getTableCache(tableName);
}
@Override
public Table<?> getRow(Node n, String tableName, String uuid) {
- NodeDB<Table<?>> db = dbCache.get(n);
+ NodeDB db = dbCache.get(n);
if (db == null) return null;
return db.getRow(tableName, uuid);
}
-
@Override
public void updateRow(Node n, String tableName, String uuid, Table<?> row) {
- NodeDB<Table<?>> db = dbCache.get(n);
+ NodeDB db = dbCache.get(n);
if (db == null) {
- db = new NodeDB<Table<?>>();
+ db = new NodeDB();
dbCache.put(n, db);
}
db.updateRow(tableName, uuid, row);
@Override
public void removeRow(Node n, String tableName, String uuid) {
- NodeDB<Table<?>> db = dbCache.get(n);
+ NodeDB db = dbCache.get(n);
if (db != null) db.removeRow(tableName, uuid);
}
@Override
public void processTableUpdates(Node n, TableUpdates tableUpdates) {
- NodeDB<Table<?>> db = dbCache.get(n);
+ NodeDB db = dbCache.get(n);
if (db == null) {
- db = new NodeDB<Table<?>>();
+ db = new NodeDB();
dbCache.put(n, db);
}
@Override
public void printCache(Node n) {
- NodeDB<Table<?>> db = dbCache.get(n);
+ NodeDB db = dbCache.get(n);
if (db != null) db.printTableCache();
}
nProp.put(prop.getName(), prop);
nodeProps.put(n, nProp);
}
+
+ @Override
+ public DatabaseSchema getDatabaseSchema(Node n) {
+ NodeDB db = dbCache.get(n);
+ if (db != null) return db.getSchema();
+ return null;
+ }
+
+ @Override
+ public void updateDatabaseSchema(Node n, DatabaseSchema schema) {
+ NodeDB db = dbCache.get(n);
+ if (db == null) {
+ db = new NodeDB();
+ dbCache.put(n, db);
+ }
+ db.setSchema(schema);
+ }
}
import org.opendaylight.controller.sal.core.Node;
import org.opendaylight.controller.sal.core.Property;
+import org.opendaylight.ovsdb.lib.database.DatabaseSchema;
import org.opendaylight.ovsdb.lib.message.TableUpdates;
import org.opendaylight.ovsdb.lib.table.internal.Table;
public void updateRow(Node n, String tableName, String uuid, Table<?> row);
public void removeRow(Node n, String tableName, String uuid);
public void processTableUpdates(Node n, TableUpdates tableUpdates);
+ public void updateDatabaseSchema(Node n, DatabaseSchema schema);
+ public DatabaseSchema getDatabaseSchema(Node n);
public void printCache(Node n);
public void addNodeProperty(Node n, Property prop);
+++ /dev/null
-package org.opendaylight.ovsdb.plugin;\r
-\r
-import java.lang.String;\r
-\r
-public class JSONMsg{\r
- public String jsonStr;\r
-\r
- public JSONMsg(String jsonStr){\r
- this.jsonStr = jsonStr;\r
- }\r
-}
\ No newline at end of file
+++ /dev/null
-package org.opendaylight.ovsdb.plugin;\r
-\r
-import com.fasterxml.jackson.databind.JsonNode;\r
-import com.fasterxml.jackson.databind.ObjectMapper;\r
-\r
-import io.netty.channel.ChannelHandlerContext;\r
-import io.netty.channel.ChannelInboundHandlerAdapter;\r
-\r
-import org.opendaylight.ovsdb.lib.message.EchoResponse;\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-\r
-import java.io.IOException;\r
-import java.util.HashMap;\r
-import java.util.Map;\r
-import java.util.concurrent.Future;\r
-\r
-public class MessageHandler extends ChannelInboundHandlerAdapter {\r
- protected static final Logger logger = LoggerFactory.getLogger(MessageHandler.class);\r
-\r
- private Map<Long, MessageHandlerFuture> responseFutures = new HashMap<Long, MessageHandlerFuture>();\r
-\r
- public Future<Object> getResponse(long id) {\r
- MessageHandlerFuture responseFuture = new MessageHandlerFuture(Long.valueOf(id));\r
- responseFutures.put(Long.valueOf(id), responseFuture);\r
- return responseFuture;\r
- }\r
-\r
- @Override\r
- public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {\r
- // logger.debug(ctx.channel().alloc().buffer().alloc().directBuffer().toString());\r
-\r
- logger.info("ChannRead ==> " + msg.toString());\r
- JsonNode jsonNode;\r
- ObjectMapper mapper = new ObjectMapper();\r
- String strmsg = msg.toString();\r
- try {\r
- jsonNode = mapper.readTree(strmsg);\r
- } catch (IOException e) {\r
- e.printStackTrace();\r
- return;\r
- }\r
-\r
- if (jsonNode.has("method")) {\r
- String method = jsonNode.get("method").toString();\r
- // if (method.contains("echo")) {\r
- EchoResponse echoreply = new EchoResponse();\r
- JsonNode echoReplyJnode = mapper.valueToTree(echoreply);\r
- logger.debug("Echo Reply DP ==>" + msg);\r
- ctx.writeAndFlush(echoReplyJnode.toString());\r
- }\r
- }\r
-\r
- @Override\r
- public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {\r
- ctx.flush();\r
- }\r
-}
\ No newline at end of file
+++ /dev/null
-package org.opendaylight.ovsdb.plugin;\r
-\r
-import org.opendaylight.controller.sal.utils.Status;\r
-import org.opendaylight.controller.sal.utils.StatusCode;\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-\r
-import java.util.concurrent.*;\r
-\r
-/**\r
- * Class which will monitor the completion of a FlowEntryDistributionOrder it\r
- * implements a Future interface so it can be inspected by who is waiting for\r
- * it.\r
- */\r
-final class MessageHandlerFuture implements Future<Object> {\r
- private final Long id;\r
- private Object response;\r
- private boolean amICancelled;\r
- private CountDownLatch waitingLatch;\r
- private Status retStatus;\r
- private static final Logger logger = LoggerFactory.getLogger(MessageHandlerFuture.class);\r
-\r
-\r
- /**\r
- * @param order for which we are monitoring the execution\r
- */\r
- public MessageHandlerFuture(Long id) {\r
- // Order being monitored\r
- this.id = id;\r
- this.response = null;\r
- this.amICancelled = false;\r
- // We need to wait for one completion to happen\r
- this.waitingLatch = new CountDownLatch(1);\r
- // No return status yet!\r
- this.retStatus = new Status(StatusCode.UNDEFINED);\r
- }\r
-\r
- @Override\r
- public boolean cancel(boolean mayInterruptIfRunning) {\r
- return false;\r
- }\r
-\r
- @Override\r
- public Object get() throws InterruptedException, ExecutionException {\r
- // If i'm done lets return the status as many times as caller wants\r
- if (this.waitingLatch.getCount() == 0L) {\r
- return response;\r
- }\r
-\r
- // Wait till someone signal that we are done\r
- this.waitingLatch.await();\r
-\r
- // Return the known status\r
- return response;\r
- }\r
-\r
- @Override\r
- public Object get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {\r
- // If i'm done lets return the status as many times as caller wants\r
- if (this.waitingLatch.getCount() == 0L) {\r
- return response;\r
- }\r
-\r
- // Wait till someone signal that we are done\r
- this.waitingLatch.await(timeout, unit);\r
-\r
- // Return the known status, could also be null if didn't return\r
- return response;\r
- }\r
-\r
- @Override\r
- public boolean isCancelled() {\r
- return this.amICancelled;\r
- }\r
-\r
- @Override\r
- public boolean isDone() {\r
- return (this.waitingLatch.getCount() == 0L);\r
- }\r
-\r
- /**\r
- * Used by the thread that gets back the status for the order so can unblock\r
- * an eventual caller waiting on the result to comes back\r
- *\r
- * @param order\r
- * @param retStatus\r
- */\r
- void gotResponse(Long id, Object response) {\r
- if (id != this.id) {\r
- // Weird we got a call for an order we didn't make\r
- return;\r
- }\r
- this.response = response;\r
- // Now we are not waiting any longer\r
- this.waitingLatch.countDown();\r
- }\r
-}\r
+++ /dev/null
-package org.opendaylight.ovsdb.plugin;\r
-\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-\r
-import java.util.HashMap;\r
-import java.util.Map;\r
-\r
-public class MessageMapper {\r
-\r
- private static final Logger logger = LoggerFactory.getLogger(MessageMapper.class);\r
-\r
- private static MessageMapper mapper = null;\r
- Map<Long, Class<?>> responseMapper = new HashMap<Long, Class<?>>();\r
- Map<String, Class<?>> requestMapper = new HashMap<String, Class<?>>();\r
-\r
- private MessageMapper() {\r
- }\r
-\r
- public static MessageMapper getMapper() {\r
- if (mapper == null) mapper = new MessageMapper();\r
- return mapper;\r
- }\r
-\r
- public void map(long id, Class<?> rClass) {\r
- responseMapper.put(Long.valueOf(id), rClass);\r
- }\r
-\r
- public Class<?> pop(long id) {\r
- return responseMapper.remove(id);\r
- }\r
-\r
- public void map(String type, Class<?> rClass) {\r
- requestMapper.put(type, rClass);\r
- }\r
-\r
- public Class<?> get(String type) {\r
- return requestMapper.get(type);\r
- }\r
-}\r
import com.google.common.collect.Maps;
import org.apache.commons.collections.MapUtils;
+import org.opendaylight.ovsdb.lib.database.DatabaseSchema;
import org.opendaylight.ovsdb.lib.table.internal.Table;
-public class NodeDB <T extends Table<?>>{
- Map<String, Map<String, T>> cache = Maps.newHashMap();
+public class NodeDB {
+ private DatabaseSchema schema;
+ Map<String, Map<String, Table<?>>> cache = Maps.newHashMap();
- public Map<String, Map<String, T>> getTableCache() {
+ public DatabaseSchema getSchema() {
+ return schema;
+ }
+
+ public void setSchema(DatabaseSchema schema) {
+ this.schema = schema;
+ }
+
+ public Map<String, Map<String, Table<?>>> getTableCache() {
return cache;
}
- public Map<String, T> getTableCache(String tableName) {
+ public Map<String, Table<?>> getTableCache(String tableName) {
return cache.get(tableName);
}
- private void setTableCache(String tableName, Map<String, T> tableCache) {
+ private void setTableCache(String tableName, Map<String, Table<?>> tableCache) {
cache.put(tableName, tableCache);
}
- public T getRow (String tableName, String uuid) {
- Map<String, T> tableCache = getTableCache(tableName);
+ public Table<?> getRow (String tableName, String uuid) {
+ Map<String, Table<?>> tableCache = getTableCache(tableName);
if (tableCache != null) {
return tableCache.get(uuid);
}
return null;
}
- public void updateRow(String tableName, String uuid, T row) {
- Map<String, T> tableCache = getTableCache(tableName);
+ public void updateRow(String tableName, String uuid, Table<?> row) {
+ Map<String, Table<?>> tableCache = getTableCache(tableName);
if (tableCache == null) {
tableCache = Maps.newHashMap();
setTableCache(tableName, tableCache);
}
public void removeRow(String tableName, String uuid) {
- Map<String, T> tableCache = getTableCache(tableName);
+ Map<String, Table<?>> tableCache = getTableCache(tableName);
if (tableCache != null) {
tableCache.remove(uuid);
}
}
public void printTableCache() {
+ MapUtils.debugPrint(System.out, null, schema.getTables());
MapUtils.debugPrint(System.out, null, cache);
}
}
package org.opendaylight.ovsdb.lib.message;
import com.google.common.util.concurrent.ListenableFuture;
+
+import org.apache.commons.collections.MapUtils;
import org.junit.Test;
import org.opendaylight.controller.sal.connection.ConnectionConstants;
import org.opendaylight.controller.sal.core.Node;
List<String> dbNames = Arrays.asList(Open_vSwitch.NAME.getName());
ListenableFuture<DatabaseSchema> dbSchemaF = ovsdb.get_schema(dbNames);
DatabaseSchema databaseSchema = dbSchemaF.get();
- System.out.println(databaseSchema);
+ MapUtils.debugPrint(System.out, null, databaseSchema.getTables());
- //TEST MONITOR
+ // TEST MONITOR
+ // YES it is expected to fail with "duplicate monitor ID" as we have a perpetual monitor in Inventory Service
MonitorRequestBuilder monitorReq = new MonitorRequestBuilder();
for (Table<?> table : Tables.getTables()) {
monitorReq.monitor(table);