Menu

Date Modified timestamp of Access file does not update immediately on database update

Help
2020-01-14
2020-01-16
  • Michael Angstadt

    When Jackcess updates a row in the database, the file system does not
    update the Access file's "date modified" timestamp immediately for me. It
    takes around 10 seconds for the timestamp to update.

    This only happens to me when the Access file is hosted on a SMB network
    share (as opposed to the local hard drive). The server hosting the network
    share is a Linux-based NAS. The client computer is running Windows. The
    Access file used to be hosted on a Windows-based server, and I just started
    to experience this issue when we migrated to the Linux server.

    This only seems to be an issue with Jackcess. If I update a plain text file
    on the network share, the date modified updates immediately.

    Please see the below sample code and output (I hope the formatting doesn't
    get messed up, as SF is only letting me create this forum post via email).

    Thanks for the wonderful library, it's very easy to use!

    Code

    public class Test {
      static final File db = new
    File("\\\\server_name\\share_name\\database.accdb");
      static final int recordId = 21176;
    
      public static void main(String args[]) throws Exception {
        startPolling();
        Thread.sleep(5000);
    
        System.out.print("Updating row...");
        updateRow();
        System.out.println("done.");
      }
    
      static void startPolling() {
        Thread t = new Thread(new Runnable() {
          @Override
          public void run() {
            try {
              while (true) {
                FileTime lastModified = Files.getLastModifiedTime(db.toPath());
                System.out.println(lastModified);
                Thread.sleep(2000);
              }
            } catch (Exception e) {
              e.printStackTrace();
            }
          }
        });
        t.start();
      }
    
      static void updateRow() throws Exception {
        try (Database database = DatabaseBuilder.open(db)) {
          Table table = database.getTable("TableName");
          IndexCursor cursor =
    CursorBuilder.createCursor(table.getIndex("PrimaryKey"));
          Iterator<Row> it = cursor.newEntryIterable(recordId).iterator();
          Row row = it.next();
          row.put("ColumnName", row.get("ColumnName") + " edited");
          table.updateRow(row);
        }
      }
    }
    

    Output

    2020-01-14T19:27:56.840064Z
    2020-01-14T19:27:56.840064Z
    2020-01-14T19:27:56.840064Z
    Updating row...done.
    2020-01-14T19:27:56.840064Z
    2020-01-14T19:27:56.840064Z
    2020-01-14T19:27:56.840064Z
    2020-01-14T19:27:56.840064Z
    2020-01-14T19:27:56.840064Z
    2020-01-14T19:54:27.691668Z
    2020-01-14T19:54:27.691668Z
    2020-01-14T19:54:39.268271Z
    
     

    Last edit: Michael Angstadt 2020-01-14
    • James Ahlborn

      James Ahlborn - 2020-01-14

      You said if you update a plain text file, this doesn't happen. are you using java to update this plain text file? ultimately, jackcess is using standard java file io. so i doubt that jackcess has anything to do with this (as opposed to a general java issue).

      also, can you view the modification stamp from the filesystem side? might help determine where the delay is happening.

       

      Last edit: James Ahlborn 2020-01-14
      • Tommy Sools

        Tommy Sools - 2020-01-14

        Hi Michael,

        If this were to be PHP, it would be required to clear the file 'stat cache'
        (at least for Linux and maybe for Windows), see:
        https://www.php.net/manual/en/function.clearstatcache.php and for example
        https://www.php.net/manual/en/function.filemtime.php

        Perhaps someone else knows how to force clearing such file cache in Java, in
        order to resolve your situation?

        Best regards,

        Tommy Sools

        Van: James Ahlborn [mailto:jahlborn@users.sourceforge.net]
        Verzonden: dinsdag 14 januari 2020 22:31
        Aan: [jackcess:discussion]
        Onderwerp: [jackcess:discussion] Re: Date Modified timestamp of Access file
        does not update immediately on database update

        You said if you update a plain text file, this doesn't happen. are you using
        java to update this plain text file? ultimately, jackcess is using standard
        java file io. so i doubt that jackcess has anything to do with this (as
        opposed to a general java issue).


        Date Modified timestamp of Access file does not update immediately on
        https://sourceforge.net/p/jackcess/discussion/456474/thread/694ab013bc/?lim it=25#d8fc/79ca
        database update


        Sent from sourceforge.net because you indicated interest in
        https://sourceforge.net/p/jackcess/discussion/456474/

        To unsubscribe from further messages, please visit
        https://sourceforge.net/auth/subscriptions/

         
      • Michael Angstadt

        Yes, I used Java to update the plain text file (see code & output below). I wonder if Jackcess has any kind of caching system that could cause this? Are there any background threads that run after the database object is closed?

        I checked the database file's timestamp at the command line right after my sample code updates the database file, and it reflects what the Java code is reporting--it takes ~10 seconds to update just like the Java code. So that suggests the problem is at the operating system level.

        Updating a plain text file:

        public class Test {
          public static void main(String args[]) throws Exception {
            testTextFile();
          }
        
          static void testTextFile() throws Exception {
            Path file = Paths.get("\\\\server_name\\share_name", "test.txt");
        
            startPolling(file);
            Thread.sleep(5000);
        
            System.out.print("Updating text file...");
            updateFile(file);
            System.out.println("done.");
          }
        
          static void startPolling(final Path file) {
            new Thread(new Runnable() {
              @Override
              public void run() {
                try {
                  while (true) {
                    FileTime lastModified = Files.getLastModifiedTime(file);
                    System.out.println(lastModified);
                    Thread.sleep(2000);
                  }
                } catch (Exception e) {
                  e.printStackTrace();
                }
              }
            }).start();
          }
        
          static void updateFile(Path file) throws Exception {
            Files.write(file, "content".getBytes());
          }
        }
        

        Output:

        2020-01-14T18:24:37.437757Z
        2020-01-14T18:24:37.437757Z
        2020-01-14T18:24:37.437757Z
        Updating text file...done.
        2020-01-15T16:28:20.591628Z
        2020-01-15T16:28:20.591628Z
        2020-01-15T16:28:20.591628Z
        
         
        • James Ahlborn

          James Ahlborn - 2020-01-15

          so jackcess definitely doesn't use any multi-threading, so no delayed updates. however, jackcess uses a RandomAccessFile under the hood and does partial updates of the underlying file (it literally re-writes a chunk of the underlying file). this is a much different path than your test case which is truncating and re-writing your entire text file (which might interact w/ the operating system file cache in a much different manner).

          a more accurate test would be to create a several megabyte file and use RandomAccessFile to overwrite 1k of bytes somewhere in the middle of the file.

           
          • Michael Angstadt

            RandomAccessFile appears to be the cause. I did what you suggested and created a 1MB file on the network share, and then used the RandomAccessFile class to edit a 1KB chunk in the middle of the file. It took several seconds for the date modified timestamp to update.

            It must have something to do with the way the Linux server handles such things because we didn't have this problem when we used a Windows server.

             
            • James Ahlborn

              James Ahlborn - 2020-01-16

              You could try calling "raf.getFD().sync()" or "raf.getChannel().force(true)" and see if that changes anything. Although I highly doubt it will because I've had some past experience with Java and networked filesystems and had this problem as well

               
              • Michael Angstadt

                I tried calling those two methods right before calling "raf.close()" and neither helped. Also tried changing the SMB version of the Linux server from 2.1 to 3.0, and enabling "Asynchronous I/O" on the server. No luck.

                 

Log in to post a comment.