yapstudios / YapDatabase

YapDB is a collection/key/value store with a plugin architecture. It's built atop sqlite, for Swift & objective-c developers.
Other
3.35k stars 365 forks source link

Deregistering databases is unreliable when they are created in certain paths #415

Open Canis-UK opened 7 years ago

Canis-UK commented 7 years ago

When opening or closing a database, the supplied path is passed through stringByStandardizingPath, to ensure that different paths to the same physical file (e.g. because of symlinks) all resolve to one string, which is used to identify whether the database is open.

Unfortunately, the behaviour of stringByStandardizingPath is a little cranky, and this can cause problems. In particular, it can return different values depending on whether the specified path exists:

Removing an initial component of “/private/var/automount”, “/var/automount”, or “/private” from the path, if the result still indicates an existing file or directory (checked by consulting the file system). — source

This means that there are circumstances where you try to create a new database, pass the new path into [[YapDatabase alloc] initWithPath: ...] and the path is unchanged (because this is a new database and the path does not yet exist). But when deallocing the database, the path does now exist, and so stringByStandardizingPath returns a different result. This causes the lookup in [YapDatabaseManager deregisterDatabaseForPath:] to fail, the database doesn't get unregistered, and subsequent attempts to reopen it fail.

(I'm encountering this because iOS tends to return "/private/..." paths when you retrieve the tmp folder.)

I'm not sure of the best strategy for solving this issue, but several possibilities come to mind, of varying degrees of hackiness:

lilhinx commented 4 years ago

I ran into the same issue. The only way I was able to move forward was to remove the calls to stringByStandardizingPath. My usage wasn't benefitting from it anyhow. It might be worth clarify the intent of the original feature. Tilde expansion I understand as a user feature, but I'm not sure I understand the desire for the API user to declare a path using symlinks. I recommend a two more ideas for changing this:

Raikerian commented 4 years ago

The other solution would be to standardize your path before passing it to YapDatabase initializer, this works for me fine so far.