IGNITE-8831 Fix of MarshallerMappingFileStore: Incorrect locks on files. - 
Fixes #4224.

Signed-off-by: Dmitriy Pavlov <dpav...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/417d31d1
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/417d31d1
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/417d31d1

Branch: refs/heads/ignite-8446
Commit: 417d31d18c6142ac6d279820d77dc1a2df4c6f9c
Parents: e5af599
Author: Alexey Stelmak <spiderru5...@gmail.com>
Authored: Fri Jun 22 16:43:53 2018 +0300
Committer: Dmitriy Pavlov <dpav...@apache.org>
Committed: Fri Jun 22 16:43:53 2018 +0300

----------------------------------------------------------------------
 .../internal/MarshallerMappingFileStore.java    | 85 ++++++++++++--------
 1 file changed, 50 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/417d31d1/modules/core/src/main/java/org/apache/ignite/internal/MarshallerMappingFileStore.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/MarshallerMappingFileStore.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/MarshallerMappingFileStore.java
index 6fb1371..a01981b 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/MarshallerMappingFileStore.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/MarshallerMappingFileStore.java
@@ -45,6 +45,9 @@ import org.apache.ignite.marshaller.MarshallerContext;
  * when a classname is requested but is not presented in local cache of {@link 
MarshallerContextImpl}.
  */
 final class MarshallerMappingFileStore {
+    /** File lock timeout in milliseconds. */
+    private static final int FILE_LOCK_TIMEOUT_MS = 5000;
+
     /** */
     private static final GridStripedLock fileLock = new GridStripedLock(32);
 
@@ -92,14 +95,12 @@ final class MarshallerMappingFileStore {
             File file = new File(workDir, fileName);
 
             try (FileOutputStream out = new FileOutputStream(file)) {
-                FileLock fileLock = fileLock(out.getChannel(), false);
-
-                assert fileLock != null : fileName;
-
                 try (Writer writer = new OutputStreamWriter(out, 
StandardCharsets.UTF_8)) {
-                    writer.write(typeName);
+                    try (FileLock ignored = fileLock(out.getChannel(), false)) 
{
+                        writer.write(typeName);
 
-                    writer.flush();
+                        writer.flush();
+                    }
                 }
             }
             catch (IOException e) {
@@ -120,11 +121,10 @@ final class MarshallerMappingFileStore {
     }
 
     /**
-     * @param platformId Platform id.
-     * @param typeId Type id.
+     * @param fileName File name.
      */
-    String readMapping(byte platformId, int typeId) throws 
IgniteCheckedException {
-        String fileName = getFileName(platformId, typeId);
+    private String readMapping(String fileName) throws IgniteCheckedException {
+        ThreadLocalRandom rnd = null;
 
         Lock lock = fileLock(fileName);
 
@@ -133,17 +133,30 @@ final class MarshallerMappingFileStore {
         try {
             File file = new File(workDir, fileName);
 
-            try (FileInputStream in = new FileInputStream(file)) {
-                FileLock fileLock = fileLock(in.getChannel(), true);
+            long time = 0;
+
+            while (true) {
+                try (FileInputStream in = new FileInputStream(file)) {
+                    try (BufferedReader reader = new BufferedReader(new 
InputStreamReader(in, StandardCharsets.UTF_8))) {
+                        try (FileLock ignored = fileLock(in.getChannel(), 
true)) {
+                            if (file.length() > 0)
+                                return reader.readLine();
+
+                            if (rnd == null)
+                                rnd = ThreadLocalRandom.current();
 
-                assert fileLock != null : fileName;
+                            if (time == 0)
+                                time = U.currentTimeMillis();
+                            else if ((U.currentTimeMillis() - time) >= 
FILE_LOCK_TIMEOUT_MS)
+                                return null;
 
-                try (BufferedReader reader = new BufferedReader(new 
InputStreamReader(in, StandardCharsets.UTF_8))) {
-                    return reader.readLine();
+                            U.sleep(rnd.nextLong(50));
+                        }
+                    }
+                }
+                catch (IOException ignored) {
+                    return null;
                 }
-            }
-            catch (IOException ignored) {
-                return null;
             }
         }
         finally {
@@ -152,6 +165,14 @@ final class MarshallerMappingFileStore {
     }
 
     /**
+     * @param platformId Platform id.
+     * @param typeId Type id.
+     */
+    String readMapping(byte platformId, int typeId) throws 
IgniteCheckedException {
+        return readMapping(getFileName(platformId, typeId));
+    }
+
+    /**
      * Restores all mappings available in file system to marshaller context.
      * This method should be used only on node startup.
      *
@@ -165,22 +186,16 @@ final class MarshallerMappingFileStore {
 
             int typeId = getTypeId(name);
 
-            try (FileInputStream in = new FileInputStream(file)) {
-                try (BufferedReader reader = new BufferedReader(new 
InputStreamReader(in, StandardCharsets.UTF_8))) {
-                    String clsName = reader.readLine();
+            String clsName = readMapping(name);
 
-                    if (clsName == null) {
-                        throw new IgniteCheckedException("Class name is null 
for [platformId=" + platformId +
-                            ", typeId=" + typeId + "], marshaller mappings 
storage is broken. " +
-                            "Clean up marshaller directory 
(<work_dir>/marshaller) and restart the node.");
-                    }
-
-                    marshCtx.registerClassNameLocally(platformId, typeId, 
clsName);
-                }
-            }
-            catch (IOException e) {
-                throw new IgniteCheckedException("Reading marshaller mapping 
from file " + name + " failed.", e);
+            if (clsName == null) {
+                throw new IgniteCheckedException("Class name is null for 
[platformId=" + platformId +
+                    ", typeId=" + typeId + "], marshaller mappings storage is 
broken. " +
+                    "Clean up marshaller directory (<work_dir>/marshaller) and 
restart the node. File name: " + name +
+                    ", FileSize: " + file.length());
             }
+
+            marshCtx.registerClassNameLocally(platformId, typeId, clsName);
         }
     }
 
@@ -276,10 +291,10 @@ final class MarshallerMappingFileStore {
         while (true) {
             FileLock fileLock = ch.tryLock(0L, Long.MAX_VALUE, shared);
 
-            if (fileLock == null)
-                U.sleep(rnd.nextLong(50));
-            else
+            if (fileLock != null)
                 return fileLock;
+
+            U.sleep(rnd.nextLong(50));
         }
     }
 }

Reply via email to