YapDatabase icon indicating copy to clipboard operation
YapDatabase copied to clipboard

Deregistering databases is unreliable when they are created in certain paths

Open Canis-UK opened this issue 8 years ago • 2 comments

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:

  • If deregisterDatabaseForPath fails to find the path in the list of registrations, try checking the passed-in path instead of the standardized one — solves the specific use-case I have, but might fail in situations where the path is non-canonical in other ways (such as having extraneous "/./" components)
  • In YapDatabase's initWithPath, before calling stringByStandardizingPath, check to see if the path exists. If it doesn't, create a blank file, standardize, then remove. This is goofy and inefficient but should produce canonically correct paths every time
  • Find some other way of making canonical paths, that produces consistent results...?

Canis-UK avatar Jul 14 '17 11:07 Canis-UK

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:

  • changing stringByStandardizingPath to stringByExpandingTildeInPath
  • suppress this feature with options somehow.

lilhinx avatar Feb 19 '20 01:02 lilhinx

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

Raikerian avatar Mar 12 '20 08:03 Raikerian