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
2d5b3dff
Commit
2d5b3dff
authored
Nov 10, 2016
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
5ad44db5
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
38 additions
and
25 deletions
+38
-25
neo/client/app.py
neo/client/app.py
+4
-0
neo/master/app.py
neo/master/app.py
+0
-1
neo/master/backup_app.py
neo/master/backup_app.py
+9
-9
neo/master/handlers/client.py
neo/master/handlers/client.py
+4
-2
neo/storage/handlers/client.py
neo/storage/handlers/client.py
+1
-2
neo/storage/handlers/storage.py
neo/storage/handlers/storage.py
+1
-0
neo/tests/threaded/__init__.py
neo/tests/threaded/__init__.py
+1
-0
neo/tests/threaded/testReplication.py
neo/tests/threaded/testReplication.py
+18
-11
No files found.
neo/client/app.py
View file @
2d5b3dff
...
@@ -330,6 +330,8 @@ class Application(ThreadedApplication):
...
@@ -330,6 +330,8 @@ 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.
...
@@ -350,6 +352,7 @@ class Application(ThreadedApplication):
...
@@ -350,6 +352,7 @@ 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
:
...
@@ -369,6 +372,7 @@ class Application(ThreadedApplication):
...
@@ -369,6 +372,7 @@ 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/master/app.py
View file @
2d5b3dff
...
@@ -522,7 +522,6 @@ class Application(BaseApplication):
...
@@ -522,7 +522,6 @@ class Application(BaseApplication):
tid
=
txn
.
getTID
()
tid
=
txn
.
getTID
()
transaction_node
=
txn
.
getNode
()
transaction_node
=
txn
.
getNode
()
invalidate_objects
=
Packets
.
InvalidateObjects
(
tid
,
txn
.
getOIDList
())
invalidate_objects
=
Packets
.
InvalidateObjects
(
tid
,
txn
.
getOIDList
())
# NOTE send invalidation to clients
for
client_node
in
self
.
nm
.
getClientList
(
only_identified
=
True
):
for
client_node
in
self
.
nm
.
getClientList
(
only_identified
=
True
):
c
=
client_node
.
getConnection
()
c
=
client_node
.
getConnection
()
if
client_node
is
transaction_node
:
if
client_node
is
transaction_node
:
...
...
neo/master/backup_app.py
View file @
2d5b3dff
# -*- coding: utf-8 -*-
#
#
# Copyright (C) 2012-2016 Nexedi SA
# Copyright (C) 2012-2016 Nexedi SA
#
#
...
@@ -95,7 +96,7 @@ class BackupApplication(object):
...
@@ -95,7 +96,7 @@ class BackupApplication(object):
bootstrap
=
BootstrapManager
(
self
,
self
.
name
,
NodeTypes
.
CLIENT
)
bootstrap
=
BootstrapManager
(
self
,
self
.
name
,
NodeTypes
.
CLIENT
)
# {offset -> node} (primary storage for off which will be talking to upstream cluster)
# {offset -> node} (primary storage for off which will be talking to upstream cluster)
self
.
primary_partition_dict
=
{}
self
.
primary_partition_dict
=
{}
# [[tid]]
# [[tid]]
part -> []tid↑ (currently scheduled-for-sync txns)
self
.
tid_list
=
tuple
([]
for
_
in
xrange
(
pt
.
getPartitions
()))
self
.
tid_list
=
tuple
([]
for
_
in
xrange
(
pt
.
getPartitions
()))
try
:
try
:
while
True
:
while
True
:
...
@@ -208,13 +209,12 @@ class BackupApplication(object):
...
@@ -208,13 +209,12 @@ class BackupApplication(object):
except
IndexError
:
except
IndexError
:
last_max_tid
=
prev_tid
last_max_tid
=
prev_tid
if
offset
in
partition_set
:
if
offset
in
partition_set
:
self
.
tid_list
[
offset
].
append
(
tid
)
self
.
tid_list
[
offset
].
append
(
tid
)
# XXX check tid is ↑
node_list
=
[]
node_list
=
[]
for
cell
in
pt
.
getCellList
(
offset
,
readable
=
True
):
for
cell
in
pt
.
getCellList
(
offset
,
readable
=
True
):
node
=
cell
.
getNode
()
node
=
cell
.
getNode
()
assert
node
.
isConnected
(),
node
assert
node
.
isConnected
(),
node
if
cell
.
backup_tid
==
prev_tid
:
if
cell
.
backup_tid
==
prev_tid
:
"""
# Let's given 4 TID t0,t1,t2,t3: if a cell is only
# Let's given 4 TID t0,t1,t2,t3: if a cell is only
# modified by t0 & t3 and has all data for t0, 4 values
# modified by t0 & t3 and has all data for t0, 4 values
# are possible for its 'backup_tid' until it replicates
# are possible for its 'backup_tid' until it replicates
...
@@ -229,8 +229,6 @@ class BackupApplication(object):
...
@@ -229,8 +229,6 @@ class BackupApplication(object):
logging
.
debug
(
logging
.
debug
(
"partition %u: updating backup_tid of %r to %s"
,
"partition %u: updating backup_tid of %r to %s"
,
offset
,
cell
,
dump
(
cell
.
backup_tid
))
offset
,
cell
,
dump
(
cell
.
backup_tid
))
"""
pass
else
:
else
:
assert
cell
.
backup_tid
<
last_max_tid
,
(
assert
cell
.
backup_tid
<
last_max_tid
,
(
cell
.
backup_tid
,
last_max_tid
,
prev_tid
,
tid
)
cell
.
backup_tid
,
last_max_tid
,
prev_tid
,
tid
)
...
@@ -301,13 +299,13 @@ class BackupApplication(object):
...
@@ -301,13 +299,13 @@ class BackupApplication(object):
app
=
self
.
app
app
=
self
.
app
cell
=
app
.
pt
.
getCell
(
offset
,
node
.
getUUID
())
cell
=
app
.
pt
.
getCell
(
offset
,
node
.
getUUID
())
tid_list
=
self
.
tid_list
[
offset
]
tid_list
=
self
.
tid_list
[
offset
]
if
tid_list
:
# may be empty if the cell is out-of-date
if
tid_list
:
# may be empty if the cell is out-of-date
# XXX check how
# or if we're not fully initialized
# or if we're not fully initialized
if
tid
<
tid_list
[
0
]:
if
tid
<
tid_list
[
0
]:
# XXX why this is possible?
cell
.
replicating
=
tid
cell
.
replicating
=
tid
else
:
else
:
try
:
try
:
tid
=
add64
(
tid_list
[
bisect
(
tid_list
,
tid
)],
-
1
)
tid
=
add64
(
tid_list
[
bisect
(
tid_list
,
tid
)],
-
1
)
# XXX why -1 ?
except
IndexError
:
except
IndexError
:
last_tid
=
app
.
getLastTransaction
()
last_tid
=
app
.
getLastTransaction
()
if
tid
<
last_tid
:
if
tid
<
last_tid
:
...
@@ -316,9 +314,11 @@ class BackupApplication(object):
...
@@ -316,9 +314,11 @@ class BackupApplication(object):
logging
.
debug
(
"partition %u: updating backup_tid of %r to %s"
,
logging
.
debug
(
"partition %u: updating backup_tid of %r to %s"
,
offset
,
cell
,
dump
(
tid
))
offset
,
cell
,
dump
(
tid
))
cell
.
backup_tid
=
tid
cell
.
backup_tid
=
tid
# TODO provide invalidation feedback about new txns to read-only clients connected to backup cluster
# NOTE ^^^ not only here but also hooked to in-progress feedback from fetchObjects (storage)
# Forget tids we won't need anymore.
# Forget tids we won't need anymore.
cell_list
=
app
.
pt
.
getCellList
(
offset
,
readable
=
True
)
cell_list
=
app
.
pt
.
getCellList
(
offset
,
readable
=
True
)
del
tid_list
[:
bisect
(
tid_list
,
min
(
x
.
backup_tid
for
x
in
cell_list
))]
del
tid_list
[:
bisect
(
tid_list
,
min
(
x
.
backup_tid
for
x
in
cell_list
))]
# XXX not only for primary Sb ?
primary_node
=
self
.
primary_partition_dict
.
get
(
offset
)
primary_node
=
self
.
primary_partition_dict
.
get
(
offset
)
primary
=
primary_node
is
node
primary
=
primary_node
is
node
result
=
None
if
primary
else
app
.
pt
.
setUpToDate
(
node
,
offset
)
result
=
None
if
primary
else
app
.
pt
.
setUpToDate
(
node
,
offset
)
...
...
neo/master/handlers/client.py
View file @
2d5b3dff
...
@@ -120,7 +120,6 @@ class ClientServiceHandler(MasterHandler):
...
@@ -120,7 +120,6 @@ class ClientServiceHandler(MasterHandler):
# like ClientServiceHandler but read-only & only for tid <= backup_tid
# like ClientServiceHandler but read-only & only for tid <= backup_tid
# XXX naming -> (?) ClientReadOnlyHandler
class
ClientROServiceHandler
(
ClientServiceHandler
):
class
ClientROServiceHandler
(
ClientServiceHandler
):
# XXX somehow make sure to propagate this to raiseReadOnlyError() on client ?
# XXX somehow make sure to propagate this to raiseReadOnlyError() on client ?
...
@@ -139,6 +138,9 @@ class ClientROServiceHandler(ClientServiceHandler):
...
@@ -139,6 +138,9 @@ class ClientROServiceHandler(ClientServiceHandler):
# like in MasterHandler but returns backup_tid instead of last_tid
# like in MasterHandler but returns backup_tid instead of last_tid
def
askLastTransaction
(
self
,
conn
):
def
askLastTransaction
(
self
,
conn
):
backup_tid
=
self
.
app
.
backup_tid
# XXX wrong vvv
backup_tid
=
self
.
app
.
backup_tid
# FIXME this is not regularly updated - only on request from outside ?
# XXX yes -> see askRecovery in master/handlers/
assert
backup_tid
is
not
None
# in BACKUPING mode it is always set
assert
backup_tid
is
not
None
# in BACKUPING mode it is always set
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 @
2d5b3dff
...
@@ -231,7 +231,6 @@ class ClientOperationHandler(EventHandler):
...
@@ -231,7 +231,6 @@ class ClientOperationHandler(EventHandler):
# like ClientOperationHandler but read-only & only for tid <= backup_tid
# like ClientOperationHandler but read-only & only for tid <= backup_tid
# XXX naming -> ClientReadOnlyHandler ?
class
ClientROOperationHandler
(
ClientOperationHandler
):
class
ClientROOperationHandler
(
ClientOperationHandler
):
def
_readOnly
(
self
,
*
args
,
**
kw
):
raise
NotReadyError
(
'read-only access'
)
def
_readOnly
(
self
,
*
args
,
**
kw
):
raise
NotReadyError
(
'read-only access'
)
...
@@ -255,8 +254,8 @@ class ClientROOperationHandler(ClientOperationHandler):
...
@@ -255,8 +254,8 @@ class ClientROOperationHandler(ClientOperationHandler):
super
(
ClientROOperationHandler
,
self
).
askTransactionInformation
(
conn
,
tid
)
super
(
ClientROOperationHandler
,
self
).
askTransactionInformation
(
conn
,
tid
)
def
askObject
(
self
,
conn
,
oid
,
serial
,
tid
):
def
askObject
(
self
,
conn
,
oid
,
serial
,
tid
):
print
'
\
n
\
n
\
n
ASK OBJECT %r, %r, %r
\
n
\
n
\
n
'
%
(
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)
\
n
\
n
\
n
'
%
(
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
...
...
neo/storage/handlers/storage.py
View file @
2d5b3dff
...
@@ -105,6 +105,7 @@ class StorageOperationHandler(EventHandler):
...
@@ -105,6 +105,7 @@ class StorageOperationHandler(EventHandler):
self
.
app
.
dm
.
commit
()
self
.
app
.
dm
.
commit
()
assert
not
pack_tid
,
"TODO"
assert
not
pack_tid
,
"TODO"
if
next_tid
:
if
next_tid
:
# TODO also provide feedback to master about current replication state (tid)
self
.
app
.
replicator
.
fetchObjects
(
next_tid
,
next_oid
)
self
.
app
.
replicator
.
fetchObjects
(
next_tid
,
next_oid
)
else
:
else
:
self
.
app
.
replicator
.
finish
()
self
.
app
.
replicator
.
finish
()
...
...
neo/tests/threaded/__init__.py
View file @
2d5b3dff
...
@@ -750,6 +750,7 @@ class NEOCluster(object):
...
@@ -750,6 +750,7 @@ class NEOCluster(object):
self
.
enableStorageList
(
storage_list
)
self
.
enableStorageList
(
storage_list
)
def
newClient
(
self
):
def
newClient
(
self
):
print
'%r: newClient()'
%
self
return
ClientApplication
(
name
=
self
.
name
,
master_nodes
=
self
.
master_nodes
,
return
ClientApplication
(
name
=
self
.
name
,
master_nodes
=
self
.
master_nodes
,
compress
=
self
.
compress
,
ssl
=
self
.
SSL
)
compress
=
self
.
compress
,
ssl
=
self
.
SSL
)
...
...
neo/tests/threaded/testReplication.py
View file @
2d5b3dff
...
@@ -525,8 +525,8 @@ class ReplicationTests(NEOThreadedTest):
...
@@ -525,8 +525,8 @@ class ReplicationTests(NEOThreadedTest):
"""Check data can be read from backup cluster by clients"""
"""Check data can be read from backup cluster by clients"""
B
=
backup
B
=
backup
U
=
B
.
upstream
U
=
B
.
upstream
S
=
U
.
getZODBStorage
()
Z
=
U
.
getZODBStorage
()
S
b
=
B
.
getZODBStorage
()
#Z
b = B.getZODBStorage()
oid_list
=
[]
oid_list
=
[]
tid_list
=
[]
tid_list
=
[]
...
@@ -534,11 +534,11 @@ class ReplicationTests(NEOThreadedTest):
...
@@ -534,11 +534,11 @@ class ReplicationTests(NEOThreadedTest):
for
i
in
xrange
(
10
):
for
i
in
xrange
(
10
):
# store new data to U
# store new data to U
txn
=
transaction
.
Transaction
()
txn
=
transaction
.
Transaction
()
S
.
tpc_begin
(
txn
)
Z
.
tpc_begin
(
txn
)
oid
=
S
.
new_oid
()
oid
=
Z
.
new_oid
()
S
.
store
(
oid
,
None
,
'%s-%i'
%
(
oid
,
i
),
''
,
txn
)
Z
.
store
(
oid
,
None
,
'%s-%i'
%
(
oid
,
i
),
''
,
txn
)
S
.
tpc_vote
(
txn
)
Z
.
tpc_vote
(
txn
)
tid
=
S
.
tpc_finish
(
txn
)
tid
=
Z
.
tpc_finish
(
txn
)
oid_list
.
append
(
oid
)
oid_list
.
append
(
oid
)
tid_list
.
append
(
tid
)
tid_list
.
append
(
tid
)
...
@@ -548,13 +548,20 @@ class ReplicationTests(NEOThreadedTest):
...
@@ -548,13 +548,20 @@ class ReplicationTests(NEOThreadedTest):
self
.
assertEqual
(
B
.
last_tid
,
U
.
last_tid
)
self
.
assertEqual
(
B
.
last_tid
,
U
.
last_tid
)
self
.
assertEqual
(
1
,
self
.
checkBackup
(
B
))
self
.
assertEqual
(
1
,
self
.
checkBackup
(
B
))
print
'
\
n
\
n
111 tid: %r, last_tid: %r, backup_tid: %r'
%
(
tid
,
B
.
backup_tid
,
U
.
last_tid
)
# try to read data from B
# try to read data from B
Sb
.
_cache
.
clear
()
# XXX we open new storage every time becasue invalidations are not yet implemented in read-only mode.
Zb
=
B
.
getZODBStorage
()
#Zb.sync()
#Zb._cache.clear()
for
j
,
oid
in
enumerate
(
oid_list
):
for
j
,
oid
in
enumerate
(
oid_list
):
data
=
S
b
.
load
(
oid
,
''
)
data
=
Z
b
.
load
(
oid
,
''
)
self
.
assertEqual
(
data
,
'%s-%s'
%
(
oid
,
j
))
self
.
assertEqual
(
data
,
'%s-%s'
%
(
oid
,
j
))
#Sb.loadSerial(oid, tid)
#Zb.loadSerial(oid, tid)
#Sb.loadBefore(oid, tid)
#Zb.loadBefore(oid, tid)
# TODO close Zb / client
if
__name__
==
"__main__"
:
if
__name__
==
"__main__"
:
unittest
.
main
()
unittest
.
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