Commit bfeb1690 authored by Kirill Smelkov's avatar Kirill Smelkov

Allow internal clients to specify intended access mode - read-only or read-write

Most of our tools need only read access for working. However e.g.
FileStorage, when opened in read-write mode, automatically creates
database file and index.

This way if database is opened in read-write mode a simple typo in path,
e.g. to `zodb dump path` would lead to:

- new database at path will be created
- the dump will print nothing (empty database)
- exit status will be 0 (ok) and no error will be reported.

For this reason it is better tools declare access level they need so for
read-only access request we can catch it with an error from storage.

This, however, requires quite recent ZODB to work:


We don't want to force users to always specify read-only in URLs or
zconf files because:

- this is error prone
- URL or zconf can be though as of file
- when a program opens a file the program, not file, declares which type
  of access it wants.

That's why access mode declaration has to be internal.
parent 82b06413
......@@ -19,7 +19,7 @@ setup(
keywords = 'zodb utility tool',
packages = find_packages(),
install_requires = ['ZODB', 'zodburi'],
install_requires = ['ZODB', 'zodburi', 'six'],
entry_points= {'console_scripts': ['zodb = zodbtools.zodb:main']},
......@@ -18,6 +18,7 @@
import hashlib
import zodburi
from six.moves.urllib_parse import urlsplit, urlunsplit
def ashex(s):
return s.encode('hex')
......@@ -76,11 +77,25 @@ def parse_tidrange(tidrange):
# storageFromURL opens a ZODB-storage specified by url
def storageFromURL(url):
# read_only specifies read or read/write mode for requested access:
# - None: use default mode specified by url
# - True/False: explicitly request read-only / read-write mode
def storageFromURL(url, read_only=None):
# no schema -> file://
if "://" not in url:
url = "file://" + url
# read_only -> url
if read_only is not None:
scheme, netloc, path, query, fragment = urlsplit(url)
# XXX this won't have effect with zconfig:// but for file:// neo://
# zeo:// etc ... it works
if scheme != "zconfig":
if len(query) > 0:
query += "&"
query += "read_only=%s" % read_only
url = urlunsplit((scheme, netloc, path, query, fragment))
stor_factory, dbkw = zodburi.resolve_uri(url)
stor = stor_factory()
......@@ -157,8 +157,8 @@ def main2(argv):
print("E: invalid tidrange: %s" % e, file=sys.stderr)
stor1 = storageFromURL(storurl1)
stor2 = storageFromURL(storurl2)
stor1 = storageFromURL(storurl1, read_only=True)
stor2 = storageFromURL(storurl2, read_only=True)
zcmp = storcmp(stor1, stor2, tidmin, tidmax, verbose)
sys.exit(1 if zcmp else 0)
......@@ -116,6 +116,6 @@ def main(argv):
print("E: invalid tidrange: %s" % e, file=sys.stderr)
stor = storageFromURL(storurl)
stor = storageFromURL(storurl, read_only=True)
zodbdump(stor, tidmin, tidmax, hashonly)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment