Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
N
neoppod
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
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Levin Zimmermann
neoppod
Commits
d48930fe
Commit
d48930fe
authored
Nov 10, 2016
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
48aa3a91
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
82 additions
and
62 deletions
+82
-62
neo/client/Storage.py
neo/client/Storage.py
+1
-2
neo/client/app.py
neo/client/app.py
+0
-4
neo/lib/logger.py
neo/lib/logger.py
+0
-4
neo/lib/protocol.py
neo/lib/protocol.py
+1
-2
neo/master/handlers/client.py
neo/master/handlers/client.py
+0
-1
neo/storage/handlers/client.py
neo/storage/handlers/client.py
+0
-3
neo/tests/threaded/testReplication.py
neo/tests/threaded/testReplication.py
+80
-46
No files found.
neo/client/Storage.py
View file @
d48930fe
...
@@ -81,8 +81,7 @@ class Storage(BaseStorage.BaseStorage,
...
@@ -81,8 +81,7 @@ class Storage(BaseStorage.BaseStorage,
try
:
try
:
return
self
.
app
.
load
(
oid
)[:
2
]
return
self
.
app
.
load
(
oid
)[:
2
]
except
NEOStorageNotFoundError
:
except
NEOStorageNotFoundError
:
raise
raise
POSException
.
POSKeyError
(
oid
)
#raise POSException.POSKeyError(oid)
def
new_oid
(
self
):
def
new_oid
(
self
):
return
self
.
app
.
new_oid
()
return
self
.
app
.
new_oid
()
...
...
neo/client/app.py
View file @
d48930fe
...
@@ -330,8 +330,6 @@ class Application(ThreadedApplication):
...
@@ -330,8 +330,6 @@ class Application(ThreadedApplication):
# TODO:
# TODO:
# - rename parameters (here? and in handlers & packet definitions)
# - rename parameters (here? and in handlers & packet definitions)
print
'QQQ client load oid: %r tid: %r before_tid: %r'
%
(
oid
,
tid
,
before_tid
)
acquire
=
self
.
_cache_lock_acquire
acquire
=
self
.
_cache_lock_acquire
release
=
self
.
_cache_lock_release
release
=
self
.
_cache_lock_release
# XXX: Consider using a more fine-grained lock.
# XXX: Consider using a more fine-grained lock.
...
@@ -352,7 +350,6 @@ class Application(ThreadedApplication):
...
@@ -352,7 +350,6 @@ class Application(ThreadedApplication):
# Do not get something more recent than the last invalidation
# Do not get something more recent than the last invalidation
# we got from master.
# we got from master.
before_tid
=
p64
(
u64
(
self
.
last_tid
)
+
1
)
before_tid
=
p64
(
u64
(
self
.
last_tid
)
+
1
)
print
'
\
t
.last_tid: %r'
%
self
.
last_tid
data
,
tid
,
next_tid
,
_
=
self
.
_loadFromStorage
(
oid
,
tid
,
before_tid
)
data
,
tid
,
next_tid
,
_
=
self
.
_loadFromStorage
(
oid
,
tid
,
before_tid
)
acquire
()
acquire
()
try
:
try
:
...
@@ -372,7 +369,6 @@ class Application(ThreadedApplication):
...
@@ -372,7 +369,6 @@ class Application(ThreadedApplication):
return
data
,
tid
,
next_tid
return
data
,
tid
,
next_tid
def
_loadFromStorage
(
self
,
oid
,
at_tid
,
before_tid
):
def
_loadFromStorage
(
self
,
oid
,
at_tid
,
before_tid
):
print
'QQQ2 client loadFromStor oid: %r at_tid: %r before_tid: %r'
%
(
oid
,
at_tid
,
before_tid
)
packet
=
Packets
.
AskObject
(
oid
,
at_tid
,
before_tid
)
packet
=
Packets
.
AskObject
(
oid
,
at_tid
,
before_tid
)
for
node
,
conn
in
self
.
cp
.
iterateForObject
(
oid
,
readable
=
True
):
for
node
,
conn
in
self
.
cp
.
iterateForObject
(
oid
,
readable
=
True
):
try
:
try
:
...
...
neo/lib/logger.py
View file @
d48930fe
...
@@ -28,7 +28,6 @@ from logging import getLogger, Formatter, Logger, StreamHandler, \
...
@@ -28,7 +28,6 @@ from logging import getLogger, Formatter, Logger, StreamHandler, \
from
time
import
time
from
time
import
time
from
traceback
import
format_exception
from
traceback
import
format_exception
import
bz2
,
inspect
,
neo
,
os
,
signal
,
sqlite3
,
sys
,
threading
import
bz2
,
inspect
,
neo
,
os
,
signal
,
sqlite3
,
sys
,
threading
from
cStringIO
import
StringIO
# Stats for storage node of matrix test (py2.7:SQLite)
# Stats for storage node of matrix test (py2.7:SQLite)
RECORD_SIZE
=
(
234360832
# extra memory used
RECORD_SIZE
=
(
234360832
# extra memory used
...
@@ -226,13 +225,10 @@ class NEOLogger(Logger):
...
@@ -226,13 +225,10 @@ class NEOLogger(Logger):
uuid_str
(
r
.
uuid
),
ip
,
port
)
uuid_str
(
r
.
uuid
),
ip
,
port
)
msg
=
r
.
msg
msg
=
r
.
msg
pktcls
=
protocol
.
StaticRegistry
[
r
.
code
]
pktcls
=
protocol
.
StaticRegistry
[
r
.
code
]
#bmsg = StringIO(msg)
#hmsg = protocol.Packets.parse(bmsg, protocol.ParserState())
print
'PACKET %s %s
\
t
%s
\
t
%s
\
t
%s %s'
%
(
r
.
created
,
r
.
_name
,
r
.
msg_id
,
print
'PACKET %s %s
\
t
%s
\
t
%s
\
t
%s %s'
%
(
r
.
created
,
r
.
_name
,
r
.
msg_id
,
pktcls
.
__name__
,
peer
,
r
.
pkt
.
decode
())
pktcls
.
__name__
,
peer
,
r
.
pkt
.
decode
())
if
msg
is
not
None
:
if
msg
is
not
None
:
msg
=
buffer
(
msg
)
msg
=
buffer
(
msg
)
self
.
_db
.
execute
(
"INSERT INTO packet VALUES (NULL,?,?,?,?,?,?)"
,
self
.
_db
.
execute
(
"INSERT INTO packet VALUES (NULL,?,?,?,?,?,?)"
,
(
r
.
created
,
r
.
_name
,
r
.
msg_id
,
r
.
code
,
peer
,
msg
))
(
r
.
created
,
r
.
_name
,
r
.
msg_id
,
r
.
code
,
peer
,
msg
))
else
:
else
:
...
...
neo/lib/protocol.py
View file @
d48930fe
...
@@ -75,7 +75,7 @@ def ErrorCodes():
...
@@ -75,7 +75,7 @@ def ErrorCodes():
REPLICATION_ERROR
REPLICATION_ERROR
CHECKING_ERROR
CHECKING_ERROR
BACKEND_NOT_IMPLEMENTED
BACKEND_NOT_IMPLEMENTED
READ_ONLY_ACCESS
# TODO use it
READ_ONLY_ACCESS
@
Enum
@
Enum
def
ClusterStates
():
def
ClusterStates
():
...
@@ -1400,7 +1400,6 @@ class NotifyReady(Packet):
...
@@ -1400,7 +1400,6 @@ class NotifyReady(Packet):
"""
"""
pass
pass
# NOTE
# replication
# replication
class
FetchTransactions
(
Packet
):
class
FetchTransactions
(
Packet
):
...
...
neo/master/handlers/client.py
View file @
d48930fe
...
@@ -142,5 +142,4 @@ class ClientROServiceHandler(ClientServiceHandler):
...
@@ -142,5 +142,4 @@ class ClientROServiceHandler(ClientServiceHandler):
def
askLastTransaction
(
self
,
conn
):
def
askLastTransaction
(
self
,
conn
):
assert
self
.
app
.
backup_tid
is
not
None
# we are in BACKUPING mode
assert
self
.
app
.
backup_tid
is
not
None
# we are in BACKUPING mode
backup_tid
=
self
.
app
.
pt
.
getBackupTid
()
backup_tid
=
self
.
app
.
pt
.
getBackupTid
()
print
'
\
n
\
n
\
n
ASK LAST_TID -> %r
\
n
'
%
backup_tid
conn
.
answer
(
Packets
.
AnswerLastTransaction
(
backup_tid
))
conn
.
answer
(
Packets
.
AnswerLastTransaction
(
backup_tid
))
neo/storage/handlers/client.py
View file @
d48930fe
...
@@ -257,7 +257,6 @@ class ClientROOperationHandler(ClientOperationHandler):
...
@@ -257,7 +257,6 @@ class ClientROOperationHandler(ClientOperationHandler):
def
askObject
(
self
,
conn
,
oid
,
serial
,
tid
):
def
askObject
(
self
,
conn
,
oid
,
serial
,
tid
):
backup_tid
=
self
.
app
.
dm
.
getBackupTID
()
backup_tid
=
self
.
app
.
dm
.
getBackupTID
()
print
'
\
n
\
n
\
n
ASK OBJECT %r, %r, %r (backup_tid: %r)'
%
(
oid
,
serial
,
tid
,
backup_tid
)
if
serial
and
serial
>
backup_tid
:
if
serial
and
serial
>
backup_tid
:
# obj lookup will find nothing, but return properly either
# obj lookup will find nothing, but return properly either
# OidDoesNotExist or OidNotFound
# OidDoesNotExist or OidNotFound
...
@@ -269,9 +268,7 @@ class ClientROOperationHandler(ClientOperationHandler):
...
@@ -269,9 +268,7 @@ class ClientROOperationHandler(ClientOperationHandler):
if
not
serial
and
not
tid
:
if
not
serial
and
not
tid
:
tid
=
add64
(
backup_tid
,
1
)
tid
=
add64
(
backup_tid
,
1
)
print
'-> asking as oid: %r serial: %r tid: %r'
%
(
oid
,
serial
,
tid
)
super
(
ClientROOperationHandler
,
self
).
askObject
(
conn
,
oid
,
serial
,
tid
)
super
(
ClientROOperationHandler
,
self
).
askObject
(
conn
,
oid
,
serial
,
tid
)
print
'(ask object done)'
def
askTIDsFrom
(
self
,
conn
,
min_tid
,
max_tid
,
length
,
partition
):
def
askTIDsFrom
(
self
,
conn
,
min_tid
,
max_tid
,
length
,
partition
):
backup_tid
=
self
.
app
.
dm
.
getBackupTID
()
backup_tid
=
self
.
app
.
dm
.
getBackupTID
()
...
...
neo/tests/threaded/testReplication.py
View file @
d48930fe
...
@@ -19,10 +19,12 @@ from logging import getLogger, INFO, DEBUG
...
@@ -19,10 +19,12 @@ from logging import getLogger, INFO, DEBUG
import
random
import
random
import
time
import
time
import
transaction
import
transaction
from
ZODB.POSException
import
ReadOnlyError
,
POSKeyError
import
unittest
import
unittest
from
collections
import
defaultdict
from
collections
import
defaultdict
from
functools
import
wraps
from
functools
import
wraps
from
neo.lib
import
logging
from
neo.lib
import
logging
from
neo.client.exception
import
NEOStorageError
from
neo.storage.checker
import
CHECK_COUNT
from
neo.storage.checker
import
CHECK_COUNT
from
neo.storage.replicator
import
Replicator
from
neo.storage.replicator
import
Replicator
from
neo.lib.connector
import
SocketConnector
from
neo.lib.connector
import
SocketConnector
...
@@ -34,9 +36,6 @@ from neo.lib.util import p64
...
@@ -34,9 +36,6 @@ from neo.lib.util import p64
from
..
import
Patch
from
..
import
Patch
from
.
import
ConnectionFilter
,
NEOCluster
,
NEOThreadedTest
,
predictable_random
from
.
import
ConnectionFilter
,
NEOCluster
,
NEOThreadedTest
,
predictable_random
from
ZODB.POSException
import
ReadOnlyError
from
neo.client.exception
import
NEOStorageError
# dump log to stderr
# dump log to stderr
logging
.
backlog
(
max_size
=
None
)
logging
.
backlog
(
max_size
=
None
)
del
logging
.
default_root_handler
.
handle
del
logging
.
default_root_handler
.
handle
...
@@ -523,7 +522,7 @@ class ReplicationTests(NEOThreadedTest):
...
@@ -523,7 +522,7 @@ class ReplicationTests(NEOThreadedTest):
@
backup_test
()
@
backup_test
()
def
testBackupReadAccess
(
self
,
backup
):
def
testBackupRead
Only
Access
(
self
,
backup
):
"""Check backup cluster can be used in read-only mode by ZODB clients"""
"""Check backup cluster can be used in read-only mode by ZODB clients"""
B
=
backup
B
=
backup
U
=
B
.
upstream
U
=
B
.
upstream
...
@@ -533,48 +532,83 @@ class ReplicationTests(NEOThreadedTest):
...
@@ -533,48 +532,83 @@ class ReplicationTests(NEOThreadedTest):
oid_list
=
[]
oid_list
=
[]
tid_list
=
[]
tid_list
=
[]
for
i
in
xrange
(
10
):
# S -> Sb link stops working during [cutoff, recover) test iterations
# commit new data to U
cutoff
=
4
txn
=
transaction
.
Transaction
()
recover
=
7
Z
.
tpc_begin
(
txn
)
def
delayReplication
(
conn
,
packet
):
oid
=
Z
.
new_oid
()
return
isinstance
(
packet
,
Packets
.
AnswerFetchTransactions
)
Z
.
store
(
oid
,
None
,
'%s-%i'
%
(
oid
,
i
),
''
,
txn
)
Z
.
tpc_vote
(
txn
)
with
ConnectionFilter
()
as
f
:
tid
=
Z
.
tpc_finish
(
txn
)
for
i
in
xrange
(
10
):
oid_list
.
append
(
oid
)
if
i
==
cutoff
:
tid_list
.
append
(
tid
)
f
.
add
(
delayReplication
)
if
i
==
recover
:
# make sure data propagated to B
# removes the filter and retransmits all packets that were
self
.
tic
()
# queued once first filtered packed was detected on a connection.
self
.
assertEqual
(
B
.
backup_tid
,
U
.
last_tid
)
f
.
remove
(
delayReplication
)
self
.
assertEqual
(
B
.
last_tid
,
U
.
last_tid
)
self
.
assertEqual
(
1
,
self
.
checkBackup
(
B
))
# commit new data to U
txn
=
transaction
.
Transaction
()
# read data from B and verify it is what it should be
txn
.
note
(
'test transaction %i'
%
i
)
# XXX we open new storage every time because invalidations are not
Z
.
tpc_begin
(
txn
)
# yet implemented in read-only mode.
oid
=
Z
.
new_oid
()
Zb
=
B
.
getZODBStorage
()
Z
.
store
(
oid
,
None
,
'%s-%i'
%
(
oid
,
i
),
''
,
txn
)
for
j
,
oid
in
enumerate
(
oid_list
):
Z
.
tpc_vote
(
txn
)
data
,
serial
=
Zb
.
load
(
oid
,
''
)
tid
=
Z
.
tpc_finish
(
txn
)
self
.
assertEqual
(
data
,
'%s-%s'
%
(
oid
,
j
))
oid_list
.
append
(
oid
)
self
.
assertEqual
(
serial
,
tid_list
[
j
])
tid_list
.
append
(
tid
)
# close storage because client app is otherwise shared in threaded
# make sure data propagated to B
# tests and we need to refresh last_tid on next run
self
.
tic
()
# (see above about invalidations not working)
if
cutoff
<=
i
<
recover
:
Zb
.
close
()
self
.
assertLess
(
B
.
backup_tid
,
U
.
last_tid
)
else
:
# try to commit something to backup storage and make sure it is really read-only
self
.
assertEqual
(
B
.
backup_tid
,
U
.
last_tid
)
Zb
=
B
.
getZODBStorage
()
self
.
assertEqual
(
B
.
last_tid
,
U
.
last_tid
)
Zb
.
_cache
.
_max_size
=
0
# make stores do work in sync way
self
.
assertEqual
(
1
,
self
.
checkBackup
(
B
,
max_tid
=
B
.
backup_tid
))
txn
=
transaction
.
Transaction
()
self
.
assertRaises
(
ReadOnlyError
,
Zb
.
tpc_begin
,
txn
)
# read data from B and verify it is what it should be
self
.
assertRaises
(
ReadOnlyError
,
Zb
.
new_oid
)
# XXX we open new ZODB storage every time because invalidations
self
.
assertRaises
(
ReadOnlyError
,
Zb
.
store
,
oid_list
[
-
1
],
tid_list
[
-
1
],
'somedata'
,
''
,
txn
)
# are not yet implemented in read-only mode.
# tpc_vote first checks whether there were store replies - thus not ReadOnlyError
Zb
=
B
.
getZODBStorage
()
self
.
assertRaises
(
NEOStorageError
,
Zb
.
tpc_vote
,
txn
)
for
j
,
oid
in
enumerate
(
oid_list
):
if
cutoff
<=
i
<
recover
and
j
>=
cutoff
:
Zb
.
close
()
self
.
assertRaises
(
POSKeyError
,
Zb
.
load
,
oid
,
''
)
else
:
data
,
serial
=
Zb
.
load
(
oid
,
''
)
self
.
assertEqual
(
data
,
'%s-%s'
%
(
oid
,
j
))
self
.
assertEqual
(
serial
,
tid_list
[
j
])
# verify how transaction log & friends behave under potentially not-yet-fully
# fetched backup state (transactions committed at [cutoff, recover) should
# not be there; otherwise transactions should be fully there)
Zb
=
B
.
getZODBStorage
()
Btxn_list
=
list
(
Zb
.
iterator
())
self
.
assertEqual
(
len
(
Btxn_list
),
cutoff
if
cutoff
<=
i
<
recover
else
i
+
1
)
for
j
,
txn
in
enumerate
(
Btxn_list
):
self
.
assertEqual
(
txn
.
tid
,
tid_list
[
j
])
self
.
assertEqual
(
txn
.
description
,
'test transaction %i'
%
j
)
obj_list
=
list
(
txn
)
self
.
assertEqual
(
len
(
obj_list
),
1
)
obj
=
obj_list
[
0
]
self
.
assertEqual
(
obj
.
oid
,
oid_list
[
j
])
self
.
assertEqual
(
obj
.
data
,
'%s-%s'
%
(
obj
.
oid
,
j
))
# TODO test askObjectHistory once it is fixed
# try to commit something to backup storage and make sure it is really read-only
Zb
.
_cache
.
_max_size
=
0
# make stores do work in sync way
txn
=
transaction
.
Transaction
()
self
.
assertRaises
(
ReadOnlyError
,
Zb
.
tpc_begin
,
txn
)
self
.
assertRaises
(
ReadOnlyError
,
Zb
.
new_oid
)
self
.
assertRaises
(
ReadOnlyError
,
Zb
.
store
,
oid_list
[
-
1
],
tid_list
[
-
1
],
'somedata'
,
''
,
txn
)
# tpc_vote first checks whether there were store replies - thus not ReadOnlyError
self
.
assertRaises
(
NEOStorageError
,
Zb
.
tpc_vote
,
txn
)
# close storage because client app is otherwise shared in threaded
# tests and we need to refresh last_tid on next run
# (see above about invalidations not working)
Zb
.
close
()
if
__name__
==
"__main__"
:
if
__name__
==
"__main__"
:
...
...
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