Renamed datagrid and datastore packages
net.onrc.onos.datagrid.* => net.onrc.onos.core.datagrid.*
net.onrc.onos.datastore.* => net.onrc.onos.core.datastore.*
Change-Id: Ibe1894a6fabae08ea7cfcbf6595f0c91b05ef497
diff --git a/src/main/java/net/onrc/onos/core/datagrid/HazelcastDatagrid.java b/src/main/java/net/onrc/onos/core/datagrid/HazelcastDatagrid.java
new file mode 100755
index 0000000..7d2b7f3
--- /dev/null
+++ b/src/main/java/net/onrc/onos/core/datagrid/HazelcastDatagrid.java
@@ -0,0 +1,287 @@
+package net.onrc.onos.core.datagrid;
+
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import net.floodlightcontroller.core.IFloodlightProviderService;
+import net.floodlightcontroller.core.module.FloodlightModuleContext;
+import net.floodlightcontroller.core.module.FloodlightModuleException;
+import net.floodlightcontroller.core.module.IFloodlightModule;
+import net.floodlightcontroller.core.module.IFloodlightService;
+import net.floodlightcontroller.restserver.IRestApiService;
+import net.onrc.onos.core.datagrid.web.DatagridWebRoutable;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.hazelcast.config.Config;
+import com.hazelcast.config.FileSystemXmlConfig;
+import com.hazelcast.core.Hazelcast;
+import com.hazelcast.core.HazelcastInstance;
+import com.hazelcast.instance.GroupProperties;
+
+/**
+ * A datagrid service that uses Hazelcast as a datagrid.
+ * The relevant data is stored in the Hazelcast datagrid and shared as
+ * appropriate in a multi-node cluster.
+ */
+public class HazelcastDatagrid implements IFloodlightModule, IDatagridService {
+ static final Logger log = LoggerFactory.getLogger(HazelcastDatagrid.class);
+ private IRestApiService restApi;
+
+ static final String HAZELCAST_CONFIG_FILE = "datagridConfig";
+ private HazelcastInstance hazelcastInstance;
+ private Config hazelcastConfig;
+
+ //
+ // NOTE: eventChannels is kept thread safe by using explicit "synchronized"
+ // blocks below. Those are needed to protect the integrity of each entry
+ // instance, and avoid preemption during channel creation/startup.
+ //
+ private final Map<String, IEventChannel<?, ?>> eventChannels = new HashMap<>();
+
+ /**
+ * Initialize the Hazelcast Datagrid operation.
+ *
+ * @param configFilename the configuration filename.
+ */
+ public void init(String configFilename) {
+ /*
+ System.setProperty("hazelcast.socket.receive.buffer.size", "32");
+ System.setProperty("hazelcast.socket.send.buffer.size", "32");
+ */
+ // System.setProperty("hazelcast.heartbeat.interval.seconds", "100");
+
+ // Init from configuration file
+ try {
+ hazelcastConfig = new FileSystemXmlConfig(configFilename);
+ } catch (FileNotFoundException e) {
+ log.error("Error opening Hazelcast XML configuration. File not found: " + configFilename, e);
+ }
+ /*
+ hazelcastConfig.setProperty(GroupProperties.PROP_IO_THREAD_COUNT, "1");
+ hazelcastConfig.setProperty(GroupProperties.PROP_OPERATION_THREAD_COUNT, "1");
+ hazelcastConfig.setProperty(GroupProperties.PROP_EVENT_THREAD_COUNT, "1");
+ */
+ //
+ hazelcastConfig.setProperty(GroupProperties.PROP_EVENT_QUEUE_CAPACITY, "4000000");
+ hazelcastConfig.setProperty(GroupProperties.PROP_SOCKET_RECEIVE_BUFFER_SIZE, "4096");
+ hazelcastConfig.setProperty(GroupProperties.PROP_SOCKET_SEND_BUFFER_SIZE, "4096");
+ }
+
+ /**
+ * Shutdown the Hazelcast Datagrid operation.
+ */
+ @Override
+ protected void finalize() {
+ close();
+ }
+
+ /**
+ * Shutdown the Hazelcast Datagrid operation.
+ */
+ public void close() {
+ Hazelcast.shutdownAll();
+ }
+
+ /**
+ * Get the collection of offered module services.
+ *
+ * @return the collection of offered module services.
+ */
+ @Override
+ public Collection<Class<? extends IFloodlightService>> getModuleServices() {
+ Collection<Class<? extends IFloodlightService>> l =
+ new ArrayList<Class<? extends IFloodlightService>>();
+ l.add(IDatagridService.class);
+ return l;
+ }
+
+ /**
+ * Get the collection of implemented services.
+ *
+ * @return the collection of implemented services.
+ */
+ @Override
+ public Map<Class<? extends IFloodlightService>, IFloodlightService>
+ getServiceImpls() {
+ Map<Class<? extends IFloodlightService>,
+ IFloodlightService> m =
+ new HashMap<Class<? extends IFloodlightService>,
+ IFloodlightService>();
+ m.put(IDatagridService.class, this);
+ return m;
+ }
+
+ /**
+ * Get the collection of modules this module depends on.
+ *
+ * @return the collection of modules this module depends on.
+ */
+ @Override
+ public Collection<Class<? extends IFloodlightService>>
+ getModuleDependencies() {
+ Collection<Class<? extends IFloodlightService>> l =
+ new ArrayList<Class<? extends IFloodlightService>>();
+ l.add(IFloodlightProviderService.class);
+ l.add(IRestApiService.class);
+ return l;
+ }
+
+ /**
+ * Initialize the module.
+ *
+ * @param context the module context to use for the initialization.
+ * @throws FloodlightModuleException on error
+ */
+ @Override
+ public void init(FloodlightModuleContext context)
+ throws FloodlightModuleException {
+ restApi = context.getServiceImpl(IRestApiService.class);
+
+ // Get the configuration file name and configure the Datagrid
+ Map<String, String> configMap = context.getConfigParams(this);
+ String configFilename = configMap.get(HAZELCAST_CONFIG_FILE);
+ this.init(configFilename);
+ }
+
+ /**
+ * Startup module operation.
+ *
+ * @param context the module context to use for the startup.
+ */
+ @Override
+ public void startUp(FloodlightModuleContext context) {
+ hazelcastInstance = Hazelcast.newHazelcastInstance(hazelcastConfig);
+
+ restApi.addRestletRoutable(new DatagridWebRoutable());
+ }
+
+ /**
+ * Create an event channel.
+ * <p/>
+ * If the channel already exists, just return it.
+ * NOTE: The channel is started automatically.
+ *
+ * @param channelName the event channel name.
+ * @param <K> the type of the Key in the Key-Value store.
+ * @param <V> the type of the Value in the Key-Value store.
+ * @param typeK the type of the Key in the Key-Value store.
+ * @param typeV the type of the Value in the Key-Value store.
+ * @return the event channel for the channel name.
+ */
+ @Override
+ public <K, V> IEventChannel<K, V> createChannel(String channelName,
+ Class<K> typeK, Class<V> typeV) {
+ synchronized (eventChannels) {
+ IEventChannel<K, V> eventChannel =
+ createChannelImpl(channelName, typeK, typeV);
+ eventChannel.startup();
+ return eventChannel;
+ }
+ }
+
+ /**
+ * Create an event channel implementation.
+ * <p/>
+ * If the channel already exists, just return it.
+ * NOTE: The caller must call IEventChannel.startup() to startup the
+ * channel operation.
+ * NOTE: The caller must own the lock on "eventChannels".
+ *
+ * @param channelName the event channel name.
+ * @param <K> the type of the Key in the Key-Value store.
+ * @param <V> the type of the Value in the Key-Value store.
+ * @param typeK the type of the Key in the Key-Value store.
+ * @param typeV the type of the Value in the Key-Value store.
+ * @return the event channel for the channel name.
+ */
+ private <K, V> IEventChannel<K, V> createChannelImpl(
+ String channelName,
+ Class<K> typeK, Class<V> typeV) {
+ IEventChannel<?, ?> genericEventChannel =
+ eventChannels.get(channelName);
+
+ // Add the channel if the first listener
+ if (genericEventChannel == null) {
+ IEventChannel<K, V> castedEventChannel =
+ new HazelcastEventChannel<K, V>(hazelcastInstance,
+ channelName, typeK, typeV);
+ eventChannels.put(channelName, castedEventChannel);
+ return castedEventChannel;
+ }
+
+ //
+ // TODO: Find if we can use Java internal support to check for
+ // type mismatch.
+ //
+ if (!genericEventChannel.verifyKeyValueTypes(typeK, typeV)) {
+ throw new ClassCastException("Key-value type mismatch for event channel " + channelName);
+ }
+ @SuppressWarnings("unchecked")
+ IEventChannel<K, V> castedEventChannel =
+ (IEventChannel<K, V>) genericEventChannel;
+ return castedEventChannel;
+ }
+
+ /**
+ * Add event channel listener.
+ * <p/>
+ * NOTE: The channel is started automatically right after the listener
+ * is added.
+ *
+ * @param channelName the event channel name.
+ * @param listener the listener to add.
+ * @param <K> the type of the Key in the Key-Value store.
+ * @param <V> the type of the Value in the Key-Value store.
+ * @param typeK the type of the Key in the Key-Value store.
+ * @param typeV the type of the Value in the Key-Value store.
+ * @return the event channel for the channel name.
+ */
+ @Override
+ public <K, V> IEventChannel<K, V> addListener(String channelName,
+ IEventChannelListener<K, V> listener,
+ Class<K> typeK, Class<V> typeV) {
+ synchronized (eventChannels) {
+ IEventChannel<K, V> eventChannel =
+ createChannelImpl(channelName, typeK, typeV);
+ eventChannel.addListener(listener);
+ eventChannel.startup();
+
+ return eventChannel;
+ }
+ }
+
+ /**
+ * Remove event channel listener.
+ *
+ * @param <K> the type of the Key in the Key-Value store.
+ * @param <V> the type of the Value in the Key-Value store.
+ * @param channelName the event channel name.
+ * @param listener the listener to remove.
+ */
+ @Override
+ public <K, V> void removeListener(String channelName,
+ IEventChannelListener<K, V> listener) {
+ synchronized (eventChannels) {
+ IEventChannel<?, ?> genericEventChannel =
+ eventChannels.get(channelName);
+
+ if (genericEventChannel != null) {
+ //
+ // TODO: Find if we can use Java internal support to check for
+ // type mismatch.
+ // NOTE: Using "ClassCastException" exception below doesn't
+ // work.
+ //
+ @SuppressWarnings("unchecked")
+ IEventChannel<K, V> castedEventChannel =
+ (IEventChannel<K, V>) genericEventChannel;
+ castedEventChannel.removeListener(listener);
+ }
+ }
+ }
+}