Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Z
ZEO
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
ZEO
Commits
2ed4e009
Commit
2ed4e009
authored
Oct 02, 2003
by
Jeremy Hylton
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Merge changes from Zope-2_7-branch to the trunk.
parent
7de4d7a7
Changes
90
Show whitespace changes
Inline
Side-by-side
Showing
90 changed files
with
515 additions
and
433 deletions
+515
-433
doc/ZEO/howto.txt
doc/ZEO/howto.txt
+3
-18
doc/ZEO/trace.txt
doc/ZEO/trace.txt
+2
-2
doc/guide/chatter.py
doc/guide/chatter.py
+9
-10
doc/guide/links.tex
doc/guide/links.tex
+0
-3
doc/guide/prog-zodb.tex
doc/guide/prog-zodb.tex
+29
-46
doc/guide/zodb.tex
doc/guide/zodb.tex
+1
-4
src/BTrees/tests/testBTrees.py
src/BTrees/tests/testBTrees.py
+1
-1
src/ThreadedAsync/LoopCallback.py
src/ThreadedAsync/LoopCallback.py
+12
-2
src/ThreadedAsync/__init__.py
src/ThreadedAsync/__init__.py
+2
-2
src/ZEO/ClientStorage.py
src/ZEO/ClientStorage.py
+14
-4
src/ZEO/CommitLog.py
src/ZEO/CommitLog.py
+5
-0
src/ZEO/DebugServer.py
src/ZEO/DebugServer.py
+2
-2
src/ZEO/ServerStub.py
src/ZEO/ServerStub.py
+7
-3
src/ZEO/StorageServer.py
src/ZEO/StorageServer.py
+18
-14
src/ZEO/__init__.py
src/ZEO/__init__.py
+2
-2
src/ZEO/auth/__init__.py
src/ZEO/auth/__init__.py
+0
-1
src/ZEO/auth/auth_digest.py
src/ZEO/auth/auth_digest.py
+2
-2
src/ZEO/auth/base.py
src/ZEO/auth/base.py
+10
-10
src/ZEO/monitor.py
src/ZEO/monitor.py
+3
-3
src/ZEO/tests/CommitLockTests.py
src/ZEO/tests/CommitLockTests.py
+12
-11
src/ZEO/tests/ConnectionTests.py
src/ZEO/tests/ConnectionTests.py
+1
-1
src/ZEO/tests/InvalidationTests.py
src/ZEO/tests/InvalidationTests.py
+9
-9
src/ZEO/tests/auth_plaintext.py
src/ZEO/tests/auth_plaintext.py
+20
-9
src/ZEO/tests/forker.py
src/ZEO/tests/forker.py
+3
-3
src/ZEO/tests/testAuth.py
src/ZEO/tests/testAuth.py
+21
-3
src/ZEO/tests/testClientCache.py
src/ZEO/tests/testClientCache.py
+2
-2
src/ZEO/tests/testMonitor.py
src/ZEO/tests/testMonitor.py
+2
-2
src/ZEO/tests/testZEO.py
src/ZEO/tests/testZEO.py
+2
-1
src/ZEO/tests/zeoserver.py
src/ZEO/tests/zeoserver.py
+9
-6
src/ZEO/version.txt
src/ZEO/version.txt
+1
-5
src/ZEO/zeopasswd.py
src/ZEO/zeopasswd.py
+15
-40
src/ZEO/zrpc/client.py
src/ZEO/zrpc/client.py
+2
-1
src/ZEO/zrpc/connection.py
src/ZEO/zrpc/connection.py
+8
-4
src/ZEO/zrpc/server.py
src/ZEO/zrpc/server.py
+0
-2
src/ZEO/zrpc/smac.py
src/ZEO/zrpc/smac.py
+42
-18
src/ZEO/zrpc/trigger.py
src/ZEO/zrpc/trigger.py
+9
-0
src/ZODB/BaseStorage.py
src/ZODB/BaseStorage.py
+1
-1
src/ZODB/Connection.py
src/ZODB/Connection.py
+6
-6
src/ZODB/DB.py
src/ZODB/DB.py
+4
-4
src/ZODB/DemoStorage.py
src/ZODB/DemoStorage.py
+1
-1
src/ZODB/FileStorage.py
src/ZODB/FileStorage.py
+9
-9
src/ZODB/POSException.py
src/ZODB/POSException.py
+2
-2
src/ZODB/TmpStore.py
src/ZODB/TmpStore.py
+1
-1
src/ZODB/Transaction.py
src/ZODB/Transaction.py
+6
-6
src/ZODB/__init__.py
src/ZODB/__init__.py
+1
-1
src/ZODB/cPickleCache.c
src/ZODB/cPickleCache.c
+12
-1
src/ZODB/config.py
src/ZODB/config.py
+1
-1
src/ZODB/fspack.py
src/ZODB/fspack.py
+11
-12
src/ZODB/fsrecover.py
src/ZODB/fsrecover.py
+2
-3
src/ZODB/tests/BasicStorage.py
src/ZODB/tests/BasicStorage.py
+2
-2
src/ZODB/tests/ConflictResolution.py
src/ZODB/tests/ConflictResolution.py
+2
-2
src/ZODB/tests/Corruption.py
src/ZODB/tests/Corruption.py
+2
-2
src/ZODB/tests/HistoryStorage.py
src/ZODB/tests/HistoryStorage.py
+2
-2
src/ZODB/tests/IteratorStorage.py
src/ZODB/tests/IteratorStorage.py
+2
-2
src/ZODB/tests/LocalStorage.py
src/ZODB/tests/LocalStorage.py
+2
-2
src/ZODB/tests/MTStorage.py
src/ZODB/tests/MTStorage.py
+0
-1
src/ZODB/tests/MinPO.py
src/ZODB/tests/MinPO.py
+2
-2
src/ZODB/tests/PackableStorage.py
src/ZODB/tests/PackableStorage.py
+5
-5
src/ZODB/tests/PersistentStorage.py
src/ZODB/tests/PersistentStorage.py
+2
-2
src/ZODB/tests/ReadOnlyStorage.py
src/ZODB/tests/ReadOnlyStorage.py
+2
-2
src/ZODB/tests/RecoveryStorage.py
src/ZODB/tests/RecoveryStorage.py
+4
-4
src/ZODB/tests/RevisionStorage.py
src/ZODB/tests/RevisionStorage.py
+2
-2
src/ZODB/tests/StorageTestBase.py
src/ZODB/tests/StorageTestBase.py
+3
-3
src/ZODB/tests/Synchronization.py
src/ZODB/tests/Synchronization.py
+2
-2
src/ZODB/tests/TransactionalUndoStorage.py
src/ZODB/tests/TransactionalUndoStorage.py
+8
-10
src/ZODB/tests/TransactionalUndoVersionStorage.py
src/ZODB/tests/TransactionalUndoVersionStorage.py
+9
-9
src/ZODB/tests/VersionStorage.py
src/ZODB/tests/VersionStorage.py
+3
-4
src/ZODB/tests/dangle.py
src/ZODB/tests/dangle.py
+3
-3
src/ZODB/tests/testCache.py
src/ZODB/tests/testCache.py
+2
-2
src/ZODB/tests/testConfig.py
src/ZODB/tests/testConfig.py
+4
-1
src/ZODB/tests/testDB.py
src/ZODB/tests/testDB.py
+8
-8
src/ZODB/tests/testFileStorage.py
src/ZODB/tests/testFileStorage.py
+9
-9
src/ZODB/tests/testPersistentList.py
src/ZODB/tests/testPersistentList.py
+2
-2
src/ZODB/tests/testPersistentMapping.py
src/ZODB/tests/testPersistentMapping.py
+2
-2
src/ZODB/tests/testRecover.py
src/ZODB/tests/testRecover.py
+0
-2
src/ZODB/tests/testTimeStamp.py
src/ZODB/tests/testTimeStamp.py
+2
-2
src/ZODB/tests/testTransaction.py
src/ZODB/tests/testTransaction.py
+3
-3
src/ZODB/tests/testUtils.py
src/ZODB/tests/testUtils.py
+2
-2
src/ZODB/tests/testZODB.py
src/ZODB/tests/testZODB.py
+3
-3
src/ZODB/tests/testfsIndex.py
src/ZODB/tests/testfsIndex.py
+2
-2
src/ZODB/transact.py
src/ZODB/transact.py
+1
-1
src/ZODB/utils.py
src/ZODB/utils.py
+0
-1
src/scripts/README.txt
src/scripts/README.txt
+45
-17
src/scripts/tests/testfstest.py
src/scripts/tests/testfstest.py
+1
-2
src/scripts/tests/testzeopack.py
src/scripts/tests/testzeopack.py
+2
-2
src/scripts/zeoserverlog.py
src/scripts/zeoserverlog.py
+1
-1
src/scripts/zodbload.py
src/scripts/zodbload.py
+1
-1
src/zLOG/BaseLogger.py
src/zLOG/BaseLogger.py
+0
-1
src/zLOG/LogHandlers.py
src/zLOG/LogHandlers.py
+0
-5
src/zLOG/tests/testzLog.py
src/zLOG/tests/testzLog.py
+31
-9
No files found.
doc/ZEO/howto.txt
View file @
2ed4e009
...
...
@@ -207,13 +207,6 @@ then this command will install the new ZEO and ZODB:
The install command should create a /home/zope/lib/python/ZEO directoy.
Simple configuration
--------------------
mkzeoinst.py
Or, do it step-by-step.
Configuring server
------------------
...
...
@@ -407,13 +400,9 @@ Running the ZEO server as a daemon
In an operational setting, you will want to run the ZEO server a
daemon process that is restarted when it dies. The zdaemon package
provides two tools for running daemons: zdrun.py and zdctl.py.
The document "Using zdctl and zdrun to manage server processes"
explains how to use these scripts to manage daemons.
XXX example of how to use zdrun
XXX mkzeoinst.py docs should probably go here
provides two tools for running daemons: zdrun.py and zdctl.py. The
document "Using zdctl and zdrun to manage server processes"
(Doc/zdctl.txt) explains how to use these scripts to manage daemons.
Rotating log files
~~~~~~~~~~~~~~~~~~
...
...
@@ -437,10 +426,6 @@ manages a ZEO servers password database.
Diagnosing problems
-------------------
How to use the debug logs.
Common gotchas.
If an exception occurs on the server, the server will log a traceback
and send an exception to the client. The traceback on the client will
show a ZEO protocol library as the source of the error. If you need
...
...
doc/ZEO/trace.txt
View file @
2ed4e009
Client Cache Tracing
====================
ZEO
Client Cache Tracing
====================
====
An important question for ZEO users is: how large should the ZEO
client cache be? ZEO 2 (as of ZEO 2.0b2) has a new feature that lets
...
...
doc/guide/chatter.py
View file @
2ed4e009
...
...
@@ -121,4 +121,3 @@ if __name__ == '__main__':
# Wait for a few seconds
pause
=
random
.
randint
(
1
,
4
)
time
.
sleep
(
pause
)
doc/guide/links.tex
View file @
2ed4e009
...
...
@@ -25,7 +25,4 @@ and less in others.
\\
\url
{
http://www.zope.org/Members/bwarsaw/ipc10-slides
}
Download link for ZEO:
\\
\url
{
http://www.zope.org/Products/ZEO/
}
doc/guide/prog-zodb.tex
View file @
2ed4e009
...
...
@@ -9,36 +9,28 @@
\subsection
{
Installing ZODB
}
The ZODB forms part of Zope, but it's difficult and somewhat painful
to extract the bits from Zope needed to support just the ZODB.
Therefore I've assembled a distribution containing only the packages
required to use the ZODB and ZEO, so you can install it and start
programming right away.
To download the distribution, go to my ZODB page at
\url
{
http://www.amk.ca/zodb/
}
.
The distribution is still experimental, so don't be surprised if the
installation process runs into problems. Please inform me of any
difficulties you encounter.
ZODB is packaged using the standard distutils tools.
\subsubsection
{
Requirements
}
You will need Python 2.
1 or higher. T
he code is packaged using
Distutils. So it is simply a matter of untarring or unzipping th
e
release
package, and then running
\code
{
python setup.py install
}
.
You will need Python 2.
2 or higher. Since t
he code is packaged using
distutils, it is simply a matter of untarring or unzipping the releas
e
package, and then running
\code
{
python setup.py install
}
.
You'll need a C compiler to build the packages, because there are
various C extension modules. At the moment no one is making Windows
binaries available, so you'll need a Windows development environment
to build ZODB.
various C extension modules. Binary installers are provided for
Windows users.
\subsubsection
{
Installing the Packages
}
Download the ZODB tarball containing all the packages for both ZODB
and ZEO from
\url
{
http://www.zope.org/Products/
StandaloneZODB
}
. See
and ZEO from
\url
{
http://www.zope.org/Products/
ZODB3.2
}
. See
the
\file
{
README.txt
}
file in the top level of the release directory
for details on building, testing, and installing.
You can find information about ZODB and the most current releases in
the ZODB Wiki at
\url
{
http://www.zope.org/Wikis/ZODB
}
.
\subsection
{
How ZODB Works
}
The ZODB is conceptually simple. Python classes subclass a
...
...
@@ -59,8 +51,10 @@ don't get corrupted by software or hardware crashes, and most database
software offers protection against such corruption by supporting four
useful properties, Atomicity, Consistency, Isolation, and Durability.
In computer science jargon these four terms are collectively dubbed
the ACID properties, forming an acronym from their names. The
definitions of the ACID properties are:
the ACID properties, forming an acronym from their names.
The ZODB provides all of the ACID properties. Definitions of the
ACID properties are:
\begin{itemize}
...
...
@@ -73,18 +67,13 @@ forgotten. That's bad, but it's better than having a
partially-applied modification put the database into an inconsistent
state.
\item
[Consistency]
means that the data cannot be placed into a
logically invalid state; sanity checks can be written and enforced.
Usually this is done by defining a database schema, and requiring
the data always matches the schema. There are two typical
approaches to consistency. One is to enforce rules about the types
of objects and attribute; for example, enforce that the
\code
{
order
_
number
}
attribute is always an integer, and not a
string, tuple, or other object. Another is to guarantee consistency
across data structures; for example, that any object with an
\code
{
order
_
number
}
attribute must also appear in the
\code
{
orders
_
table
}
object. In general, atomicity and isolation make
it possible for applications to provide consistency.
\item
[Consistency]
means that each transaction executes a valid
transformation of the database state. Some databases, but not ZODB,
provide a variety of consistency checks in the database or language;
for example, a relational database constraint columns to be of
particular types and can enforce relations across tables. Viewed more
generally, atomicity and isolation make it possible for applications
to provide consistency.
\item
[Isolation]
means that two programs or threads running in two
different transactions cannot see each other's changes until they
...
...
@@ -95,10 +84,6 @@ a subsequent crash will not cause any data to be lost or corrupted.
\end{itemize}
The ZODB provides 3 of the ACID properties. Only Consistency is not
supported; the ZODB has no notion of a database schema, and therefore
has no way of enforcing consistency with a schema.
\subsection
{
Opening a ZODB
}
There are 3 main interfaces supplied by the ZODB:
...
...
@@ -132,9 +117,9 @@ implement the \class{Storage} interface.
\end{itemize}
Preparing to use a ZODB requires 3 steps: you have to open the
\class
{
Storage
}
, then create a
\class
{
DB
}
instance that uses the
\class
{
Storage
}
, and then get
a
\class
{
Connection
}
from the
\class
{
DB instance
}
. All this is only a few lines of
code:
\class
{
Storage
}
, then create a
\class
{
DB
}
instance that uses the
\class
{
Storage
}
, and then get a
\class
{
Connection
}
from the
\class
{
DB
instance
}
. All this is only a few lines of
code:
\begin{verbatim}
from ZODB import FileStorage, DB
...
...
@@ -189,7 +174,7 @@ retrieving a \class{User} object given the user's ID. First, we
retrieve the primary root object of the ZODB using the
\method
{
root()
}
method of the
\class
{
Connection
}
instance. The root object behaves
like a Python dictionary, so you can just add a new key/value pair for
your application's root object. We'll insert a
\class
{
BTree
}
object
your application's root object. We'll insert a
n
\class
{
OO
BTree
}
object
that will contain all the
\class
{
User
}
objects. (The
\class
{
BTree
}
module is also included as part of Zope.)
...
...
@@ -199,8 +184,8 @@ dbroot = conn.root()
# Ensure that a 'userdb' key is present
# in the root
if not dbroot.has
_
key('userdb'):
import
BTree
dbroot['userdb'] =
BTree.
BTree()
from BTrees.OOBTree import OO
BTree
dbroot['userdb'] =
OO
BTree()
userdb = dbroot['userdb']
\end{verbatim}
...
...
@@ -426,13 +411,11 @@ different class instances, then there's no longer any easy way to find
them all, short of writing a generalized object traversal function
that would walk over every single object in a ZODB, checking each one
to see if it's an instance of
\class
{
User
}
.
\footnote
{
XXX is there a convenience method for walking the object graph hiding
somewhere inside DC's code? Should there be a utility method for
doing this? Should I write one and include it in this section?
}
Some OODBs support a feature called extents, which allow quickly
finding all the instances of a given class, no matter where they are
in the object graph; unfortunately the ZODB doesn't offer extents as a
feature.
XXX Rest of section not written yet:
__
getstate
__
/
__
setstate
__
%
XXX Rest of section not written yet: __getstate__/__setstate__
doc/guide/zodb.tex
View file @
2ed4e009
\documentclass
{
howto
}
\title
{
ZODB/ZEO Programming Guide
}
\release
{
0.
1
}
\release
{
0.
2
}
\date
{
\today
}
\author
{
A.M.
\
Kuchling
}
...
...
@@ -23,9 +23,6 @@
\input
{
prog-zodb
}
\input
{
zeo
}
\input
{
transactions
}
%\input{storages}
%\input{indexing}
%\input{admin}
\input
{
modules
}
\appendix
...
...
src/BTrees/tests/testBTrees.py
View file @
2ed4e009
src/ThreadedAsync/LoopCallback.py
View file @
2ed4e009
...
...
@@ -25,7 +25,7 @@ register_loop_callback() to register interest. When the mainloop
thread calls loop(), each registered callback will be called with the
socket map as its first argument.
"""
__version__
=
'$Revision: 1.
8
$'
[
11
:
-
2
]
__version__
=
'$Revision: 1.
9
$'
[
11
:
-
2
]
import
asyncore
import
select
...
...
@@ -58,6 +58,16 @@ def register_loop_callback(callback, args=(), kw=None):
finally
:
_loop_lock
.
release
()
def
remove_loop_callback
(
callback
):
"""Remove a callback function registered earlier.
This is useful if loop() was never called.
"""
for
i
in
range
(
len
(
_loop_callbacks
)):
if
_loop_callbacks
[
i
][
0
]
==
callback
:
del
_loop_callbacks
[
i
]
return
def
_start_loop
(
map
):
_loop_lock
.
acquire
()
try
:
...
...
src/ThreadedAsync/__init__.py
View file @
2ed4e009
...
...
@@ -13,7 +13,7 @@
##############################################################################
"""Manage the asyncore mainloop in a multi-threaded app.
$Id: __init__.py,v 1.
6 2003/02/25 15:17:09 fdrake
Exp $
$Id: __init__.py,v 1.
7 2003/10/02 18:17:26 jeremy
Exp $
"""
from
LoopCallback
import
register_loop_callback
,
loop
from
LoopCallback
import
register_loop_callback
,
loop
,
remove_loop_callback
src/ZEO/ClientStorage.py
View file @
2ed4e009
...
...
@@ -99,7 +99,7 @@ class ClientStorage(object):
name
=
''
,
client
=
None
,
debug
=
0
,
var
=
None
,
min_disconnect_poll
=
5
,
max_disconnect_poll
=
300
,
wait_for_server_on_startup
=
None
,
# deprecated alias for wait
wait
=
None
,
# defaults to 1
wait
=
None
,
wait_timeout
=
None
,
read_only
=
0
,
read_only_fallback
=
0
,
username
=
''
,
password
=
''
,
realm
=
None
):
"""ClientStorage constructor.
...
...
@@ -152,6 +152,9 @@ class ClientStorage(object):
wait -- A flag indicating whether to wait until a connection
with a server is made, defaulting to true.
wait_timeout -- Maximum time to wait for a connection before
giving up. Only meaningful if wait is True.
read_only -- A flag indicating whether this should be a
read-only storage, defaulting to false (i.e. writing is
allowed by default).
...
...
@@ -302,7 +305,7 @@ class ClientStorage(object):
tmax
=
max_disconnect_poll
)
if
wait
:
self
.
_wait
()
self
.
_wait
(
wait_timeout
)
else
:
# attempt_connect() will make an attempt that doesn't block
# "too long," for a very vague notion of too long. If that
...
...
@@ -313,7 +316,9 @@ class ClientStorage(object):
if
not
self
.
_ready
.
isSet
():
self
.
_cache
.
open
()
def
_wait
(
self
):
def
_wait
(
self
,
timeout
=
None
):
if
timeout
is
not
None
:
deadline
=
time
.
time
()
+
timeout
# Wait for a connection to be established.
self
.
_rpc_mgr
.
connect
(
sync
=
1
)
# When a synchronous connect() call returns, there is
...
...
@@ -326,6 +331,9 @@ class ClientStorage(object):
self
.
_ready
.
wait
(
30
)
if
self
.
_ready
.
isSet
():
break
if
timeout
and
time
.
time
()
>
deadline
:
log2
(
PROBLEM
,
"Timed out waiting for connection"
)
break
log2
(
INFO
,
"Waiting for cache verification to finish"
)
else
:
self
.
_wait_sync
()
...
...
@@ -434,8 +442,10 @@ class ClientStorage(object):
auth
=
stub
.
getAuthProtocol
()
log2
(
INFO
,
"Server authentication protocol %r"
%
auth
)
if
auth
:
if
self
.
doAuth
(
auth
,
stub
):
skey
=
self
.
doAuth
(
auth
,
stub
)
if
skey
:
log2
(
INFO
,
"Client authentication successful"
)
conn
.
setSessionKey
(
skey
)
else
:
log2
(
ERROR
,
"Authentication failed"
)
raise
AuthError
,
"Authentication failed"
...
...
src/ZEO/CommitLog.py
View file @
2ed4e009
...
...
@@ -42,3 +42,8 @@ class CommitLog:
self
.
read
=
1
self
.
file
.
seek
(
0
)
return
self
.
stores
,
cPickle
.
Unpickler
(
self
.
file
)
def
close
(
self
):
if
self
.
file
:
self
.
file
.
close
()
self
.
file
=
None
src/ZEO/DebugServer.py
View file @
2ed4e009
src/ZEO/ServerStub.py
View file @
2ed4e009
...
...
@@ -32,9 +32,13 @@ class StorageServer:
zrpc.connection.Connection class.
"""
self
.
rpc
=
rpc
if
self
.
rpc
.
peer_protocol_version
==
'Z200'
:
# Wait until we know what version the other side is using.
while
rpc
.
peer_protocol_version
is
None
:
rpc
.
pending
()
if
rpc
.
peer_protocol_version
==
'Z200'
:
self
.
lastTransaction
=
lambda
:
None
self
.
getInvalidations
=
lambda
tid
:
None
self
.
getAuthProtocol
=
lambda
:
None
def
extensionMethod
(
self
,
name
):
return
ExtensionMethodWrapper
(
self
.
rpc
,
name
).
call
...
...
src/ZEO/StorageServer.py
View file @
2ed4e009
...
...
@@ -43,7 +43,7 @@ from ZODB.POSException import StorageError, StorageTransactionError
from
ZODB.POSException
import
TransactionError
,
ReadOnlyError
,
ConflictError
from
ZODB.referencesf
import
referencesf
from
ZODB.Transaction
import
Transaction
from
ZODB.utils
import
u64
from
ZODB.utils
import
u64
,
oid_repr
_label
=
"ZSS"
# Default label used for logging.
...
...
@@ -398,6 +398,7 @@ class ZEOStorage:
def
_clear_transaction
(
self
):
# Common code at end of tpc_finish() and tpc_abort()
self
.
transaction
=
None
self
.
txnlog
.
close
()
if
self
.
locked
:
self
.
locked
=
0
self
.
timeout
.
end
(
self
)
...
...
@@ -483,6 +484,8 @@ class ZEOStorage:
self
.
store_failed
=
1
if
isinstance
(
err
,
ConflictError
):
self
.
stats
.
conflicts
+=
1
self
.
log
(
"conflict error oid=%s msg=%s"
%
(
oid_repr
(
oid
),
str
(
err
)),
zLOG
.
BLATHER
)
if
not
isinstance
(
err
,
TransactionError
):
# Unexpected errors are logged and passed to the client
exc_info
=
sys
.
exc_info
()
...
...
@@ -506,6 +509,7 @@ class ZEOStorage:
self
.
invalidated
.
append
((
oid
,
version
))
if
newserial
==
ResolvedSerial
:
self
.
stats
.
conflicts_resolved
+=
1
self
.
log
(
"conflict resolved oid=%s"
%
oid_repr
(
oid
),
zLOG
.
BLATHER
)
self
.
serials
.
append
((
oid
,
newserial
))
return
err
is
None
...
...
@@ -928,6 +932,7 @@ class TimeoutThread(threading.Thread):
self
.
_cond
.
acquire
()
try
:
assert
self
.
_client
is
not
None
assert
self
.
_client
is
client
self
.
_client
=
None
self
.
_deadline
=
None
finally
:
...
...
@@ -953,7 +958,6 @@ class TimeoutThread(threading.Thread):
self
.
_trigger
.
pull_trigger
(
lambda
:
client
.
connection
.
close
())
else
:
time
.
sleep
(
howlong
)
self
.
trigger
.
close
()
def
run_in_thread
(
method
,
*
args
):
t
=
SlowMethodThread
(
method
,
args
)
...
...
src/ZEO/__init__.py
View file @
2ed4e009
...
...
@@ -21,4 +21,4 @@ ZEO is now part of ZODB; ZODB's home on the web is
"""
version
=
"2.
1b2
"
version
=
"2.
2c1
"
src/ZEO/auth/__init__.py
View file @
2ed4e009
...
...
@@ -28,4 +28,3 @@ def register_module(name, storage_class, client, db):
if
_auth_modules
.
has_key
(
name
):
raise
TypeError
,
"%s is already registred"
%
name
_auth_modules
[
name
]
=
storage_class
,
client
,
db
src/ZEO/auth/auth_digest.py
View file @
2ed4e009
src/ZEO/auth/base.py
View file @
2ed4e009
src/ZEO/monitor.py
View file @
2ed4e009
...
...
@@ -13,7 +13,7 @@
##############################################################################
"""Monitor behavior of ZEO server and record statistics.
$Id: monitor.py,v 1.
3 2003/01/15 21:23:16
jeremy Exp $
$Id: monitor.py,v 1.
4 2003/10/02 18:17:22
jeremy Exp $
"""
import
asyncore
...
...
src/ZEO/tests/CommitLockTests.py
View file @
2ed4e009
...
...
@@ -27,7 +27,7 @@ from ZEO.tests.TestThread import TestThread
ZERO
=
'
\
0
'
*
8
class
DummyDB
:
def
invalidate
(
self
,
*
args
):
def
invalidate
(
self
,
*
args
,
**
kwargs
):
pass
class
WorkerThread
(
TestThread
):
...
...
@@ -204,7 +204,8 @@ class CommitLockTests:
def
_begin_threads
(
self
):
# Start a second transaction on a different connection without
# blocking the test thread.
# blocking the test thread. Returns only after each thread has
# set it's ready event.
self
.
_storages
=
[]
self
.
_threads
=
[]
...
...
src/ZEO/tests/ConnectionTests.py
View file @
2ed4e009
src/ZEO/tests/InvalidationTests.py
View file @
2ed4e009
...
...
@@ -347,8 +347,8 @@ class InvalidationTests:
# Run two threads that update the BTree
cd
=
{}
t1
=
self
.
StressThread
(
self
,
db1
,
stop
,
1
,
cd
,
1
,
sleep
=
0.0
0
1
)
t2
=
self
.
StressThread
(
self
,
db1
,
stop
,
2
,
cd
,
2
,
sleep
=
0.0
0
1
)
t1
=
self
.
StressThread
(
self
,
db1
,
stop
,
1
,
cd
,
1
,
sleep
=
0.01
)
t2
=
self
.
StressThread
(
self
,
db1
,
stop
,
2
,
cd
,
2
,
sleep
=
0.01
)
self
.
go
(
stop
,
cd
,
t1
,
t2
)
cn
.
sync
()
...
...
@@ -375,8 +375,8 @@ class InvalidationTests:
cd
=
{}
t1
=
self
.
StressThread
(
self
,
db1
,
stop
,
1
,
cd
,
1
,
3
)
t2
=
self
.
StressThread
(
self
,
db2
,
stop
,
2
,
cd
,
2
,
3
,
0.0
0
1
)
t3
=
self
.
StressThread
(
self
,
db2
,
stop
,
3
,
cd
,
3
,
3
,
0.0
0
1
)
t2
=
self
.
StressThread
(
self
,
db2
,
stop
,
2
,
cd
,
2
,
3
,
0.01
)
t3
=
self
.
StressThread
(
self
,
db2
,
stop
,
3
,
cd
,
3
,
3
,
0.01
)
self
.
go
(
stop
,
cd
,
t1
,
t2
,
t3
)
cn
.
sync
()
...
...
@@ -404,8 +404,8 @@ class InvalidationTests:
cd
=
{}
t1
=
VersionStressThread
(
self
,
db1
,
stop
,
1
,
cd
,
1
,
3
)
t2
=
VersionStressThread
(
self
,
db2
,
stop
,
2
,
cd
,
2
,
3
,
0.0
0
1
)
t3
=
VersionStressThread
(
self
,
db2
,
stop
,
3
,
cd
,
3
,
3
,
0.0
0
1
)
t2
=
VersionStressThread
(
self
,
db2
,
stop
,
2
,
cd
,
2
,
3
,
0.01
)
t3
=
VersionStressThread
(
self
,
db2
,
stop
,
3
,
cd
,
3
,
3
,
0.01
)
self
.
go
(
stop
,
cd
,
t1
,
t2
,
t3
)
cn
.
sync
()
...
...
@@ -435,9 +435,9 @@ class InvalidationTests:
# at the same time.
cd
=
{}
t1
=
LargeUpdatesThread
(
self
,
db1
,
stop
,
1
,
cd
,
1
,
3
,
0.0
01
)
t2
=
LargeUpdatesThread
(
self
,
db2
,
stop
,
2
,
cd
,
2
,
3
,
0.0
0
1
)
t3
=
LargeUpdatesThread
(
self
,
db2
,
stop
,
3
,
cd
,
3
,
3
,
0.0
0
1
)
t1
=
LargeUpdatesThread
(
self
,
db1
,
stop
,
1
,
cd
,
1
,
3
,
0.0
2
)
t2
=
LargeUpdatesThread
(
self
,
db2
,
stop
,
2
,
cd
,
2
,
3
,
0.01
)
t3
=
LargeUpdatesThread
(
self
,
db2
,
stop
,
3
,
cd
,
3
,
3
,
0.01
)
self
.
go
(
stop
,
cd
,
t1
,
t2
,
t3
)
cn
.
sync
()
...
...
src/ZEO/tests/auth_plaintext.py
View file @
2ed4e009
...
...
@@ -16,8 +16,8 @@ an SHA hash in the Database. The client sends over the plaintext
password, and the SHA hashing is done on the server side.
This mechanism offers *no network security at all*; the only security
is provided by not storing plaintext passwords on disk.
(See the
auth_srp module for a secure mechanism)
"""
is provided by not storing plaintext passwords on disk.
"""
import
sha
...
...
@@ -25,6 +25,9 @@ from ZEO.StorageServer import ZEOStorage
from
ZEO.auth
import
register_module
from
ZEO.auth.base
import
Client
,
Database
def
session_key
(
username
,
realm
,
password
):
return
sha
.
new
(
"%s:%s:%s"
%
(
username
,
realm
,
password
)).
hexdigest
()
class
StorageClass
(
ZEOStorage
):
def
auth
(
self
,
username
,
password
):
try
:
...
...
@@ -32,13 +35,21 @@ class StorageClass(ZEOStorage):
except
LookupError
:
return
0
password
=
sha
.
new
(
password
).
hexdigest
()
return
self
.
finish_auth
(
dbpw
==
password
)
password_dig
=
sha
.
new
(
password
).
hexdigest
()
if
dbpw
==
password_dig
:
self
.
connection
.
setSessionKey
(
session_key
(
username
,
self
.
database
.
realm
,
password
))
return
self
.
finish_auth
(
dbpw
==
password_dig
)
class
PlaintextClient
(
Client
):
extensions
=
[
"auth"
]
def
start
(
self
,
username
,
realm
,
password
):
return
self
.
stub
.
auth
(
username
,
password
)
if
self
.
stub
.
auth
(
username
,
password
):
return
session_key
(
username
,
realm
,
password
)
else
:
return
None
register_module
(
"plaintext"
,
StorageClass
,
PlaintextClient
,
Database
)
src/ZEO/tests/forker.py
View file @
2ed4e009
src/ZEO/tests/testAuth.py
View file @
2ed4e009
...
...
@@ -18,8 +18,11 @@ import tempfile
import
time
import
unittest
import
zLOG
from
ThreadedAsync
import
LoopCallback
from
ZEO.ClientStorage
import
ClientStorage
from
ZEO.Exceptions
import
ClientDisconnected
from
ZEO.StorageServer
import
StorageServer
from
ZEO.tests.ConnectionTests
import
CommonSetupTearDown
...
...
@@ -74,6 +77,8 @@ class AuthTest(CommonSetupTearDown):
self
.
assert_
(
self
.
_storage
.
_connection
)
self
.
_storage
.
_connection
.
poll
()
self
.
assert_
(
self
.
_storage
.
is_connected
())
# Make a call to make sure the mechanism is working
self
.
_storage
.
versions
()
def
testNOK
(
self
):
self
.
_storage
=
self
.
openClientStorage
(
wait
=
0
,
username
=
"foo"
,
...
...
@@ -83,6 +88,20 @@ class AuthTest(CommonSetupTearDown):
# If the test established a connection, then it failed.
self
.
failIf
(
self
.
_storage
.
_connection
)
def
testUnauthenticatedMessage
(
self
):
# Test that an unauthenticated message is rejected by the server
# if it was sent after the connection was authenticated.
# Sleep for 0.2 seconds to give the server some time to start up
# seems to be needed before and after creating the storage
self
.
_storage
=
self
.
openClientStorage
(
wait
=
0
,
username
=
"foo"
,
password
=
"bar"
,
realm
=
self
.
realm
)
self
.
wait
()
self
.
_storage
.
versions
()
# Manually clear the state of the hmac connection
self
.
_storage
.
_connection
.
_SizedMessageAsyncConnection__hmac_send
=
None
# Once the client stops using the hmac, it should be disconnected.
self
.
assertRaises
(
ClientDisconnected
,
self
.
_storage
.
versions
)
class
PlainTextAuth
(
AuthTest
):
import
ZEO.tests.auth_plaintext
protocol
=
"plaintext"
...
...
@@ -108,4 +127,3 @@ def test_suite():
if
__name__
==
"__main__"
:
unittest
.
main
(
defaultTest
=
'test_suite'
)
src/ZEO/tests/testClientCache.py
View file @
2ed4e009
src/ZEO/tests/testMonitor.py
View file @
2ed4e009
...
...
@@ -13,7 +13,7 @@
##############################################################################
"""Test that the monitor produce sensible results.
$Id: testMonitor.py,v 1.
6 2003/05/30 19:20:56
jeremy Exp $
$Id: testMonitor.py,v 1.
7 2003/10/02 18:17:21
jeremy Exp $
"""
import
socket
...
...
src/ZEO/tests/testZEO.py
View file @
2ed4e009
...
...
@@ -132,7 +132,8 @@ class GenericTests(
self
.
_servers
=
[
adminaddr
]
self
.
_conf_path
=
path
self
.
_storage
=
ClientStorage
(
zport
,
'1'
,
cache_size
=
20000000
,
min_disconnect_poll
=
0.5
,
wait
=
1
)
min_disconnect_poll
=
0.5
,
wait
=
1
,
wait_timeout
=
60
)
self
.
_storage
.
registerDB
(
DummyDB
(),
None
)
def
tearDown
(
self
):
...
...
src/ZEO/tests/zeoserver.py
View file @
2ed4e009
...
...
@@ -122,8 +122,11 @@ class Suicide(threading.Thread):
self
.
_adminaddr
=
addr
def
run
(
self
):
# If this process doesn't exit in 300 seconds, commit suicide
time
.
sleep
(
300
)
# If this process doesn't exit in 330 seconds, commit suicide.
# The client threads in the ConcurrentUpdate tests will run for
# as long as 300 seconds. Set this timeout to 330 to minimize
# chance that the server gives up before the clients.
time
.
sleep
(
330
)
log
(
"zeoserver"
,
"suicide thread invoking shutdown"
)
from
ZEO.tests.forker
import
shutdown_zeo_server
# XXX If the -k option was given to zeoserver, then the process will
...
...
src/ZEO/version.txt
View file @
2ed4e009
2.1b2
2.2c1
src/ZEO/zeopasswd.py
View file @
2ed4e009
...
...
@@ -17,16 +17,12 @@
usage: python zeopasswd.py [options] username [password]
-C/--configuration URL -- configuration file or URL
-p/--protocol -- authentication protocol name
-f/--filename -- authentication database filename
-r/--realm -- authentication database realm
-d/--delete -- delete user instead of updating password
"""
import
getopt
import
getpass
import
sys
import
os
import
ZConfig
import
ZEO
...
...
@@ -39,41 +35,22 @@ def usage(msg):
def
options
(
args
):
"""Password-specific options loaded from regular ZEO config file."""
schema
=
ZConfig
.
loadSchema
(
os
.
path
.
join
(
os
.
path
.
dirname
(
ZEO
.
__file__
),
"schema.xml"
))
try
:
options
,
args
=
getopt
.
getopt
(
args
,
"dr:p:f:C:"
,
[
"configure="
,
"protocol="
,
"filename="
,
"realm"
])
options
,
args
=
getopt
.
getopt
(
args
,
"C:"
,
[
"configure="
])
except
getopt
.
error
,
msg
:
usage
(
msg
)
config
=
None
delete
=
0
auth_protocol
=
None
auth_db
=
""
auth_realm
=
None
delete
=
False
for
k
,
v
in
options
:
if
k
==
'-C'
or
k
==
'--configure'
:
schemafile
=
os
.
path
.
join
(
os
.
path
.
dirname
(
ZEO
.
__file__
),
"schema.xml"
)
schema
=
ZConfig
.
loadSchema
(
schemafile
)
config
,
nil
=
ZConfig
.
loadConfig
(
schema
,
v
)
if
k
==
'-d'
or
k
==
'--delete'
:
delete
=
1
if
k
==
'-p'
or
k
==
'--protocol'
:
auth_protocol
=
v
if
k
==
'-f'
or
k
==
'--filename'
:
auth_db
=
v
if
k
==
'-r'
or
k
==
'--realm'
:
auth_realm
=
v
if
config
is
not
None
:
if
auth_protocol
or
auth_db
:
usage
(
"Conflicting options; use either -C *or* -p and -f"
)
auth_protocol
=
config
.
zeo
.
authentication_protocol
auth_db
=
config
.
zeo
.
authentication_database
auth_realm
=
config
.
zeo
.
authentication_realm
elif
not
(
auth_protocol
and
auth_db
):
usage
(
"Must specifiy configuration file or protocol and database"
)
delete
=
True
if
config
is
None
:
usage
(
"Must specifiy configuration file"
)
password
=
None
if
delete
:
...
...
@@ -92,21 +69,20 @@ def options(args):
else
:
username
,
password
=
args
return
auth_protocol
,
auth_db
,
auth_realm
,
delete
,
username
,
password
return
config
.
zeo
,
delete
,
username
,
password
def
main
(
args
=
None
):
p
,
auth_db
,
auth_realm
,
delete
,
username
,
password
=
options
(
args
)
options
,
delete
,
username
,
password
=
options
(
args
)
p
=
options
.
authentication_protocol
if
p
is
None
:
usage
(
"ZEO configuration does not specify authentication-protocol"
)
if
p
==
"digest"
:
from
ZEO.auth.auth_digest
import
DigestDatabase
as
Database
elif
p
==
"srp"
:
from
ZEO.auth.auth_srp
import
SRPDatabase
as
Database
else
:
raise
ValueError
,
"Unknown database type %r"
%
p
if
auth_db
is
None
:
if
options
.
authentication_database
is
None
:
usage
(
"ZEO configuration does not specify authentication-database"
)
db
=
Database
(
auth_db
,
auth_realm
)
db
=
Database
(
options
.
authentication_database
)
if
delete
:
db
.
del_user
(
username
)
else
:
...
...
@@ -116,5 +92,4 @@ def main(args=None):
db
.
save
()
if
__name__
==
"__main__"
:
main
(
sys
.
argv
[
1
:])
main
(
sys
.
argv
)
src/ZEO/zrpc/client.py
View file @
2ed4e009
...
...
@@ -105,6 +105,7 @@ class ConnectionManager(object):
if
self
.
trigger
is
not
None
:
self
.
trigger
.
close
()
self
.
trigger
=
None
ThreadedAsync
.
remove_loop_callback
(
self
.
set_async
)
def
set_async
(
self
,
map
):
# This is the callback registered with ThreadedAsync. The
...
...
src/ZEO/zrpc/connection.py
View file @
2ed4e009
...
...
@@ -126,11 +126,15 @@ class Connection(smac.SizedMessageAsyncConnection, object):
# Protocol history:
#
# Z200 --
o
riginal ZEO 2.0 protocol
# Z200 --
O
riginal ZEO 2.0 protocol
#
# Z201 -- added invalidateTransaction() to client;
# renamed several client methods;
# added lastTransaction() to server
# Z201 -- Added invalidateTransaction() to client.
# Renamed several client methods.
# Added several sever methods:
# lastTransaction()
# getAuthProtocol() and scheme-specific authentication methods
# getExtensionMethods().
# getInvalidations().
def
__init__
(
self
,
sock
,
addr
,
obj
=
None
):
self
.
obj
=
None
...
...
src/ZEO/zrpc/server.py
View file @
2ed4e009
...
...
@@ -31,7 +31,6 @@ class Dispatcher(asyncore.dispatcher):
self
.
__super_init
()
self
.
addr
=
addr
self
.
factory
=
factory
self
.
clients
=
[]
self
.
_open_socket
()
def
_open_socket
(
self
):
...
...
@@ -58,4 +57,3 @@ class Dispatcher(asyncore.dispatcher):
return
c
=
self
.
factory
(
sock
,
addr
)
log
(
"connect from %s: %s"
%
(
repr
(
addr
),
c
))
self
.
clients
.
append
(
c
)
src/ZEO/zrpc/smac.py
View file @
2ed4e009
...
...
@@ -64,7 +64,7 @@ del tmp_dict
# that we could pass to send() without blocking.
SEND_SIZE
=
60000
MAC_BIT
=
0x80000000
MAC_BIT
=
0x80000000
L
class
SizedMessageAsyncConnection
(
asyncore
.
dispatcher
):
__super_init
=
asyncore
.
dispatcher
.
__init__
...
...
@@ -96,12 +96,33 @@ class SizedMessageAsyncConnection(asyncore.dispatcher):
self
.
__output_lock
=
threading
.
Lock
()
# Protects __output
self
.
__output
=
[]
self
.
__closed
=
0
self
.
__hmac
=
None
# Each side of the connection sends and receives messages. A
# MAC is generated for each message and depends on each
# previous MAC; the state of the MAC generator depends on the
# history of operations it has performed. So the MACs must be
# generated in the same order they are verified.
# Each side is guaranteed to receive messages in the order
# they are sent, but there is no ordering constraint between
# message sends and receives. If the two sides are A and B
# and message An indicates the nth message sent by A, then
# A1 A2 B1 B2 and A1 B1 B2 A2 are both legitimate total
# orderings of the messages.
# As a result, there must be seperate MAC generators for each
# side of the connection. If not, the generator state would
# be different after A1 A2 B1 B2 than it would be after
# A1 B1 B2 A2; if the generator state was different, the MAC
# could not be verified.
self
.
__hmac_send
=
None
self
.
__hmac_recv
=
None
self
.
__super_init
(
sock
,
map
)
def
setSessionKey
(
self
,
sesskey
):
log
(
"set session key %r"
%
sesskey
)
self
.
__hmac
=
hmac
.
HMAC
(
sesskey
,
digestmod
=
sha
)
self
.
__hmac_send
=
hmac
.
HMAC
(
sesskey
,
digestmod
=
sha
)
self
.
__hmac_recv
=
hmac
.
HMAC
(
sesskey
,
digestmod
=
sha
)
def
get_addr
(
self
):
return
self
.
addr
...
...
@@ -150,16 +171,18 @@ class SizedMessageAsyncConnection(asyncore.dispatcher):
inp
=
""
.
join
(
inp
)
offset
=
0
expect
_mac
=
0
has
_mac
=
0
while
(
offset
+
msg_size
)
<=
input_len
:
msg
=
inp
[
offset
:
offset
+
msg_size
]
offset
=
offset
+
msg_size
if
not
state
:
msg_size
=
struct
.
unpack
(
">
i
"
,
msg
)[
0
]
expect
_mac
=
msg_size
&
MAC_BIT
if
expect
_mac
:
msg_size
=
struct
.
unpack
(
">
I
"
,
msg
)[
0
]
has
_mac
=
msg_size
&
MAC_BIT
if
has
_mac
:
msg_size
^=
MAC_BIT
msg_size
+=
20
elif
self
.
__hmac_send
:
raise
ValueError
(
"Received message without MAC"
)
state
=
1
else
:
msg_size
=
4
...
...
@@ -174,12 +197,12 @@ class SizedMessageAsyncConnection(asyncore.dispatcher):
# incoming call to be handled. During all this
# time, the __input_lock is held. That's a good
# thing, because it serializes incoming calls.
if
expect
_mac
:
if
has
_mac
:
mac
=
msg
[:
20
]
msg
=
msg
[
20
:]
if
self
.
__hmac
:
self
.
__hmac
.
update
(
msg
)
_mac
=
self
.
__hmac
.
digest
()
if
self
.
__hmac
_recv
:
self
.
__hmac
_recv
.
update
(
msg
)
_mac
=
self
.
__hmac
_recv
.
digest
()
if
mac
!=
_mac
:
raise
ValueError
(
"MAC failed: %r != %r"
%
(
_mac
,
mac
))
...
...
@@ -245,8 +268,9 @@ class SizedMessageAsyncConnection(asyncore.dispatcher):
def
message_output
(
self
,
message
):
if
__debug__
:
if
self
.
_debug
:
log
(
'message_output %d bytes: %s'
%
(
len
(
message
),
short_repr
(
message
)),
log
(
"message_output %d bytes: %s hmac=%d"
%
(
len
(
message
),
short_repr
(
message
),
self
.
__hmac_send
and
1
or
0
),
level
=
zLOG
.
TRACE
)
if
self
.
__closed
:
...
...
@@ -255,12 +279,12 @@ class SizedMessageAsyncConnection(asyncore.dispatcher):
self
.
__output_lock
.
acquire
()
try
:
# do two separate appends to avoid copying the message string
if
self
.
__hmac
:
self
.
__output
.
append
(
struct
.
pack
(
">
i
"
,
len
(
message
)
|
MAC_BIT
))
self
.
__hmac
.
update
(
message
)
self
.
__output
.
append
(
self
.
__hmac
.
digest
())
if
self
.
__hmac
_send
:
self
.
__output
.
append
(
struct
.
pack
(
">
I
"
,
len
(
message
)
|
MAC_BIT
))
self
.
__hmac
_send
.
update
(
message
)
self
.
__output
.
append
(
self
.
__hmac
_send
.
digest
())
else
:
self
.
__output
.
append
(
struct
.
pack
(
">
i
"
,
len
(
message
)))
self
.
__output
.
append
(
struct
.
pack
(
">
I
"
,
len
(
message
)))
if
len
(
message
)
<=
SEND_SIZE
:
self
.
__output
.
append
(
message
)
else
:
...
...
src/ZEO/zrpc/trigger.py
View file @
2ed4e009
...
...
@@ -167,6 +167,15 @@ else:
self
.
lock
=
thread
.
allocate_lock
()
self
.
thunks
=
[]
self
.
_trigger_connected
=
0
self
.
_closed
=
0
def
close
(
self
):
if
not
self
.
_closed
:
self
.
_closed
=
1
self
.
del_channel
()
# self.socket is a, self.trigger is w from __init__
self
.
socket
.
close
()
self
.
trigger
.
close
()
def
__repr__
(
self
):
return
'<select-trigger (loopback) at %x>'
%
id
(
self
)
...
...
src/ZODB/BaseStorage.py
View file @
2ed4e009
...
...
@@ -13,7 +13,7 @@
##############################################################################
"""Handy standard storage machinery
$Id: BaseStorage.py,v 1.3
5 2003/09/15 16:29:15
jeremy Exp $
$Id: BaseStorage.py,v 1.3
6 2003/10/02 18:17:19
jeremy Exp $
"""
import
cPickle
import
time
...
...
src/ZODB/Connection.py
View file @
2ed4e009
...
...
@@ -13,7 +13,7 @@
##############################################################################
"""Database connection support
$Id: Connection.py,v 1.
99 2003/09/15 16:29:15
jeremy Exp $"""
$Id: Connection.py,v 1.
100 2003/10/02 18:17:19
jeremy Exp $"""
from
__future__
import
nested_scopes
...
...
src/ZODB/DB.py
View file @
2ed4e009
...
...
@@ -13,8 +13,8 @@
##############################################################################
"""Database objects
$Id: DB.py,v 1.5
4 2003/09/15 16:29:15
jeremy Exp $"""
__version__
=
'$Revision: 1.5
4
$'
[
11
:
-
2
]
$Id: DB.py,v 1.5
5 2003/10/02 18:17:19
jeremy Exp $"""
__version__
=
'$Revision: 1.5
5
$'
[
11
:
-
2
]
import
cPickle
,
cStringIO
,
sys
,
POSException
,
UndoLogCompatible
from
Connection
import
Connection
...
...
src/ZODB/DemoStorage.py
View file @
2ed4e009
...
...
@@ -79,7 +79,7 @@ method::
and call it to monitor the storage.
"""
__version__
=
'$Revision: 1.2
0
$'
[
11
:
-
2
]
__version__
=
'$Revision: 1.2
1
$'
[
11
:
-
2
]
import
base64
,
time
,
string
from
ZODB
import
POSException
,
BaseStorage
,
utils
...
...
src/ZODB/FileStorage.py
View file @
2ed4e009
...
...
@@ -115,7 +115,7 @@
# may have a back pointer to a version record or to a non-version
# record.
#
__version__
=
'$Revision: 1.13
7
$'
[
11
:
-
2
]
__version__
=
'$Revision: 1.13
8
$'
[
11
:
-
2
]
import
base64
from
cPickle
import
Pickler
,
Unpickler
,
loads
...
...
src/ZODB/POSException.py
View file @
2ed4e009
...
...
@@ -13,7 +13,7 @@
##############################################################################
"""ZODB-defined exceptions
$Id: POSException.py,v 1.2
0 2003/06/10 15:46:31 shane
Exp $"""
$Id: POSException.py,v 1.2
1 2003/10/02 18:17:19 jeremy
Exp $"""
from
types
import
StringType
,
DictType
from
ZODB.utils
import
oid_repr
,
serial_repr
...
...
src/ZODB/TmpStore.py
View file @
2ed4e009
src/ZODB/Transaction.py
View file @
2ed4e009
...
...
@@ -13,7 +13,7 @@
##############################################################################
"""Transaction management
$Id: Transaction.py,v 1.
49 2003/06/10 15:46:31 shane
Exp $
$Id: Transaction.py,v 1.
50 2003/10/02 18:17:19 jeremy
Exp $
"""
import
time
,
sys
,
struct
,
POSException
...
...
src/ZODB/__init__.py
View file @
2ed4e009
...
...
@@ -12,7 +12,7 @@
#
##############################################################################
__version__
=
'3.2
b2
'
__version__
=
'3.2
c1
'
import
sys
import
cPersistence
,
Persistence
...
...
src/ZODB/cPickleCache.c
View file @
2ed4e009
...
...
@@ -90,7 +90,7 @@ process must skip such objects, rather than deactivating them.
static
char
cPickleCache_doc_string
[]
=
"Defines the PickleCache used by ZODB Connection objects.
\n
"
"
\n
"
"$Id: cPickleCache.c,v 1.8
5 2003/05/30 19:20:55
jeremy Exp $
\n
"
;
"$Id: cPickleCache.c,v 1.8
6 2003/10/02 18:17:19
jeremy Exp $
\n
"
;
#define ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;}
#define UNLESS(E) if(!(E))
...
...
@@ -499,6 +499,17 @@ cc_clear(ccobject *self, PyObject *args)
Py_DECREF
(
o
);
}
self
->
ring_lock
=
0
;
/* Free two references to the Connection, which can't be discovered
via garbage collection.
*/
Py_XDECREF
(
self
->
setklassstate
);
self
->
setklassstate
=
NULL
;
Py_XDECREF
(
self
->
jar
);
self
->
jar
=
NULL
;
Py_INCREF
(
Py_None
);
return
Py_None
;
}
...
...
src/ZODB/config.py
View file @
2ed4e009
...
...
@@ -13,7 +13,7 @@
##############################################################################
"""Open database and storage from a configuration.
$Id: config.py,v 1.1
4 2003/09/15 16:29:15
jeremy Exp $"""
$Id: config.py,v 1.1
5 2003/10/02 18:17:19
jeremy Exp $"""
import
os
from
cStringIO
import
StringIO
...
...
src/ZODB/fspack.py
View file @
2ed4e009
...
...
@@ -878,4 +878,3 @@ class FileStoragePacker(FileStorageFormatter):
if
self
.
_lock_counter
%
20
==
0
:
self
.
_commit_lock_acquire
()
return
ipos
src/ZODB/fsrecover.py
View file @
2ed4e009
...
...
@@ -372,4 +372,3 @@ def recover(inp, outp, verbose=0, partial=0, force=0, pack=0):
if
__name__
==
"__main__"
:
main
()
src/ZODB/tests/BasicStorage.py
View file @
2ed4e009
src/ZODB/tests/ConflictResolution.py
View file @
2ed4e009
src/ZODB/tests/Corruption.py
View file @
2ed4e009
src/ZODB/tests/HistoryStorage.py
View file @
2ed4e009
src/ZODB/tests/IteratorStorage.py
View file @
2ed4e009
src/ZODB/tests/LocalStorage.py
View file @
2ed4e009
src/ZODB/tests/MTStorage.py
View file @
2ed4e009
...
...
@@ -96,7 +96,6 @@ class ZODBClientThread(TestThread):
return
root
.
get
(
name
)
except
ConflictError
:
get_transaction
().
abort
()
root
.
_p_jar
.
sync
()
class
StorageClientThread
(
TestThread
):
...
...
src/ZODB/tests/MinPO.py
View file @
2ed4e009
src/ZODB/tests/PackableStorage.py
View file @
2ed4e009
src/ZODB/tests/PersistentStorage.py
View file @
2ed4e009
src/ZODB/tests/ReadOnlyStorage.py
View file @
2ed4e009
src/ZODB/tests/RecoveryStorage.py
View file @
2ed4e009
src/ZODB/tests/RevisionStorage.py
View file @
2ed4e009
src/ZODB/tests/StorageTestBase.py
View file @
2ed4e009
src/ZODB/tests/Synchronization.py
View file @
2ed4e009
src/ZODB/tests/TransactionalUndoStorage.py
View file @
2ed4e009
...
...
@@ -789,5 +789,3 @@ class TransactionalUndoStorage:
self
.
assertEqual
(
d
[
'description'
],
't1'
)
self
.
assertEqual
(
d
[
'k2'
],
'this is transaction metadata'
)
self
.
assertEqual
(
d
[
'user_name'
],
'p3 u3'
)
src/ZODB/tests/TransactionalUndoVersionStorage.py
View file @
2ed4e009
src/ZODB/tests/VersionStorage.py
View file @
2ed4e009
...
...
@@ -528,4 +528,3 @@ class VersionStorage:
cn2
=
db
.
open
(
version
=
"b"
)
rt2
=
cn2
.
root
()
self
.
assertEqual
(
rt2
[
"b"
].
value
.
value
,
"still version"
)
src/ZODB/tests/dangle.py
View file @
2ed4e009
src/ZODB/tests/testCache.py
View file @
2ed4e009
src/ZODB/tests/testConfig.py
View file @
2ed4e009
...
...
@@ -56,6 +56,7 @@ class ZODBConfigTest(ConfigTestBase):
"""
)
def
test_file_config1
(
self
):
import
ZODB.FileStorage
path
=
tempfile
.
mktemp
()
self
.
_test
(
"""
...
...
@@ -65,9 +66,10 @@ class ZODBConfigTest(ConfigTestBase):
</filestorage>
</zodb>
"""
%
path
)
os
.
unlink
(
path
)
ZODB
.
FileStorage
.
cleanup
(
path
)
def
test_file_config2
(
self
):
import
ZODB.FileStorage
path
=
tempfile
.
mktemp
()
cfg
=
"""
<zodb>
...
...
@@ -79,6 +81,7 @@ class ZODBConfigTest(ConfigTestBase):
</zodb>
"""
%
path
self
.
assertRaises
(
ReadOnlyError
,
self
.
_test
,
cfg
)
ZODB
.
FileStorage
.
cleanup
(
path
)
def
test_zeo_config
(
self
):
# We're looking for a port that doesn't exist so a connection attempt
...
...
src/ZODB/tests/testDB.py
View file @
2ed4e009
src/ZODB/tests/testFileStorage.py
View file @
2ed4e009
src/ZODB/tests/testPersistentList.py
View file @
2ed4e009
src/ZODB/tests/testPersistentMapping.py
View file @
2ed4e009
src/ZODB/tests/testRecover.py
View file @
2ed4e009
...
...
@@ -151,5 +151,3 @@ class RecoverTest(unittest.TestCase):
def
test_suite
():
return
unittest
.
makeSuite
(
RecoverTest
)
src/ZODB/tests/testTimeStamp.py
View file @
2ed4e009
src/ZODB/tests/testTransaction.py
View file @
2ed4e009
...
...
@@ -14,7 +14,7 @@
"""
Revision information:
$Id: testTransaction.py,v 1.1
2 2003/01/27 20:29:50 bwarsaw
Exp $
$Id: testTransaction.py,v 1.1
3 2003/10/02 18:17:17 jeremy
Exp $
"""
"""
...
...
src/ZODB/tests/testUtils.py
View file @
2ed4e009
src/ZODB/tests/testZODB.py
View file @
2ed4e009
src/ZODB/tests/testfsIndex.py
View file @
2ed4e009
src/ZODB/transact.py
View file @
2ed4e009
src/ZODB/utils.py
View file @
2ed4e009
...
...
@@ -96,4 +96,3 @@ def oid_repr(oid):
return
repr
(
oid
)
serial_repr
=
oid_repr
src/scripts/README.txt
View file @
2ed4e009
This directory contains a collect of utilities for managing ZODB
This directory contains a collect
ion
of utilities for managing ZODB
databases. Some are more useful than others. If you install ZODB
using distutils ("python setup.py install"), fsdump.py, fstest.py,
repozo.py, and zeopack.py will be installed in /usr/local/bin.
...
...
@@ -7,27 +7,27 @@ Unless otherwise noted, these scripts are invoked with the name of the
Data.fs file as their only argument. Example: checkbtrees.py data.fs.
analyze.py --
A
transaction analyzer for FileStorage
analyze.py --
a
transaction analyzer for FileStorage
Reports on the data in a FileStorage. The report is organized by
class. It shows total data, as well as separate reports for current
and historical revisions of objects.
checkbtrees.py --
Checks BTrees in a FileStorage for corruption.
checkbtrees.py --
checks BTrees in a FileStorage for corruption
Attempts to find all the BTrees contained in a Data.fs
and
calls their
_check() methods.
Attempts to find all the BTrees contained in a Data.fs
,
calls their
_check() methods
, and runs them through BTrees.check.check()
.
fsdump.py --
Summarize FileStorage contents, one line per revision.
fsdump.py --
summarize FileStorage contents, one line per revision
Prints a report of FileStorage contents, with one line for each
transaction and one line for each data record in that transaction.
Includes time stamps, file positions, and class names.
fstest.py --
S
imple consistency checker for FileStorage
fstest.py --
s
imple consistency checker for FileStorage
usage: fstest.py [-v] data.fs
...
...
@@ -46,7 +46,14 @@ possible for the damage to occur only in the part of the file that
stores object pickles. Those errors will go undetected.
netspace.py -- Hackish attempt to report on size of objects
space.py -- report space used by objects in a FileStorage
usage: space.py [-v] data.fs
This ignores revisions and versions.
netspace.py -- hackish attempt to report on size of objects
usage: netspace.py [-P | -v] data.fs
...
...
@@ -57,7 +64,7 @@ Traverses objects from the database root and attempts to calculate
size of object, including all reachable subobjects.
parsezeolog.py --
Parse BLATHER logs from ZEO server.
parsezeolog.py --
parse BLATHER logs from ZEO server
This script may be obsolete. It has not been tested against the
current log output of the ZEO server.
...
...
@@ -66,12 +73,12 @@ Reports on the time and size of transactions committed by a ZEO
server, by inspecting log messages at BLATHER level.
repozo.py --
Incremental backup utility for FileStorage.
repozo.py --
incremental backup utility for FileStorage
Run the script with the -h option to see usage details.
timeout.py --
S
cript to test transaction timeout
timeout.py --
s
cript to test transaction timeout
usage: timeout.py address delay [storage-name]
...
...
@@ -80,13 +87,13 @@ and tpc_vote(), and then sleeps forever. This should trigger the
transaction timeout feature of the server.
zeopack.py --
Script to pack a ZEO server.
zeopack.py --
pack a ZEO server
The script connects to a server and calls pack() on a specific
storage. See the script for usage details.
zeoreplay.py --
Experimental script to replay transactions from a ZEO log.
zeoreplay.py --
experimental script to replay transactions from a ZEO log
Like parsezeolog.py, this may be obsolete because it was written
against an earlier version of the ZEO server. See the script for
...
...
@@ -95,7 +102,7 @@ usage details.
zeoup.py
U
sage: zeoup.py [options]
u
sage: zeoup.py [options]
The test will connect to a ZEO server, load the root object, and
attempt to update the zeoup counter in the root. It will report
...
...
@@ -106,13 +113,34 @@ start a transaction.
See the script for details about the options.
zodbload.py - exercise ZODB under a heavy synthesized Zope-like load
zodbload.py -
-
exercise ZODB under a heavy synthesized Zope-like load
See the module docstring for details. Note that this script requires
Zope. New in ZODB3 3.1.4.
zeoserverlog.py - analyze ZEO server log for performance statistics
zeoserverlog.py -
-
analyze ZEO server log for performance statistics
See the module docstring for details; there are a large number of
options. New in ZODB3 3.1.4.
fsrefs.py -- check FileStorage for dangling references
fstail.py -- display the most recent transactions in a FileStorage
usage: fstail.py [-n nxtn] data.fs
The most recent ntxn transactions are displayed, to stdout.
Optional argument -n specifies ntxn, and defaults to 10.
migrate.py -- do a storage migration and gather statistics
See the module docstring for details.
zeoqueue.py -- report number of clients currently waiting in the ZEO queue
See the module docstring for details.
src/scripts/tests/testfstest.py
View file @
2ed4e009
...
...
@@ -180,4 +180,3 @@ class TestCorruptedFS(unittest.TestCase):
if
__name__
==
"__main__"
:
unittest
.
main
()
src/scripts/tests/testzeopack.py
View file @
2ed4e009
src/scripts/zeoserverlog.py
View file @
2ed4e009
...
...
@@ -140,7 +140,7 @@ Commands:
- wall time to verify
- average miliseconds to verify per object.
$Id: zeoserverlog.py,v 1.
2 2003/09/15 16:29:19
jeremy Exp $
$Id: zeoserverlog.py,v 1.
3 2003/10/02 18:17:26
jeremy Exp $
"""
import
datetime
,
sys
,
re
,
os
...
...
src/scripts/zodbload.py
View file @
2ed4e009
...
...
@@ -88,7 +88,7 @@ Usage: loadmail2 [options]
Specify the mailbox for getting input data.
$Id: zodbload.py,v 1.
2 2003/09/15 16:29:19
jeremy Exp $
$Id: zodbload.py,v 1.
3 2003/10/02 18:17:26
jeremy Exp $
"""
import
mailbox
...
...
src/zLOG/BaseLogger.py
View file @
2ed4e009
...
...
@@ -21,4 +21,3 @@ class BaseLogger:
for
handler
in
self
.
logger
.
handlers
:
if
hasattr
(
handler
,
'reopen'
)
and
callable
(
handler
.
reopen
):
handler
.
reopen
()
src/zLOG/LogHandlers.py
View file @
2ed4e009
...
...
@@ -75,8 +75,3 @@ class StartupHandler(Handler):
for
record
in
self
.
buffer
:
target
.
handle
(
record
)
self
.
buffer
=
[]
src/zLOG/tests/testzLog.py
View file @
2ed4e009
...
...
@@ -17,6 +17,7 @@ import sys
import
tempfile
import
unittest
import
zLOG
import
logging
severity_string
=
{
-
300
:
'TRACE'
,
...
...
@@ -50,13 +51,24 @@ class StupidLogTest(unittest.TestCase):
self
.
wipeEnvironment
()
self
.
path
=
tempfile
.
mktemp
()
self
.
_severity
=
0
# Windows cannot remove a file that's open. The logging code
# keeps the log file open, and I can't find an advertised API
# to tell the logger to close a log file. So here we cheat:
# tearDown() will close and remove all the handlers that pop
# into existence after setUp() runs. This breaks into internals,
# but I couldn't find a sane way to do it.
self
.
handlers
=
logging
.
_handlers
.
keys
()
# capture current handlers
def
tearDown
(
self
):
try
:
# Close and remove all the handlers that came into existence
# since setUp ran.
for
h
in
logging
.
_handlers
.
keys
():
if
h
not
in
self
.
handlers
:
h
.
close
()
del
logging
.
_handlers
[
h
]
os
.
remove
(
self
.
path
)
except
os
.
error
:
pass
self
.
wipeEnvironment
()
zLOG
.
initialize
()
def
setLog
(
self
,
severity
=
0
):
os
.
environ
[
'%s_LOG_FILE'
%
self
.
prefix
]
=
self
.
path
...
...
@@ -111,14 +123,20 @@ class StupidLogTest(unittest.TestCase):
self
.
setLog
()
zLOG
.
LOG
(
"basic"
,
zLOG
.
INFO
,
"summary"
)
f
=
self
.
getLogFile
()
try
:
self
.
verifyEntry
(
f
,
subsys
=
"basic"
,
summary
=
"summary"
)
finally
:
f
.
close
()
def
checkDetail
(
self
):
self
.
setLog
()
zLOG
.
LOG
(
"basic"
,
zLOG
.
INFO
,
"xxx"
,
"this is a detail"
)
f
=
self
.
getLogFile
()
try
:
self
.
verifyEntry
(
f
,
subsys
=
"basic"
,
detail
=
"detail"
)
finally
:
f
.
close
()
def
checkError
(
self
):
self
.
setLog
()
...
...
@@ -131,9 +149,13 @@ class StupidLogTest(unittest.TestCase):
zLOG
.
LOG
(
"basic"
,
zLOG
.
ERROR
,
"raised exception"
,
error
=
err
)
f
=
self
.
getLogFile
()
try
:
self
.
verifyEntry
(
f
,
subsys
=
"basic"
,
summary
=
"summary"
)
self
.
verifyEntry
(
f
,
subsys
=
"basic"
,
severity
=
zLOG
.
ERROR
,
error
=
err
)
finally
:
f
.
close
()
class
EventLogTest
(
StupidLogTest
):
""" Test alternate envvars EVENT_LOG_FILE and EVENT_LOG_SEVERITY """
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment