Blame view

lib/zodb.py 3.44 KB
Kirill Smelkov committed
1
# Wendelin.bigfile | common ZODB-related helpers
Kirill Smelkov committed
2 3 4 5 6 7 8 9
# Copyright (C) 2014-2015  Nexedi SA and Contributors.
#                          Kirill Smelkov <kirr@nexedi.com>
#
# This program is free software: you can Use, Study, Modify and Redistribute
# it under the terms of the GNU General Public License version 3, or (at your
# option) any later version, as published by the Free Software Foundation.
#
# You can also Link and Combine this program with other software covered by
Kirill Smelkov committed
10 11 12 13
# the terms of any of the Free Software licenses or any of the Open Source
# Initiative approved licenses and Convey the resulting work. Corresponding
# source of such a combination shall include the source code for all other
# software used.
Kirill Smelkov committed
14 15 16 17 18
#
# This program is distributed WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# See COPYING file for full licensing terms.
Kirill Smelkov committed
19
# See https://www.nexedi.com/licensing for rationale and options.
Kirill Smelkov committed
20 21 22

from ZODB.FileStorage import FileStorage
from ZODB import DB
Kirill Smelkov committed
23 24
from persistent import Persistent
import gc
Kirill Smelkov committed
25 26


Kirill Smelkov committed
27 28
# open db storage by uri
def dbstoropen(uri):
Kirill Smelkov committed
29 30 31 32 33 34 35 36 37 38 39 40 41
    # if we can - use zodbtools to open via zodburi
    try:
        import zodbtools.util
    except ImportError:
        return _dbstoropen(uri)

    return zodbtools.util.storageFromURL(uri)


# simplified fallback to open a storage by URI when zodbtools/zodburi are not available.
# ( they require ZODB, instead of ZODB3, and thus we cannot use
#   them together with ZODB 3.10 which we still support )
def _dbstoropen(uri):
Kirill Smelkov committed
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
    if uri.startswith('neo://'):
        # XXX hacky, only 1 master supported
        from neo.client.Storage import Storage
        name, master = uri[6:].split('@', 1)    # neo://db@master -> db, master
        stor = Storage(master_nodes=master, name=name)

    elif uri.startswith('zeo://'):
        # XXX hacky
        from ZEO.ClientStorage import ClientStorage
        host, port = uri[6:].split(':',1)       # zeo://host:port -> host, port
        port = int(port)
        stor = ClientStorage((host, port))

    else:
        stor = FileStorage(uri)

    return stor


Kirill Smelkov committed
61
# open stor/db/connection and return root obj
Kirill Smelkov committed
62 63
def dbopen(uri):
    stor = dbstoropen(uri)
Kirill Smelkov committed
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
    db   = DB(stor)
    conn = db.open()
    root = conn.root()
    return root


# close db/connection/storage identified by root obj
def dbclose(root):
    conn = root._p_jar
    db   = conn.db()
    stor = db.storage

    conn.close()
    db.close()
    stor.close()
Kirill Smelkov committed
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107


# deactivate a btree, including all internal buckets and leaf nodes
def deactivate_btree(btree):
    # first activate btree, to make sure its first bucket is loaded at all.
    #
    # we have to do this because btree could be automatically deactivated
    # before by cache (the usual way) and then in its ghost state it does not
    # contain pointer to first bucket and thus we won't be able to start
    # bucket deactivation traversal.
    btree._p_activate()

    for _ in gc.get_referents(btree):
        # for top-level btree we ignore any direct referent besides bucket
        # (there are _p_jar, cache, etc)
        if type(_) is btree._bucket_type:
            _deactivate_bucket(_)

    btree._p_deactivate()

def _deactivate_bucket(bucket):
    # TODO also support objects in keys, when we need it
    for obj in bucket.values():
        if type(obj) == type(bucket):
            _deactivate_bucket(obj)
        elif isinstance(obj, Persistent):
            obj._p_deactivate()

    bucket._p_deactivate()