tests to specify when modification count for file is advanced and when it isn't advanced
authorMaxim.Mossienko <Maxim.Mossienko@jetbrains.com>
Thu, 17 Nov 2016 14:17:09 +0000 (15:17 +0100)
committerMaxim.Mossienko <Maxim.Mossienko@jetbrains.com>
Thu, 17 Nov 2016 14:23:28 +0000 (15:23 +0100)
platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java
platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/LocalFileSystemTest.java
platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/PersistentFsTest.java

index 30f7c7724f986bc40073b172f351de55a1cf1265..6e340aa581098d3b055af3b2771be8f61108f054 100644 (file)
@@ -1001,21 +1001,16 @@ public class FSRecords {
   }
 
   private static void incModCount(int id) {
-    DbConnection.markDirty();
-    ourLocalModificationCount++;
+    incLocalModCount();
     final int count = getModCount() + 1;
     getRecords().putInt(HEADER_GLOBAL_MOD_COUNT_OFFSET, count);
 
-    int parent = id;
-    int depth = 10000;
-    while (parent != 0) {
-      setModCount(parent, count);
-      parent = getParent(parent);
-      if (depth -- == 0) {
-        LOG.error("Cyclic parent child relation? file: " + getName(id));
-        return;
-      }
-    }
+    setModCount(id, count);
+  }
+
+  private static void incLocalModCount() {
+    DbConnection.markDirty();
+    ourLocalModificationCount++;
   }
 
   static int getLocalModCount() {
@@ -1226,8 +1221,12 @@ public class FSRecords {
   public static void setLength(int id, long len) {
     w.lock();
     try {
-      incModCount(id);
-      getRecords().putLong(getOffset(id, LENGTH_OFFSET), len);
+      ResizeableMappedFile records = getRecords();
+      int lengthOffset = getOffset(id, LENGTH_OFFSET);
+      if (records.getLong(lengthOffset) != len) {
+        incModCount(id);
+        records.putLong(lengthOffset, len);
+      }
     }
     catch (Throwable e) {
       DbConnection.handleError(e);
@@ -1250,8 +1249,12 @@ public class FSRecords {
   public static void setTimestamp(int id, long value) {
     w.lock();
     try {
-      incModCount(id);
-      getRecords().putLong(getOffset(id, TIMESTAMP_OFFSET), value);
+      int timeStampOffset = getOffset(id, TIMESTAMP_OFFSET);
+      ResizeableMappedFile records = getRecords();
+      if (records.getLong(timeStampOffset) != value) {
+        incModCount(id);
+        records.putLong(timeStampOffset, value);
+      }
     }
     catch (Throwable e) {
       DbConnection.handleError(e);
@@ -1645,8 +1648,6 @@ public class FSRecords {
       RefCountingStorage contentStorage = getContentStorage();
       w.lock();
       try {
-        incModCount(myFileId);
-
         checkFileIsValid(myFileId);
 
         int page;
@@ -1654,8 +1655,10 @@ public class FSRecords {
         if (weHaveContentHashes) {
           page = findOrCreateContentRecord(bytes.getBytes(), bytes.getOffset(), bytes.getLength());
 
-          incModCount(myFileId);
-          checkFileIsValid(myFileId);
+          if (page < 0 || getContentId(myFileId) != page) {
+            incModCount(myFileId);
+            setContentRecordId(myFileId, page > 0 ? page : -page);
+          }
 
           setContentRecordId(myFileId, page > 0 ? page : -page);
 
@@ -1663,6 +1666,7 @@ public class FSRecords {
           page = -page;
           fixedSize = true;
         } else {
+          incModCount(myFileId);
           page = getContentRecordId(myFileId);
           if (page == 0 || contentStorage.getRefCount(page) > 1) {
             page = contentStorage.acquireNewRecord();
@@ -1782,7 +1786,7 @@ public class FSRecords {
           w.lock();
           try {
             rewriteDirectoryRecordWithAttrContent(_out);
-            incModCount(myFileId);
+            incLocalModCount();
           }
           finally {
             w.unlock();
@@ -1791,7 +1795,7 @@ public class FSRecords {
         else {
           w.lock();
           try {
-            incModCount(myFileId);
+            incLocalModCount();
             int page = findAttributePage(myFileId, myAttribute, true);
             if (inlineAttributes && page < 0) {
               rewriteDirectoryRecordWithAttrContent(new BufferExposingByteArrayOutputStream());
index 485701fb2277acabccd2c7a655eb73aaa2441c2e..1445241d4314d9e931abfb31b6c4c38c3f23d7d9 100644 (file)
@@ -720,25 +720,6 @@ public class LocalFileSystemTest extends PlatformTestCase {
     assertWritable(file, vFile, true);
   }
 
-  public void testModCountIncreases() throws IOException {
-    File file = IoTestUtil.createTestFile("file.txt");
-    VirtualFile vFile = myFS.refreshAndFindFileByIoFile(file);
-    assertNotNull(vFile);
-    assertWritable(file, vFile, true);
-    ManagingFS managingFS = ManagingFS.getInstance();
-    final int globalModCount = managingFS.getFilesystemModificationCount();
-    final int parentModCount = managingFS.getModificationCount(vFile.getParent());
-
-    ApplicationManager.getApplication().runWriteAction((ThrowableComputable<Object, IOException>)() -> {
-      vFile.setWritable(false);
-      return null;
-    });
-
-    assertEquals(globalModCount + 1, managingFS.getModificationCount(vFile));
-    assertEquals(globalModCount + 1, managingFS.getFilesystemModificationCount());
-    assertEquals(globalModCount + 1, managingFS.getModificationCount(vFile.getParent()));
-  }
-
   private static void assertWritable(File file, VirtualFile vFile, boolean expected) {
     assertEquals(expected, file.canWrite());
     assertEquals(expected, ObjectUtils.assertNotNull(FileSystemUtil.getAttributes(file)).isWritable());
index f349f8f8a313cf2f5085c3443875141358cbb0bf..e834f0983514418cb3188790c0fc6d802744f318 100644 (file)
  */
 package com.intellij.openapi.vfs.local;
 
+import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.ThrowableComputable;
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.util.io.IoTestUtil;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.*;
 import com.intellij.openapi.vfs.ex.temp.TempFileSystem;
+import com.intellij.openapi.vfs.newvfs.FileAttribute;
+import com.intellij.openapi.vfs.newvfs.ManagingFS;
 import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
+import com.intellij.openapi.vfs.newvfs.persistent.FSRecords;
 import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS;
 import com.intellij.testFramework.LoggedErrorProcessor;
 import com.intellij.testFramework.PlatformTestCase;
+import com.intellij.util.io.DataInputOutputUtil;
 import org.apache.log4j.Logger;
 import org.jetbrains.annotations.NotNull;
 
+import java.io.DataOutputStream;
 import java.io.File;
+import java.io.IOException;
+import java.nio.charset.Charset;
 import java.util.jar.JarFile;
 
 public class PersistentFsTest extends PlatformTestCase {
@@ -169,4 +178,78 @@ public class PersistentFsTest extends PlatformTestCase {
 
     assertEquals(1, logCount[0]);
   }
+
+  public void testModCountIncreases() throws IOException {
+    VirtualFile vFile = setupFile();
+    ManagingFS managingFS = ManagingFS.getInstance();
+    int globalModCount = managingFS.getFilesystemModificationCount();
+    final int parentModCount = managingFS.getModificationCount(vFile.getParent());
+
+    ApplicationManager.getApplication().runWriteAction((ThrowableComputable<Object, IOException>)() -> {
+      vFile.setWritable(false);
+      return null;
+    });
+
+    assertEquals(globalModCount + 1, managingFS.getModificationCount(vFile));
+    assertEquals(globalModCount + 1, managingFS.getFilesystemModificationCount());
+    assertEquals(parentModCount, managingFS.getModificationCount(vFile.getParent()));
+
+    FSRecords.force();
+    assertTrue(!FSRecords.isDirty());
+    ++globalModCount;
+
+    ApplicationManager.getApplication().runWriteAction((ThrowableComputable<Object, IOException>)() -> {
+      vFile.setWritable(true);  // 1
+      vFile.setBinaryContent("foo".getBytes(Charset.defaultCharset())); // 1 + timestamp + length
+      return null;
+    });
+
+    assertEquals(globalModCount + 4, managingFS.getModificationCount(vFile));
+    assertEquals(globalModCount + 4, managingFS.getFilesystemModificationCount());
+    assertEquals(parentModCount, managingFS.getModificationCount(vFile.getParent()));
+  }
+
+  @NotNull
+  private static VirtualFile setupFile() throws IOException {
+    File file = IoTestUtil.createTestFile("file.txt");
+    VirtualFile vFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file);
+    assertNotNull(vFile);
+    return vFile;
+  }
+
+  public void testModCountNotIncreases() throws IOException {
+    VirtualFile vFile = setupFile();
+    ManagingFS managingFS = ManagingFS.getInstance();
+    final int globalModCount = managingFS.getFilesystemModificationCount();
+    final int parentModCount = managingFS.getModificationCount(vFile.getParent());
+
+    FSRecords.force();
+    assertTrue(!FSRecords.isDirty());
+
+    FileAttribute attribute = new FileAttribute("test.attribute", 1, true);
+    ApplicationManager.getApplication().runWriteAction((ThrowableComputable<Object, IOException>)() -> {
+      try(DataOutputStream output = attribute.writeAttribute(vFile)) {
+        DataInputOutputUtil.writeINT(output, 1);
+      }
+      return null;
+    });
+
+    assertEquals(globalModCount, managingFS.getModificationCount(vFile));
+    assertEquals(globalModCount, managingFS.getFilesystemModificationCount());
+    assertEquals(parentModCount, managingFS.getModificationCount(vFile.getParent()));
+
+    assertTrue(FSRecords.isDirty());
+    FSRecords.force();
+    assertTrue(!FSRecords.isDirty());
+
+    //
+    int fileId = ((VirtualFileWithId)vFile).getId();
+    FSRecords.setTimestamp(fileId, FSRecords.getTimestamp(fileId));
+    FSRecords.setLength(fileId, FSRecords.getLength(fileId));
+
+    assertEquals(globalModCount, managingFS.getModificationCount(vFile));
+    assertEquals(globalModCount, managingFS.getFilesystemModificationCount());
+    assertEquals(parentModCount, managingFS.getModificationCount(vFile.getParent()));
+    assertTrue(!FSRecords.isDirty());
+  }
 }