Recent Changes - Search:

edit SideBar

VertxDirectories

.vertx directories being created

Edward wrote:

Running any of the REST or Websocket accessor demos or tests seems to result in vertx leaving turds in the file system. It leaves directories called .vertx that have empty directories named file-cache...

Apparently this is because we aren't calling close() on the instance of vertx defined in VertxHelperBase.java:

    /** Global (unclustered) instance of Vert.x core. */
    protected static Vertx _vertx = Vertx.vertx();

Summary

In theory, Vert.x-3.2.0-SNAPSHOT should delete the subdirectories in the .vertx/ directory via shutdown hooks. However, this did not work for me under Mac OS X. To get this to work, I had to modify the vert.x FileResolver deleteCacheDir() method so that it calls deleteRecursiveBlocking() instead of deleteRecursive().

I'll submit a bug report for this issue.

We could create a shutdown that would just remove the entire .vertx/ directory. The shutdown hooks may be run in any order, so if our shutdown hook was run first, then the Vert.x shutdown hooks would detect that the .vertx directory was missing.

One issue is that the .vertx directory is created in the current working directory, which could change by the time the shutdown hooks are invoked. Unfortunately, there is no way to get the cache directory from the FileResolver class. In addition, each FileResolver instance could have a separate .vertx/ directory if the current working directory changes, or the value of the vertx.cwd property changes.

Thus, to delete the .vertx/ directory, we would need to modify the vert.x FileResolver class.

A better solution would be to set the vertx.cacheDirBase to ~/.vertx. Note that we can't use /tmp/.vertx because multiple users would not be able to write to that directory.

Reproducing The Bug

This was submitted as https://github.com/vert-x3/issues/issues/72 and fixed in https://github.com/eclipse/vert.x/commit/a9db9646106d24e5f04a72aa0f4a17b4ba13c2f6

Set up Vert.x and add vertx to your path

cd ~/src
wget https://bintray.com/artifact/download/vertx/downloads/vert.x-3.1.0-full.tar.gz
tar -zxf vert.x-3.1.0-full.tar.gz
export PATH=`pwd`/vert.x-3.1.0/bin:${PATH}

Set up the Vert.x examples, see https://github.com/vert-x3/vertx-examples/tree/master/core-examples

git clone https://github.com/vert-x3/vertx-examples.git
cd vertx-examples
mvn3 clean-compile

Verify that the example works:

In the window where the above commands were run:

cd core-examples/src/main/java/io/vertx/example/core/net/echo
vertx run Client.java

In another window:

cd ~/src
export PATH=`pwd`/vert.x-3.1.0/bin:${PATH}
cd vertx-examples/core-examples/src/main/java/io/vertx/example/core/net/echo
vertx run Server.java

In the client window, we see:

bash-3.2$ vertx run Client.java
warning: Implicitly compiled files were not subject to annotation processing.
  Use -proc:none to disable annotation processing or -implicit to specify a policy for implicit \
compilation.
Succeeded in deploying verticle
Net client sending: hello 0

Net client sending: hello 1

Net client sending: hello 2

Net client sending: hello 3

Net client sending: hello 4

Net client sending: hello 5

Net client sending: hello 6

Net client sending: hello 7

Net client sending: hello 8

Net client sending: hello 9

Net client receiving: hello 0
hello 1
hello 2
hello 3
hello 4
hello 5
hello 6
hello 7
hello 8
hello 9

  C-c C-cbash-3.2$ ls -l .vertx
total 0
drwxr-xr-x  2 cxh  staff  68 Nov  5 14:05 file-cache-fd21b7d3-0353-4712-b2d6-7b11f15bb427
bash-3.2$

In the above, the Client connected to the Server and ran until I hit Control-C. Note that the .vertx directory contains one file-cache directory.

The Server window looks like:

bash-3.2$ vertx run Server.java
warning: Implicitly compiled files were not subject to annotation processing.
  Use -proc:none to disable annotation processing or -implicit to specify a policy for implicit compilation.
Echo server is now listening
Succeeded in deploying verticle
  C-c C-cbash-3.2$ ls -l .vertx
bash-3.2$

After I stopped the Client, I stopped the Server with Control-C. The .vertx/ directory is empty.

The above indicates that the shutdown hooks ran successfully and removed the subdirectories in .vertx/.

To replicate the bug, we first compile the files:

cd src/vertx-examples/core-examples/src/main/java/
javac -classpath '.:/Users/cxh/src/vert.x-3.1.0/lib/*' io/vertx/example/core/net/echo/*.java

In the above single quotes are needed to protect the * from expansion. The end results is all the jars in that directory are included in the classpath.

Next, we remove the .vertx directory if any:

rm -rf .vertx

Then, we start the server:

java -classpath '.:/Users/cxh/src/vert.x-3.1.0/lib/*' io.vertx.example.core.net.echo.Server

In our other window, we start the client:

bash-3.2$ java -classpath '.:/Users/cxh/src/vert.x-3.1.0/lib/*' io.vertx.example.core.net.echo.C\
lient
Net client sending: hello 0

Net client sending: hello 1

Net client sending: hello 2

Net client sending: hello 3

Net client sending: hello 4

Net client sending: hello 5

Net client sending: hello 6

Net client sending: hello 7

Net client sending: hello 8

Net client sending: hello 9

Net client receiving: hello 0
hello 1
hello 2
hello 3
hello 4
hello 5
hello 6
hello 7

In the client window, we stop the Client, put it in the background and we can see two subdirectories:

  C-c C-z
[1]+  Stopped                 java -classpath '.:/Users/cxh/src/vert.x-3.1.0/lib/*' io.vertx.example.core.net.echo.Client
bash-3.2$ bg
[1]+ java -classpath '.:/Users/cxh/src/vert.x-3.1.0/lib/*' io.vertx.example.core.net.echo.Client &
bash-3.2$ ls -l .vertx
total 0
drwxr-xr-x  2 cxh  staff  68 Nov  5 14:13 file-cache-8b08f94d-85a8-4fed-bf0e-fad3a2b0f3b0
drwxr-xr-x  2 cxh  staff  68 Nov  5 14:14 file-cache-cfbaaf05-e1b1-46de-8f55-05b10b88b56a

In the client window, we kill the background process and neither subdirectory is removed:

bash-3.2$ kill %1
bash-3.2$ ls -l .vertx
total 0
drwxr-xr-x  2 cxh  staff  68 Nov  5 14:13 file-cache-8b08f94d-85a8-4fed-bf0e-fad3a2b0f3b0
drwxr-xr-x  2 cxh  staff  68 Nov  5 14:14 file-cache-cfbaaf05-e1b1-46de-8f55-05b10b88b56a
[1]+  Exit 143                java -classpath '.:/Users/cxh/src/vert.x-3.1.0/lib/*' io.vertx.example.core.net.echo.Client
bash-3.2$ ls -l .vertx
total 0
drwxr-xr-x  2 cxh  staff  68 Nov  5 14:13 file-cache-8b08f94d-85a8-4fed-bf0e-fad3a2b0f3b0
drwxr-xr-x  2 cxh  staff  68 Nov  5 14:14 file-cache-cfbaaf05-e1b1-46de-8f55-05b10b88b56a
bash-3.2$

In the server window, we stop the process and neither subdirectory is removed:

bash-3.2$ java -classpath '.:/Users/cxh/src/vert.x-3.1.0/lib/*' io.vertx.example.core.net.echo.Server
Echo server is now listening
  C-c C-cbash-3.2$ ls -l .vertx
total 0
drwxr-xr-x  2 cxh  staff  68 Nov  5 14:13 file-cache-8b08f94d-85a8-4fed-bf0e-fad3a2b0f3b0
drwxr-xr-x  2 cxh  staff  68 Nov  5 14:14 file-cache-cfbaaf05-e1b1-46de-8f55-05b10b88b56a
bash-3.2$

Conclusion: When we run the echo Server/Client example with the vertx command, the subdirectories are removed.

However, when we run the echo Server/Client example Java classes as plain Java code the subdirectories are not removed.

Setting Properties

https://groups.google.com/forum/?fromgroups#!topic/vertx/7cBbKrjYfeI says:

Hi,
This directory is used to serve files contained in jar files (for example web assets packaged in a fat jar). If you are not using this feature, you can disable the creation of this directory by setting the vertx.disableFileCPResolving system property to true. You can also change the location using the vertx.cacheDirBase system property.
On 19 octobre 2015 at 23:10:58, Hoobajoob (chefho...@gmail.com) wrote:
vertx appears to create a .vertx folder when it runs, and within that folder, subfolders named like "file-cache-<guid>", and these folders, in turn, are empty.
What are these folders for? Can/should I prevent them from being created?

Vert.x Uses Shutdown Hooks already to remove the subdirectories

In looking at the Vert.x code in 3.2.0-SNAPSHOT,

FileResolver has this code:


  private static final boolean ENABLE_CP_RESOLVING = !Boolean.getBoolean(DISABLE_CP_RESOLVING_PROP_NAME);

  public FileResolver(Vertx vertx) {
    this.vertx = vertx;
    String cwdOverride = System.getProperty("vertx.cwd");
    if (cwdOverride != null) {
      cwd = new File(cwdOverride).getAbsoluteFile();
    } else {
      cwd = null;
    }
    if (ENABLE_CP_RESOLVING) {
      setupCacheDir();
    }
  }

  private void setupCacheDir() {
    String cacheDirName = CACHE_DIR_BASE + "/file-cache-" + UUID.randomUUID().toString();
    cacheDir = new File(cacheDirName);
    if (!cacheDir.mkdirs()) {
      throw new IllegalStateException("Failed to create cache dir");
    }
    // Add shutdown hook to delete on exit
    shutdownHook = new Thread(() -> deleteCacheDir(ar -> {}));
    Runtime.getRuntime().addShutdownHook(shutdownHook);
  }

So, in the default, creating a FileResolver calls setupCacheDir(), which sets up a shutdownhook.

However, when we run PTII/ptolemy/actor/lib/jjs/modules/eventbus/demo/VertxChat/VertxChat.xml, with the latest vertx-core from github, then the directories are not reliably deleted.

.vertx Directory is not deleted by FileResolver.

Vert.x FileResolver.java does not delete the .vertx directory.


  private void setupCacheDir() {
    String cacheDirName = CACHE_DIR_BASE + "/file-cache-" + UUID.randomUUID().toString();
    cacheDir = new File(cacheDirName);
...
  }

  private void deleteCacheDir(Handler<AsyncResult<Void>> handler) {
    if (cacheDir != null && cacheDir.exists()) {
      vertx.fileSystem().deleteRecursive(cacheDir.getAbsolutePath(), true, handler);
    } else {
      handler.handle(Future.succeededFuture());
    }
  }

So, the above will delete the .vertx/file-cache-* directories, but not the .vertx directories themselves.

Two solutions

  1. Create our own shutdown hook that calls close() and then deletes the .vertx directory. Note that there is no guarantee about the order the shutdown hooks will be called, so there is no way to know whether the shutdown hooks created in FileResolver will be called before or after our shutdown hook. Thus, if our shutdown hook calls close(), we need to read the code to see if the deletion of the subdirectories will occur before close() returns.
  2. Set the property to not use this directory or set the property to be in the user's top level directory.

Using deleteRecursiveBlocking() causes the subdirectories to be removed.

If I modify Vert.x FileResolver.java so that deleteCache() calls deleteRecursiveBlocking() instead of deleteRecursive(), then the subdirectories are removed by the Vertx shutdown hooks.

 private void deleteCacheDir(Handler<AsyncResult<Void>> handler) {
      System.out.println("FileResolver.deleteCacheDir()");
    if (cacheDir != null && cacheDir.exists()) {
      vertx.fileSystem().deleteRecursiveBlocking(cacheDir.getAbsolutePath(), true/* handler*/);
    } else {
      handler.handle(Future.succeededFuture());
    }
  }

Perhaps the VertxHelperBase should just remove the .vertx directory?

.vertx directories are not removed by close() in a non-clustered environment.

11/3/2015

I tried using a clustered environment, but that did not do it. My work is below. I updated VertxHelperBase so that a shutdown handler is created:

    static {
        try {
            _vertx = Vertx.vertx();
            _registerShutdownHook(_vertx);
        } catch (Throwable throwable) {
            System.err.println("Static initialization failed.");
            throwable.printStackTrace();
        }
    }
...
    private static void _registerShutdownHook(Vertx vertx) {
        // Create a Weak Reference for the Vertx.  currently,  
        // there is only one because _vertx is static.                                      
        final WeakReference<Vertx> vertxToShutdown = new WeakReference<Vertx>(vertx);
        Thread shutdownThread =  new Thread() {
                @Override
                public void run() {
                    System.out.println("Calling close on " + vertxToShutdown);                              
                    vertxToShutdown.get().close();
                }
            };
        try {
            Runtime.getRuntime().addShutdownHook(shutdownThread);
        } catch (java.security.AccessControlException ex) {
            // This exception gets triggered by                                                                
            // http://ptolemy.eecs.berkeley.edu/ptolemyII/ptII10.0/ptII10.0.devel/ptolemy/vergil/Vergil.htm    
            System.out.println("Warning: failed to add a shutdown hook for VertxHelperBase."
                    + "(Running a model in an applet always causes this)");
        }
    }

When I run $PTII/ptolemy/actor/lib/jjs/modules/eventbus/demo/VertxChat/VertxChat.xml, I can see that the shutdown hook is executed:

bash-3.2$ $PTII/bin/vergil eventbus/demo/VertxChat/VertxChat.xml
Updating local copy of the accessors repository.
In "/Users/cxh/ptII/org/terraswarm/accessor/accessors", about to execute:
    svn update --non-interactive --trust-server-cert --accept postpone
Updating '.':
At revision 343.
All Done
Updated accessor repository.
WARNING: VertxSubscribe2: Model stopped before executing actions (e.g. producing outputs) scheduled for execution at times [4.231]
5620 ms. Memory: 363520K Free: 195583K (54%)
Calling close on io.vertx.core.impl.VertxImpl@1685b366
bash-3.2$

However, the .vertx directory is not removed.

Below is an analysis of the code.

VertxImpl.close() at https://github.com/eclipse/vert.x/blob/master/src/main/java/io/vertx/core/impl/VertxImpl.java looks like:

  public void close() {
    close(null);
  }
...
  public synchronized void close(Handler<AsyncResult<Void>> completionHandler) {
    if (closed || eventBus == null) {
      // Just call the handler directly since pools shutdown
      if (completionHandler != null) {
        completionHandler.handle(Future.succeededFuture());
      }
      return;
    }
    closed = true;
    deploymentManager.undeployAll(ar -> {
      if (haManager() != null) {
        haManager().stop();
      }
      eventBus.close(ar2 -> {
        closeClusterManager(ar3 -> {
          // Copy set to prevent ConcurrentModificationException
          Set<HttpServer> httpServers = new HashSet<>(sharedHttpServers.values());
          Set<NetServer> netServers = new HashSet<>(sharedNetServers.values());
          sharedHttpServers.clear();
          sharedNetServers.clear();
          int serverCount = httpServers.size() + netServers.size();
 ...
          if (serverCount == 0) {
            deleteCacheDirAndShutdown(completionHandler);
          }
        });
      });
    });
  }

Thus, if eventBus is null, then deleteCacheDirAndShutdown() is not invoked.

eventBus is set by VertxImpl.createAndStartEventBus():

 private void createAndStartEventBus(VertxOptions options, Handler<AsyncResult<Vertx>> resultHandler) {
    eventBus = eventBusFactory.createEventBus(this, options, clusterManager, haManager);
...

VertxImpl.createAndStartEventBus() is invoked VertxImpl(VertxOptions options, Handler<AsyncResult<Vertx>> resultHandler) for both clustered and unclustered options:

    if (options.isClustered()) {
      this.clusterManager = getClusterManager(options);
      this.clusterManager.setVertx(this);
      this.clusterManager.join(ar -> {
        if (ar.failed()) {
          log.error("Failed to join cluster", ar.cause());
        } else {
          // Provide a memory barrier as we are setting from a different thread
          synchronized (VertxImpl.this) {
            haManager = new HAManager(this, deploymentManager, clusterManager, options.getQuorumSize(),
                                      options.getHAGroup(), haEnabled);
            createAndStartEventBus(options, resultHandler);
          }
        }
      });
    } else {
      this.clusterManager = null;
      createAndStartEventBus(options, resultHandler);
    }

So, eventBus is non-null in both cases.


Edit - History - Print - Recent Changes - Search
Page last modified on November 09, 2015, at 03:49 PM