Uploaded image for project: 'XNIO'
  1. XNIO
  2. XNIO-344

WatchServiceFileSystemWatcher has a possibility to prune all file change events and miss to invoke FileChangeCallback

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Done
    • Icon: Major Major
    • 3.7.3.Final
    • 3.6.6.Final, 3.7.2.Final
    • nio-impl
    • None
    • Hide

      1. Create two different file systems. For example, one for JBoss (/mnt/test/jboss) and another for the source directory of JSP (/mnt/test/jsp)

      2. Deploy test.war which contains example.jsp:

      <% out.println("example.jsp"); %>
      

      3. Access the example.jsp:

      curl -v localhost:8080/test/example.jsp
      

      4. Create an updated JSP file under /mnt/test/jsp:

      <% out.println("updated example.jsp"); %>
      

      5. move the updated.jsp as example.jsp under test.war:

      $ mv /mnt/test/jsp/updated.jsp /mnt/test/jboss/standalone/deployments/test.war/example.jsp
      

      6. Access the updated example.jsp:

      curl -v localhost:8080/test/example.jsp
      

      You will not see the updated JSP content but still see the old JSP content.

      -------------------

      You can reproduce the same issue by creating two directories having different project quota settings in the same one filesystem.

      1. mount the filesystem with enabling project quota ("prjquota" option):

      # mount /dev/mapper/<VG_LV-name> /mnt/test -o prjquota
      

      2. Create "/etc/projects" and "/etc/projid" like the following:
      – /etc/projects

      10:/mnt/test/jsp
      20:/mnt/test/jboss
      

      – /etc/projid

      jsppro:10
      jbosspro:20
      

      3. Create two project quotas by "xfs_quota" command:

      # xfs_quota -x -c 'project -s jsppro' /mnt/test
      # xfs_quota -x -c 'project -s jbosspro' /mnt/test
      # xfs_quota -x -c 'limit -p bsoft=10m bhard=20m jsppro' /mnt/test
      # xfs_quota -x -c 'limit -p bsoft=500m bhard=700m jbosspro' /mnt/test
      

      4. Check the created quotas:

      # xfs_quota -x -c 'report -a -h'
      Project quota on /mnt/test (/dev/mapper/<VG_LV-name>)
                              Blocks              
      Project ID   Used   Soft   Hard Warn/Grace   
      ---------- --------------------------------- 
      #0         336.0G      0      0  00 [------]
      jsppro        12K    10M    20M  00 [------]
      jbosspro   182.9M   500M   700M  00 [------]
      

      Then, do the same steps to reproduce.

      Memo: You can remove quota by the following "xfs_quota" command after the test was done:

      # xfs_quota -x -c 'limit -p bsoft=0 bhard=0 jsppro' /mnt/test
      # xfs_quota -x -c 'limit -p bsoft=0 bhard=0 jbosspro' /mnt/test
      # xfs_quota -x -c 'project -C jsppro' /mnt/test
      # xfs_quota -x -c 'project -C jbosspro' /mnt/test
      
      Show
      1. Create two different file systems. For example, one for JBoss (/mnt/test/jboss) and another for the source directory of JSP (/mnt/test/jsp) 2. Deploy test.war which contains example.jsp: <% out.println( "example.jsp" ); %> 3. Access the example.jsp: curl -v localhost:8080/test/example.jsp 4. Create an updated JSP file under /mnt/test/jsp: <% out.println( "updated example.jsp" ); %> 5. move the updated.jsp as example.jsp under test.war: $ mv /mnt/test/jsp/updated.jsp /mnt/test/jboss/standalone/deployments/test.war/example.jsp 6. Access the updated example.jsp: curl -v localhost:8080/test/example.jsp You will not see the updated JSP content but still see the old JSP content. ------------------- You can reproduce the same issue by creating two directories having different project quota settings in the same one filesystem. 1. mount the filesystem with enabling project quota ("prjquota" option): # mount /dev/mapper/<VG_LV-name> /mnt/test -o prjquota 2. Create "/etc/projects" and "/etc/projid" like the following: – /etc/projects 10:/mnt/test/jsp 20:/mnt/test/jboss – /etc/projid jsppro:10 jbosspro:20 3. Create two project quotas by "xfs_quota" command: # xfs_quota -x -c 'project -s jsppro' /mnt/test # xfs_quota -x -c 'project -s jbosspro' /mnt/test # xfs_quota -x -c 'limit -p bsoft=10m bhard=20m jsppro' /mnt/test # xfs_quota -x -c 'limit -p bsoft=500m bhard=700m jbosspro' /mnt/test 4. Check the created quotas: # xfs_quota -x -c 'report -a -h' Project quota on /mnt/test (/dev/mapper/<VG_LV-name>) Blocks Project ID Used Soft Hard Warn/Grace ---------- --------------------------------- #0 336.0G 0 0 00 [------] jsppro 12K 10M 20M 00 [------] jbosspro 182.9M 500M 700M 00 [------] Then, do the same steps to reproduce. Memo: You can remove quota by the following "xfs_quota" command after the test was done: # xfs_quota -x -c 'limit -p bsoft=0 bhard=0 jsppro' /mnt/test # xfs_quota -x -c 'limit -p bsoft=0 bhard=0 jbosspro' /mnt/test # xfs_quota -x -c 'project -C jsppro' /mnt/test # xfs_quota -x -c 'project -C jbosspro' /mnt/test
    • Hide

      Use "touch" command to update the file after "mv" the file between the different filesystems or different quota directories

      Show
      Use "touch" command to update the file after "mv" the file between the different filesystems or different quota directories

      XNIO's WatchServiceFileSystemWatcher has a possibility to prune all file change events and miss to invoke FileChangeCallback to notify the change event. Hence, Undertow has a possibility not to detect the file change and updating JSP does not trigger recompilation.

      When an existing file is updated by using "mv" command from the different filesystem or the different directories having different quota settings,
      three events StandardWatchEventKinds.ENTRY_DELETE (REMOVED in XNIO), StandardWatchEventKinds.ENTRY_CREATE (ADDED in XNIO) and StandardWatchEventKinds.ENTRY_MODIFY (MODIFIED in XNIO) happen for the updated file.

      mv command tries to invoke "renameat2" system call but it's not possible due to EXDEV (Invalid cross-device link) between the different filesystems or different quotas. So, it internally invokes "unlink" to remove the existing file, invoke "open" a file with the same name with O_CREAT, then invoke "write" and "utimensat". So, this is why all three events are notified for the same file at the same time.

      XNIO's WatchServiceFileSystemWatcher prunes the duplicated file change events in https://github.com/xnio/xnio/blob/3.6.6.Final/nio-impl/src/main/java/org/xnio/nio/WatchServiceFileSystemWatcher.java#L122-L142

      And, if REMOVED, ADDED and MODIFIED are notified for the same file at the same time, all three file change events are removed from the results by the pruning processing.

              rhn-support-mmiura Masafumi Miura
              rhn-support-mmiura Masafumi Miura
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

                Created:
                Updated:
                Resolved: