Cherry-pick from https://gerrit.onos.onlab.us/#/c/337/

Add a rollback method for clearing cache of IDeviceObject.
Call the rollback method in Forwarding.class.

Change-Id: I32c85708a5595c7cd70f239eaefd1f2f96812de1
diff --git a/src/main/java/net/onrc/onos/ofcontroller/core/IDeviceStorage.java b/src/main/java/net/onrc/onos/ofcontroller/core/IDeviceStorage.java
index 2eddadf..9818b1b 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/core/IDeviceStorage.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/core/IDeviceStorage.java
@@ -14,6 +14,8 @@
 	public IDeviceObject getDeviceByIP(int ipv4Address);
 	public void changeDeviceAttachments(IDevice device);
 	public void changeDeviceIPv4Address(IDevice device);
+	public void rollback();
+	public void commit();
 	
 	public void addOnosDevice(OnosDevice onosDevice);
 }
diff --git a/src/main/java/net/onrc/onos/ofcontroller/core/internal/DeviceStorageImpl.java b/src/main/java/net/onrc/onos/ofcontroller/core/internal/DeviceStorageImpl.java
index 0699491..94954a6 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/core/internal/DeviceStorageImpl.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/core/internal/DeviceStorageImpl.java
@@ -162,6 +162,20 @@
 	}
 
 	/***
+	 * This function is for closing the DB transaction properly.
+	 * After you use any DB operation, to clear the cache of transaction, it should be called.
+	 */
+	@Override
+	public void rollback() {
+		ope.rollback();
+	}
+	
+	@Override
+	public void commit(){
+		ope.commit();
+	}
+
+	/***
 	 * This function is for getting the Device from the DB by IP address of the device.
 	 * @param ip The device ip address you want to get from the DB.
 	 * @return IDeviceObject you want to get.
diff --git a/src/main/java/net/onrc/onos/ofcontroller/forwarding/Forwarding.java b/src/main/java/net/onrc/onos/ofcontroller/forwarding/Forwarding.java
index 479f170..9947eb0 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/forwarding/Forwarding.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/forwarding/Forwarding.java
@@ -253,22 +253,24 @@
 		String destinationMac = 
 				HexString.toHexString(eth.getDestinationMACAddress()); 
 		
-		//FIXME TitanTransaction opened here probably needs to be either commit()/rollback() to avoid transaction leak, before exiting run().
-		//But it seems that IDeviceStorage does not provide a way to close transaction properly.
-		//Also getDeviceByMac() is a blocking call, so it may be better way to handle it to avoid the condition.
-		IDeviceObject deviceObject = deviceStorage.getDeviceByMac(
+		//FIXME getDeviceByMac() is a blocking call, so it may be better way to handle it to avoid the condition.
+		try{	
+			IDeviceObject deviceObject = deviceStorage.getDeviceByMac(
 				destinationMac);
-		
-		if (deviceObject == null) {
-			log.debug("No device entry found for {}",
-					destinationMac);
-			
-			//Device is not in the DB, so wait it until the device is added.
-			executor.schedule(new WaitDeviceArp(sw, pi, eth), SLEEP_TIME_FOR_DB_DEVICE_INSTALLED, TimeUnit.MILLISECONDS);
-			return;
+
+			if (deviceObject == null) {
+				log.debug("No device entry found for {}",
+						destinationMac);
+
+				//Device is not in the DB, so wait it until the device is added.
+				executor.schedule(new WaitDeviceArp(sw, pi, eth), SLEEP_TIME_FOR_DB_DEVICE_INSTALLED, TimeUnit.MILLISECONDS);
+				return;
+			}
+
+			continueHandlePacketIn(sw, pi, eth, deviceObject);
+		} finally {
+			deviceStorage.rollback();
 		}
-		
-		continueHandlePacketIn(sw, pi, eth, deviceObject);
 	}
 	
 	private class WaitDeviceArp implements Runnable {
@@ -285,14 +287,18 @@
 
 		@Override
 		public void run() {
+			try {
 				IDeviceObject deviceObject = deviceStorage.getDeviceByMac(HexString.toHexString(eth.getDestinationMACAddress()));
-				if(deviceObject == null){
-					log.debug("wait {}ms and device was not found. Send broadcast packet and the thread finish.", SLEEP_TIME_FOR_DB_DEVICE_INSTALLED);
-					handleBroadcast(sw, pi, eth);
-					return;
-				}
-				log.debug("wait {}ms and device {} was found, continue",SLEEP_TIME_FOR_DB_DEVICE_INSTALLED, deviceObject.getMACAddress());
-				continueHandlePacketIn(sw, pi, eth, deviceObject);
+					if(deviceObject == null){
+						log.debug("wait {}ms and device was not found. Send broadcast packet and the thread finish.", SLEEP_TIME_FOR_DB_DEVICE_INSTALLED);
+						handleBroadcast(sw, pi, eth);
+						return;
+					}
+					log.debug("wait {}ms and device {} was found, continue",SLEEP_TIME_FOR_DB_DEVICE_INSTALLED, deviceObject.getMACAddress());
+					continueHandlePacketIn(sw, pi, eth, deviceObject);
+			} finally {
+				deviceStorage.rollback();
+			}
 		}
 	}