Sorry - not meaning to hijack Luca's thread. I use a registry class to track what's open and my iterable uses it to close resources.
My wrapper looks like this:
public class RegistryClosingIterator implements CloseableIterable {
private Iterator<?> iterator;
public void setResult(Object resultPipe) { this.iterator = QueryResultUtil.getIterator(resultPipe); }
public Iterator<?> iterator() { return iterator; }
public void close() {
CloseableRegistry.closeAll();
}
}
where CloseableRegistry is a container of opened resources:
public class CloseableRegistry {
private static final ThreadLocal<CloseableRegistry> threadLocalCloseable = new ThreadLocal<>();
private final Map<Closeable, Closeable> map = new IdentityHashMap<>();
private CloseableRegistry() { threadLocalCloseable.set(this); }
public static void add(Closeable closeable) {
CloseableRegistry registryClosingIterator = threadLocalCloseable.get();
if (registryClosingIterator == null)
registryClosingIterator = new CloseableRegistry();
registryClosingIterator.map.put(closeable, closeable);
}
public static void remove(Closeable closeable) {
CloseableRegistry closeableRegistry = threadLocalCloseable.get();
if (closeableRegistry != null)
closeableRegistry.map.remove(closeable);
}
static void closeAll() {
CloseableRegistry closeableRegistry = threadLocalCloseable.get();
if (closeableRegistry != null) {
threadLocalCloseable.remove();
if (!closeableRegistry.map.isEmpty())
closeableRegistry.map.keySet().forEach(FileUtils::closeQuietly);
}
}
}
Finally, my Graph registers any iterable that it returns to Gremlin before returning.
CloseableRegistry.add(iterable);
It's a hack, of course, but it was the only way I could see to ensure resources are closed when the caller is finished with the traversal.
-Paul