# Concurrency bug in the Directory Layer

**URL:** <https://forums.foundationdb.org/t/concurrency-bug-in-the-directory-layer/4071>\
**Category:** Using FoundationDB\
**Tags:** bindings\
**Created:** [July 20, 2023, 3:41pm UTC](https://forums.foundationdb.org/t/concurrency-bug-in-the-directory-layer/4071 "2023-07-20T15:41:05Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Imperatorx](https://avatars.discourse-cdn.com/v4/letter/i/d2c977/32.png) [@Imperatorx](https://forums.foundationdb.org/u/Imperatorx)\
**Post date:** [July 20, 2023, 3:41pm UTC](https://forums.foundationdb.org/t/concurrency-bug-in-the-directory-layer/4071/1 "2023-07-20T15:41:05Z")

</div>

In the java binding, there is a local concurrency bug:

Inside a single transaction, if multiple threads are createOrOpening directories in a base directory with a common prefix, the directory might return as created, but in reality, it won’t be created. Even inside the same transation, listing it will cause an error.

7.1.x, Linux and Windows tested. Reproducer:

(“a”, “b”) is the base directory.

(“a”, “b”, “prefix”, random-uuid) are the directories being created.

```auto
 public static void main(String[] args) {

        int subDirectoryCount = 100;

        var executor = Executors.newFixedThreadPool(8);

        var db = FDB.selectAPIVersion(710)
                .open(null, Runnable::run);

        List<String> basePath = List.of("a", "b");

        // Delete root dir of it existed
        db.run(tr -> {
            DirectoryLayer.getDefault()
                    .removeIfExists(tr, basePath)
                    .join();
            return null;
        });

        // Create root dir
        var baseDirectory = db.run(tr -> {
            return DirectoryLayer.getDefault()
                    .createOrOpen(tr, basePath)
                    .join();
        });

        // Create many subdirectories in PARALLEL
        try (var tr = db.createTransaction(Runnable::run)) {
            CompletableFuture[] dirFutures = IntStream.range(0, subDirectoryCount)
                    .mapToObj(x -> CompletableFuture.supplyAsync(() -> {
                        try {

                            String subDirName = UUID.randomUUID().toString();

                            baseDirectory.createOrOpen(tr, List.of("prefix", subDirName))
                                    .join();

                            if (!baseDirectory.exists(tr, List.of("prefix", subDirName)).join()) {
                                throw new IllegalStateException("Subdir does not exist, although it was just created");
                            }

                            return null;

                        } catch (Exception e) {
                            throw new RuntimeException(e);
                        }
                    }, executor))
                    .toArray(CompletableFuture[]::new);

            CompletableFuture.allOf(dirFutures)
                    .join();

            tr.commit().join();
        }

        executor.shutdownNow();
        db.close();
        System.out.println("No bug detected");
    }

```

---

<div class="post-metadata">

**Author:** ![ajbeamon](https://sea1.discourse-cdn.com/foundationdb/user_avatar/forums.foundationdb.org/ajbeamon/32/13_2.png) [@ajbeamon](https://forums.foundationdb.org/u/ajbeamon)\
**Post date:** [August 6, 2023, 2:21am UTC](https://forums.foundationdb.org/t/concurrency-bug-in-the-directory-layer/4071/2 "2023-08-06T02:21:22Z")

</div>

Thanks for the report! This is possibly a reproduction of this bug:

> <https://github.com/apple/foundationdb/issues/895>
>
> The Java implementation of DirectoryLayer does not seem to work when used with a…n FDBTransaction, but does when used with an FDBDatabase.
> 
> I'm seeing issues where the DirectoryLayer allocates a prefix and returns it to me. I commit the transaction successfully, but future calls to the DirectoryLayer from new transactions do not find the allocated directory.
> 
> If I use a FDBDatabase when invoking DirectoryLayer.createOrOpen(...) then all works fine.
> 
> Since FDBTransaction implements TransactionContext I would have expected it to work with DirectoryLayer. Is this a correct assumption? I know this issue is not the most helpful, but I'm not quite sure where to start on getting useful information.

Unfortunately at this point, I don’t think there has been any attempt to make these directory operations within a single transaction thread safe.
