[COMM] improve trace stop routine (receiving data channel until MSG_TERMINATE)
authorgreatim <jaewon81.lim@samsung.com>
Fri, 25 Sep 2015 04:44:49 +0000 (13:44 +0900)
committergreatim <jaewon81.lim@samsung.com>
Wed, 30 Sep 2015 18:42:11 +0000 (03:42 +0900)
make sure there is no more data to receive from data channel
add synchronization for device attachment and detachment

Change-Id: I9306389bd684a1d506628df8b085be3974ea8eed
Signed-off-by: greatim <jaewon81.lim@samsung.com>
org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/communicator/DeviceManager.java [changed mode: 0644->0755]
org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/swap/communicator/DataChannelThread.java [changed mode: 0644->0755]

old mode 100644 (file)
new mode 100755 (executable)
index 627c5d3..9bfb9a3
@@ -55,48 +55,32 @@ public class DeviceManager {
        private static IDeviceChangeListener deviceChanged = new IDeviceChangeListener() {
                @Override
                public void onDisconnected(IDevice device) {
-                       // called : each device disconnected time
-                       if (onDisconnectedInternal(device)) {
-                               // this should be asyncExec
-                               // think about this happened while device combo is middle of selection
-                               Display.getDefault().asyncExec(new Runnable() {
-                                       @Override
-                                       public void run() {
-                                               if (!Toolbar.INSTANCE.updateDeviceCombo(null)) {
-                                                       Toolbar.INSTANCE.updateAppCombo(true);
+                       synchronized (devices) {
+                               // called : each device disconnected time
+                               if (onDisconnectedInternal(device)) {
+                                       // this should be asyncExec
+                                       // think about this happened while device combo is middle of
+                                       // selection
+                                       Display.getDefault().asyncExec(new Runnable() {
+                                               @Override
+                                               public void run() {
+                                                       if (!Toolbar.INSTANCE.updateDeviceCombo(null)) {
+                                                               Toolbar.INSTANCE.updateAppCombo(true);
+                                                       }
                                                }
-                                       }
-                               });
+                                       });
+                               }
                        }
                }
 
                @Override
                public void onConnected(IDevice device) {
-                       // It called when dynamic-analyzer start, only one time
-                       if (onConnectedInternal(device)) {
-                               // this should be asyncExec
-                               // think about this happened while device combo is middle of selection
-                               Display.getDefault().asyncExec(new Runnable() {
-                                       @Override
-                                       public void run() {
-                                               if (!Toolbar.INSTANCE.updateDeviceCombo(null)) {
-                                                       Toolbar.INSTANCE.updateAppCombo(true);
-                                               }
-                                       }
-                               });
-                       }
-               }
-
-               @Override
-               public void onChanged(IDevice device, int changeMask) {
-                       // called : device added - already dynamic-analyzer running (not tracing)
-                       Logger.debug("device changed : " + device.getSerialNumber() + " : " + changeMask);
-                       if (1 == changeMask) { // state changed (offline -> online, vice versa)
-                               boolean bRemoved = onDisconnectedInternal(device);
-                               boolean bAdded = onConnectedInternal(device);
-                               if (bRemoved || bAdded) {
+                       synchronized (devices) {
+                               // It called when dynamic-analyzer start, only one time
+                               if (onConnectedInternal(device)) {
                                        // this should be asyncExec
-                                       // think about this happened while device combo is middle of selection
+                                       // think about this happened while device combo is middle of
+                                       // selection
                                        Display.getDefault().asyncExec(new Runnable() {
                                                @Override
                                                public void run() {
@@ -106,26 +90,53 @@ public class DeviceManager {
                                                }
                                        });
                                }
-                       } else {
-                               // do nothing
+                       }
+               }
+
+               @Override
+               public void onChanged(IDevice device, int changeMask) {
+                       synchronized (devices) {
+                               // called : device added - already dynamic-analyzer running (not
+                               // tracing)
+                               Logger.debug("device changed : " + device.getSerialNumber() + " : " + changeMask);
+                               if (1 == changeMask) { // state changed (offline -> online, vice
+                                                                               // versa)
+                                       boolean bRemoved = onDisconnectedInternal(device);
+                                       boolean bAdded = onConnectedInternal(device);
+                                       if (bRemoved || bAdded) {
+                                               // this should be asyncExec
+                                               // think about this happened while device combo is
+                                               // middle of selection
+                                               Display.getDefault().asyncExec(new Runnable() {
+                                                       @Override
+                                                       public void run() {
+                                                               if (!Toolbar.INSTANCE.updateDeviceCombo(null)) {
+                                                                       Toolbar.INSTANCE.updateAppCombo(true);
+                                                               }
+                                                       }
+                                               });
+                                       }
+                               } else {
+                                       // do nothing
+                               }
                        }
                }
        };
 
+       // this method should be called inside synchronized(devices) block
        private static boolean onDisconnectedInternal(IDevice device) {
                boolean bRemoved = false;
                Logger.debug("device disconnected : " + device.getSerialNumber());
                DeviceInfo deviceInfo = getDeviceByName(device.getSerialNumber());
                if (deviceInfo != null) {
-                       synchronized (devices) {
-                               bRemoved = devices.remove(deviceInfo);
-                       }
+                       bRemoved = devices.remove(deviceInfo);
                        deviceInfo.getCommunicator().disconnect();
                }
 
                return bRemoved;
        }
 
+       // this method should be called inside synchronized(devices) block
        private static boolean onConnectedInternal(IDevice device) {
                boolean bAdded = false;
                DeviceInfo devInfo = new DeviceInfo(device);
@@ -136,9 +147,7 @@ public class DeviceManager {
                // connect with swap of device
                DAResult result = devInfo.getCommunicator().connect();
                if (result.isSuccess()) {
-                       synchronized (devices) {
-                               devices.add(devInfo);
-                       }
+                       devices.add(devInfo);
                        bAdded = true;
                } else {
                        Logger.warning("Cannot connect with swap manager : " + result.getMessage());
@@ -157,11 +166,13 @@ public class DeviceManager {
 
        public static void loadDevices() {
                if (null != sdbBridge) {
-                       IDevice[] devices = sdbBridge.getDevices();
-                       int size = devices.length;
-                       for (int i = 0; i < size; i++) {
-                               if (isOnline(devices[i])) {
-                                       onConnectedInternal(devices[i]);
+                       synchronized (devices) {
+                               IDevice[] devices = sdbBridge.getDevices();
+                               int size = devices.length;
+                               for (int i = 0; i < size; i++) {
+                                       if (isOnline(devices[i])) {
+                                               onConnectedInternal(devices[i]);
+                                       }
                                }
                        }
                } else {
old mode 100644 (file)
new mode 100755 (executable)
index 414434b..ada4349
@@ -72,6 +72,10 @@ public class DataChannelThread extends DataThread<Object> {
        }
 
        private STATE state = STATE.INITIALIZED;
+       
+       private static class EndOfTraceException extends Exception {
+               private static final long serialVersionUID = -1012165582483739981L;
+       }
 
        public static DataChannelThread getInstance() {
                return instance;
@@ -251,9 +255,13 @@ public class DataChannelThread extends DataThread<Object> {
                                                }
                                        }
                                }
-                       } catch (SocketTimeoutException e) {
-                               // timeout to read (there is no more data to read)
+                       } catch (EndOfTraceException e) {
+                               // this means there is no more data to read
                                // do nothing
+                               Logger.debug("there is no more data to read");
+                       } catch (SocketTimeoutException e) {
+                               // timeout to read (maybe connection is broken)
+                               notifyStopWork(new DAResult(ErrorCode.ERR_DISCONNECTED), false);
                                Logger.exception(e);
                        } catch (InterruptedIOException e) {
                                // thread is interrupted by other thread during reading from socket
@@ -280,11 +288,12 @@ public class DataChannelThread extends DataThread<Object> {
        }
 
        // interruptible read byte from InputStream
-       private int readByte(InputStream input, byte[] buffer, int length) throws IOException {
+       private int readByte(InputStream input, byte[] buffer, int length) throws IOException, EndOfTraceException {
                // read data message header
                int toRead = length;
                int readSize = 0;
                int timeoutValue = 0;
+               boolean stopControlChannel = false;
                while (toRead > 0) {
                        try {
                                readSize = input.read(buffer, length - toRead, toRead);
@@ -305,7 +314,11 @@ public class DataChannelThread extends DataThread<Object> {
 
                                // check if stop ack arrived
                                if (AnalyzerManager.isStopAckArrived()) {
-                                       throw new SocketTimeoutException();
+                                       if (stopControlChannel) {
+                                               throw new EndOfTraceException();
+                                       } else {
+                                               stopControlChannel = true;
+                                       }
                                }
 
                                // check the real timeout for socket
@@ -355,9 +368,9 @@ public class DataChannelThread extends DataThread<Object> {
                        }
                }
 
-               // exit data channel thread only if ensure stop ack is arrived
-               // that means there is no more data to received by data channel
-               if (AnalyzerManager.isStopAckArrived()) {
+               // exit data channel thread only if both stop ack and terminate msg are arrived
+               // that means there is no more data to receive via data channel
+               if (AnalyzerManager.isTerminateMsgArrived() && AnalyzerManager.isStopAckArrived()) {
                        return true;
                } else {
                        return false;