VMProperty: prepare for property file corruption
authorSeokYeon Hwang <syeon.hwang@samsung.com>
Fri, 29 Jan 2016 06:21:30 +0000 (15:21 +0900)
committerSeokYeon Hwang <syeon.hwang@samsung.com>
Fri, 29 Jan 2016 06:38:56 +0000 (15:38 +0900)
Always truncate property file before re-writing.
If property file is corrupted, we can handle it now.

Change-Id: Id35a4bf452a769bf4af8abcddd0eeb89312323ef
Signed-off-by: SeokYeon Hwang <syeon.hwang@samsung.com>
src/org/tizen/emulator/manager/vms/ManagedVMKeeper.java
src/org/tizen/emulator/manager/vms/VMKeeper.java
src/org/tizen/emulator/manager/vms/VMProperty.java
src/org/tizen/emulator/manager/vms/VMPropertyConfiguration.java
src/org/tizen/emulator/manager/vms/monitor/PosixLockFileMonitor.java
src/org/tizen/emulator/manager/vms/monitor/VMAvailabilityMonitor.java

index 010dda9..a091b57 100644 (file)
@@ -8,6 +8,7 @@ import java.util.concurrent.ConcurrentLinkedQueue;
 
 import javax.xml.bind.JAXBException;
 
+import org.tizen.emulator.manager.vms.VMProperty.Health;
 import org.tizen.emulator.manager.vms.monitor.FileAssetsMonitor;
 import org.tizen.emulator.manager.vms.monitor.FileWatcher;
 import org.tizen.emulator.manager.vms.monitor.RunningMonitor;
@@ -57,11 +58,8 @@ public class ManagedVMKeeper extends VMKeeper {
                assert Files.isRegularFile(propertyFilePath);
 
                VMProperty property = newProperty(propertyFilePath);
-               if (property == null) {
-                       return;
-               }
 
-               assert !properties.contains(property);
+               assert property.getHealth() != Health.CORRUPTED && !properties.contains(property);
 
                properties.add(property);
        }
index c5ba73e..81896c1 100644 (file)
@@ -131,53 +131,48 @@ public abstract class VMKeeper {
         */
        public abstract Queue<VMProperty> getProperties();
 
-       /**
-        * Create 'VMProperty' that have empty emulator configuration
-        * @param name
-        * @return
-        */
-       public synchronized VMProperty newProperty(VMPropertyValue value) {
-               return new VMProperty(value);
+       public VMProperty newProperty(VMPropertyValue value) {
+               return VMProperty.createNew(value);
        }
 
        public VMProperty newProperty(Path propertyFile) {
-               VMProperty property = new VMProperty(propertyFile);
-
-               return property;
+               return VMProperty.loadFrom(propertyFile);
        }
 
-       EmulatorConfiguration parseXML(Path propertyFile) {
+       synchronized EmulatorConfiguration parseXML(Path propertyFile) {
                JAXBElement<EmulatorConfiguration> element = null;
 
-               synchronized (context) {
+               FileChannel fc = null;
+               FileLock lock = null;
+               try {
+                       fc = FileChannel.open(propertyFile, StandardOpenOption.READ, StandardOpenOption.WRITE);
+                       lock = fc.lock();
+
+                       Unmarshaller unmarshaller = context.createUnmarshaller();
+                       element = unmarshaller.unmarshal(new StreamSource(Channels.newInputStream(fc)),
+                                       EmulatorConfiguration.class);
+                       fc.close();
+               } catch (OverlappingFileLockException e) {
+                       // have not to enter here
+                       e.printStackTrace();
+                       assert false;
+               } catch (IOException e) {
+                       e.printStackTrace();
+               } catch (JAXBException e) {
+                       e.printStackTrace();
+                       EMLogger.getLogger().warning("Can not load config file( " //$NON-NLS-1$
+                                       + propertyFile + ")" + StringResources.NEW_LINE + e.getMessage()); //$NON-NLS-1$
+               } finally {
                        try {
-                               FileChannel fc = FileChannel.open(propertyFile, StandardOpenOption.READ, StandardOpenOption.WRITE);
-                               FileLock lock = fc.lock();
-
-
-                               try {
-                                       Unmarshaller unmarshaller = context.createUnmarshaller();
-                                       element = unmarshaller.unmarshal(new StreamSource(Channels.newInputStream(fc)),
-                                                       EmulatorConfiguration.class);
-                                       fc.close();
-                               } catch (IOException e) {
-                                       e.printStackTrace();
+                               if (lock != null && lock.isValid()) {
+                                       lock.release();
                                }
 
-                               if (lock.isValid()) {
-                                       lock.release();
+                               if (fc != null && fc.isOpen()) {
+                                       fc.close();
                                }
-                               fc.close();
-                       } catch (OverlappingFileLockException e) {
-                               // have not to enter here
-                               e.printStackTrace();
-                               assert false;
                        } catch (IOException e) {
                                e.printStackTrace();
-                       } catch (JAXBException e) {
-                               e.printStackTrace();
-                               EMLogger.getLogger().warning("Can not load config file( " //$NON-NLS-1$
-                                               + propertyFile + ")" + StringResources.NEW_LINE + e.getMessage()); //$NON-NLS-1$
                        }
                }
 
@@ -188,47 +183,50 @@ public abstract class VMKeeper {
                return null;
        }
 
-       boolean storeXML(VMProperty property){
+       synchronized boolean storeXML(VMProperty property){
                Path outputFile = property.getPropertyFile();
 
-               synchronized (context) {
-                       FileLock lock = null;
-                       FileChannel fc = null;
-                       try {
-                               Files.createDirectories(property.getPropertyFile().resolve("..").normalize());
+               FileChannel fc = null;
+               FileLock lock = null;
+               try {
+                       Files.createDirectories(property.getPropertyFile().resolve("..").normalize());
 
-                               fc = FileChannel.open(outputFile, StandardOpenOption.CREATE, StandardOpenOption.WRITE);
-                               lock = fc.lock();
+                       fc = FileChannel.open(outputFile, StandardOpenOption.CREATE, StandardOpenOption.WRITE,
+                                       StandardOpenOption.TRUNCATE_EXISTING);
+                       lock = fc.lock();
 
-                               assert lock != null;
+                       assert lock != null;
 
-                               if (!lock.isValid()) {
-                                       return false;
-                               }
-                       } catch (IOException e1) {
-                               // TODO Auto-generated catch block
-                               e1.printStackTrace();
-                       }
-
-                       OutputStream os = null;
-                       try {
-                               Marshaller marshaller = context.createMarshaller();
-                               marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8"); //$NON-NLS-1$
-                               marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
-
-                               os = Channels.newOutputStream(fc);
-                               marshaller.marshal(property.getVMConfiguration().getConfiguration(), os);
-                       } catch (JAXBException e) {
-                               e.printStackTrace();
+                       if (!lock.isValid()) {
                                return false;
                        }
+               } catch (IOException e1) {
+                       // TODO Auto-generated catch block
+                       e1.printStackTrace();
+               }
 
-                       try {
+               OutputStream os = null;
+               try {
+                       Marshaller marshaller = context.createMarshaller();
+                       marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8"); //$NON-NLS-1$
+                       marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+
+                       os = Channels.newOutputStream(fc);
+                       marshaller.marshal(property.getVMConfiguration().getConfiguration(), os);
+               } catch (JAXBException e) {
+                       e.printStackTrace();
+                       return false;
+               }
+
+               try {
+                       if (lock != null && lock.isValid()) {
                                lock.release();
+                       }
+                       if (fc != null && fc.isOpen()) {
                                fc.close();
-                       } catch (IOException e) {
-                               e.printStackTrace();
                        }
+               } catch (IOException e) {
+                       e.printStackTrace();
                }
 
                return true;
index e195483..98404e2 100644 (file)
@@ -68,6 +68,7 @@ public final class VMProperty {
                NOT_CHECKED,
                WELL,
                NOT_AVAILABLE,
+               CORRUPTED,
        }
 
        public static enum State {
@@ -98,14 +99,6 @@ public final class VMProperty {
                stateChangelisteners.remove(listener);
        }
 
-       private void stateChanged() {
-               synchronized (stateChangelisteners) {
-                       for (StateChangeListener<VMProperty> listener : stateChangelisteners) {
-                               listener.stateChanged(this);
-                       }
-               }
-       }
-
        public static void addHealthChangeListener(StateChangeListener<VMProperty> listener) {
                healthChangelisteners.add(listener);
        }
@@ -114,50 +107,56 @@ public final class VMProperty {
                healthChangelisteners.remove(listener);
        }
 
-       private void healthChanged() {
-               synchronized (healthChangelisteners) {
-                       for (StateChangeListener<VMProperty> listener : healthChangelisteners) {
-                               listener.stateChanged(this);
-                       }
-               }
-       }
+       static VMProperty loadFrom(Path propertyFile) {
+               VMProperty property = new VMProperty(propertyFile);
+               property.refresh();
 
-       @Override
-       public boolean equals(Object obj) {
-               if (obj == null) {
-                       return false;
-               }
-
-               VMProperty target = (VMProperty)obj;
-               if (target.getName().equals(getName())) {
-                       return true;
-               }
-               return false;
-       }
-
-       VMProperty(Path propertyFile) {
-               this.propertyFile = propertyFile;
-
-               refresh();
+               return property;
        }
 
-       VMProperty(VMPropertyValue value) {
+       static VMProperty createNew(VMPropertyValue value) {
                assert value != null;
 
                String directoryName = FilePathResources.getTizenVmsPath() + File.separator + value.vmsName;
                String propertyFilename = directoryName + File.separator + StringResources.PROPERTY_XML_NAME;
 
                Path propertyFile = Paths.get(propertyFilename);
+               assert Files.notExists(propertyFile);
 
+               VMProperty property = new VMProperty(propertyFile);
+               property.setPropertyValue(value);
+
+               return property;
+       }
+
+       private VMProperty(Path propertyFile) {
                this.propertyFile = propertyFile;
-               assert Files.notExists(propertyFile);
+       }
+
+       private void stateChanged() {
+               synchronized (stateChangelisteners) {
+                       for (StateChangeListener<VMProperty> listener : stateChangelisteners) {
+                               listener.stateChanged(this);
+                       }
+               }
+       }
 
-               setPropertyValue(value);
+       private void healthChanged() {
+               synchronized (healthChangelisteners) {
+                       for (StateChangeListener<VMProperty> listener : healthChangelisteners) {
+                               listener.stateChanged(this);
+                       }
+               }
        }
 
        void refresh() {
                EmulatorConfiguration element = EmulatorManager.getVMKeeper().parseXML(propertyFile);
 
+               // If vm_config.xml is corrupted
+               if (element == null) {
+                       setHealth(Health.CORRUPTED);
+               }
+
                this.configuration = new VMPropertyConfiguration(element);
 
                if (configuration.getName() != null) {
@@ -300,6 +299,19 @@ public final class VMProperty {
                return this.health == Health.WELL && this.state != State.NOT_SET;
        }
 
+       @Override
+       public boolean equals(Object obj) {
+               if (obj == null) {
+                       return false;
+               }
+
+               VMProperty target = (VMProperty)obj;
+               if (target.getName().equals(getName())) {
+                       return true;
+               }
+               return false;
+       }
+
        // for plug-in source -> need to delete
        @ Deprecated
        public EmulatorConfiguration getConfiguration() {
index 44fd386..1d8391a 100644 (file)
@@ -51,7 +51,13 @@ public class VMPropertyConfiguration {
        private final ObjectFactory factory = new ObjectFactory();
 
        public VMPropertyConfiguration(EmulatorConfiguration element) {
-               this.configuration = element;
+               // If vm_config.xml is corrupted
+               if (element == null) {
+                       configuration = factory.createEmulatorConfiguration();
+                       return;
+               }
+
+               configuration = element;
        }
 
        public VMPropertyConfiguration(VMPropertyValue value) {
index 3c88d22..9324098 100644 (file)
@@ -38,6 +38,7 @@ import java.nio.file.Paths;
 import java.nio.file.StandardOpenOption;
 
 import org.tizen.emulator.manager.vms.VMProperty;
+import org.tizen.emulator.manager.vms.VMProperty.Health;
 import org.tizen.emulator.manager.vms.VMProperty.State;
 
 final class PosixLockFileMonitor extends LockFileMonitor {
@@ -46,6 +47,10 @@ final class PosixLockFileMonitor extends LockFileMonitor {
        }
 
        private synchronized boolean examineLock(VMProperty property) throws IOException {
+               if (property.getHealth() == Health.CORRUPTED) {
+                       return false;
+               }
+
                Path lockfile = Paths.get(property.getChildImagePath());
 
                assert Files.isRegularFile(lockfile) && Files.isWritable(lockfile);
index 90747f9..bb9cf55 100644 (file)
@@ -78,6 +78,10 @@ public class VMAvailabilityMonitor implements Runnable, ListChangeListener<VMPro
        }
 
        private void checkAvailability(VMProperty property) {
+               if (property.getHealth() == Health.CORRUPTED) {
+                       return;
+               }
+
                // Check availability
                Path childImagePath = Paths.get(property.getChildImagePath());
                Path baseImagePath = Paths.get(property.getBaseImagePath());