This file is indexed.

/usr/share/pyshared/ZEO/tests/invalidation-age.txt is in python-zodb 1:3.9.7-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
Invalidation age
================

When a ZEO client with a non-empty cache connects to the server, it
needs to verify whether the data in its cache is current.  It does
this in one of 2 ways:

quick verification
   It gets a list of invalidations from the server since the last
   transaction the client has seen and applies those to it's disk and
   in-memory caches.  This is only possible if there haven't been too
   many transactions since the client was last connected.

full verification
   If quick verification isn't possible, the client iterates through
   it's disk cache asking the server to verify whether each current
   entry is valid.

Unfortunately, for large caches, full verification is soooooo not
quick that it is impractical.  Quick verificatioin is highly
desireable.

To support quick verification, the server keeps a list of recent
invalidations. The size of this list is controlled by the
invalidation_queue_size parameter.  If there is a lot of database
activity, the size might need to be quite large to support having
clients be disconnected for more than a few minutes.  A very large
invalidation queue size can use a lot of memory.

To suppliment the invalidation queue, you can also specify an
invalidation_age parameter.  When a client connects and presents the
last transaction id it has seen, we first check to see if the
invalidation queue has that transaction id. It it does, then we send
all transactions since that id.  Otherwise, we check to see if the
difference between storage's last transaction id and the given id is
less than or equal to the invalidation age.  If it is, then we iterate
over the storage, starting with the given id, to get the invalidations
since the given id.

NOTE: This assumes that iterating from a point near the "end" of a
database is inexpensive. Don't use this option for a storage for which
that is not the case.

Here's an example.  We set up a server, using an
invalidation-queue-size of 5:

    >>> addr, admin = start_server(zeo_conf=dict(invalidation_queue_size=5),
    ...                            keep=True)

Now, we'll open a client with a persistent cache, set up some data,
and  then close client:

    >>> import ZEO, transaction
    >>> db = ZEO.DB(addr, client='test')
    >>> conn = db.open()
    >>> for i in range(9):
    ...     conn.root()[i] = conn.root().__class__()
    ...     conn.root()[i].x = 0
    >>> transaction.commit()
    >>> db.close()

We'll open another client, and commit some transactions:

    >>> db = ZEO.DB(addr)
    >>> conn = db.open()
    >>> import transaction
    >>> for i in range(2):
    ...     conn.root()[i].x = 1
    ...     transaction.commit()
    >>> db.close()

If we reopen the first client, we'll do quick verification.  We'll
turn on logging so we can see this:

    >>> import logging, sys
    >>> old_logging_level = logging.getLogger().getEffectiveLevel()
    >>> logging.getLogger().setLevel(logging.INFO)
    >>> handler = logging.StreamHandler(sys.stdout)
    >>> logging.getLogger().addHandler(handler)

    >>> db = ZEO.DB(addr, client='test') # doctest: +ELLIPSIS
    ('localhost', ...
    ('localhost', ...) Recovering 2 invalidations

    >>> logging.getLogger().removeHandler(handler)

    >>> [v.x for v in db.open().root().values()]
    [1, 1, 0, 0, 0, 0, 0, 0, 0]

Now, if we disconnect and commit more than 5 transactions, we'll see
that verification is necessary:

    >>> db.close()
    >>> db = ZEO.DB(addr)
    >>> conn = db.open()
    >>> import transaction
    >>> for i in range(9):
    ...     conn.root()[i].x = 2
    ...     transaction.commit()
    >>> db.close()

    >>> logging.getLogger().addHandler(handler)
    >>> db = ZEO.DB(addr, client='test') # doctest: +ELLIPSIS
    ('localhost', ...
    ('localhost', ...) Verifying cache
    ('localhost', ...) endVerify finishing
    ('localhost', ...) endVerify finished

    >>> logging.getLogger().removeHandler(handler)

    >>> [v.x for v in db.open().root().values()]
    [2, 2, 2, 2, 2, 2, 2, 2, 2]

    >>> db.close()

But if we restart the server with invalidation-age set, we can
do quick verification:

    >>> stop_server(admin)
    >>> addr, admin = start_server(zeo_conf=dict(invalidation_queue_size=5,
    ...                                          invalidation_age=100))
    >>> db = ZEO.DB(addr)
    >>> conn = db.open()
    >>> import transaction
    >>> for i in range(9):
    ...     conn.root()[i].x = 3
    ...     transaction.commit()
    >>> db.close()


    >>> logging.getLogger().addHandler(handler)
    >>> db = ZEO.DB(addr, client='test') # doctest: +ELLIPSIS
    ('localhost', ...
    ('localhost', ...) Recovering 9 invalidations

    >>> logging.getLogger().removeHandler(handler)

    >>> [v.x for v in db.open().root().values()]
    [3, 3, 3, 3, 3, 3, 3, 3, 3]

    >>> db.close()

    >>> logging.getLogger().setLevel(old_logging_level)