microstream icon indicating copy to clipboard operation
microstream copied to clipboard

Cannot store any entry in map

Open ghilainm opened this issue 2 years ago • 3 comments

Environment Details

  • MicroStream Version:
  • JDK version: JDK 17
  • OS: Linux
  • Used frameworks: None

Describe the bug

Cannot store any entry in map. When loading it after restart it is always empty. Following the same pattern with a list does not show the problem.

Here is code snippet showcasing issue.

    @Test
    void test() {

        EmbeddedStorageManager storageManager = EmbeddedStorage.start(Paths.get("/home/my-data"));
        PerfData root = getRoot(storageManager);
        if (root.getUsers() == null) {
            root.setUsers(new LinkedList<>());
        }
        if (root.getUserData() == null) {
            root.setUserData(new HashMap<>());
        }
        System.out.println("User ? "+root.getUsers().size());
        PerfData.UserData xxx = new PerfData.UserData("xxx");
        root.getUserData().put("abc", xxx);
        storageManager.store(root.getUserData());
        root.getUsers().add(xxx);
        storageManager.store(root.getUsers());
        storageManager.storeRoot();
        storageManager.shutdown();
    }

    private PerfData getRoot(EmbeddedStorageManager storageManager) {
        if (storageManager.root() == null) {
            PerfData perfData = new PerfData();
            storageManager.setRoot(perfData);
            storageManager.storeRoot();
            storageManager.store(perfData.getUserData());
            log.info("Generating new root for data.");
            return perfData;
        } else {
            PerfData root = (PerfData) storageManager.root();
            log.info("Reusing data. Already {} users generated", root.getUserData().keySet().size());
            return root;
        }
    }

@Getter
@Setter
class PerfData {

    Map<String, UserData> userData = new HashMap<>();
    List<UserData> users = new LinkedList<>();
    String name = UUID.randomUUID().toString();

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    record UserId(String userId) {
    }
    record UserData(String name) {
    }
}

ghilainm avatar Dec 21 '22 17:12 ghilainm

After some investigation, it has the same problem when storing a list build using Collections.synchronizedList().

The problem is that no error is raised. There should be at least some warnings or stuff that the map/list cannot be saved/loaded.

ghilainm avatar Dec 21 '22 17:12 ghilainm

Hi @ghilainm

I did run your code and do not have any issues. When I run it the second time, I get this log message

Reusing data. Already 1 users generated

So can you assemble a project that shows the error so that we can run it and test it further.

Thx Rudy

rdebusscher avatar Dec 29 '22 08:12 rdebusscher

Some additional comments about your code

            storageManager.storeRoot();
            storageManager.store(perfData.getUserData());

The call to .store() here is not needed as the .storeRoot() method stored everything already on disk. The rule is store what is changed but nothing is changed between the call to .storeRoot() and .store().

Also this call to .storeRoot() is not needed.

        storageManager.storeRoot();
        storageManager.shutdown();

Since you did not change the Root instance itself. You should only call .storeRoot() whenever you perform .setRoot().

rdebusscher avatar Dec 29 '22 08:12 rdebusscher