Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
erp5
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
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Eteri
erp5
Commits
78cb52bc
Commit
78cb52bc
authored
Mar 14, 2013
by
Aurel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
implement deletion of object (works for asynchronous engine only for now)
parent
de2b6575
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
62 additions
and
43 deletions
+62
-43
product/ERP5SyncML/Document/SyncMLSubscription.py
product/ERP5SyncML/Document/SyncMLSubscription.py
+20
-40
product/ERP5SyncML/Engine/AsynchronousEngine.py
product/ERP5SyncML/Engine/AsynchronousEngine.py
+10
-3
product/ERP5SyncML/Tool/SynchronizationTool.py
product/ERP5SyncML/Tool/SynchronizationTool.py
+32
-0
No files found.
product/ERP5SyncML/Document/SyncMLSubscription.py
View file @
78cb52bc
...
...
@@ -97,8 +97,7 @@ class SyncMLSubscription(XMLObject):
self
.
_edit
(
authenticated_user
=
None
)
security
.
declarePrivate
(
'getAndActivate'
)
def
getAndActivate
(
self
,
callback
,
method_kw
,
activate_kw
,
final_activate_kw
,
**
kw
):
def
getAndActivate
(
self
,
callback
,
method_kw
,
activate_kw
,
**
kw
):
"""
This methods is called by the asynchronous engine to split activity
generation into activities.
...
...
@@ -106,7 +105,6 @@ class SyncMLSubscription(XMLObject):
callback : method to call in activity
method_kw : callback's parameters
activate_kw : activity parameters to pass to activate call
final_activate_kw : activity parameters to pass to the last activate call
kw : any parameter getAndActivate can required if it calls itself
Last activate must wait for all other activities to be processed in order
...
...
@@ -141,7 +139,7 @@ class SyncMLSubscription(XMLObject):
(
kw
[
"min_id"
],))
self
.
activate
(
**
next_kw
).
getAndActivate
(
callback
,
method_kw
,
activate_kw
,
final_activate_kw
,
**
kw
)
callback
,
method_kw
,
activate_kw
,
**
kw
)
generated_other_activity
=
True
r
=
[
x
.
getId
()
for
x
in
r
]
message_id_list
=
self
.
getNextMessageIdList
(
id_count
=
result_count
)
...
...
@@ -166,25 +164,12 @@ class SyncMLSubscription(XMLObject):
activate_kw
=
activate_kw
,
**
method_kw
)
# Final activity must be executed after all other
callback_method
=
getattr
(
activate
(
**
final_activate_kw
),
callback
)
syncml_logger
.
info
(
"---- getAndActivate : final call for %s : %s"
%
(
r
[
i
+
packet_size
:],
final_activate_kw
))
syncml_logger
.
info
(
"---- getAndActivate : final call for %s : %s"
%
(
r
[
i
+
packet_size
:],
activate_kw
))
callback_method
(
id_list
=
r
[
i
+
packet_size
:],
# XXX Has to be unit tested
# with mock object
message_id
=
message_id_list
.
pop
(),
activate_kw
=
final_activate_kw
,
is_final_message
=
True
,
**
method_kw
)
else
:
# We got no more result, but we must send a message with a final tag
activate
=
self
.
getPortalObject
().
portal_synchronizations
.
activate
callback_method
=
getattr
(
activate
(
**
final_activate_kw
),
callback
)
syncml_logger
.
info
(
"getAndActivate : No result : final call"
)
callback_method
(
id_list
=
[],
message_id
=
self
.
getNextMessageId
(),
activate_kw
=
final_activate_kw
,
is_final_message
=
True
,
activate_kw
=
activate_kw
,
**
method_kw
)
return
result_count
security
.
declarePrivate
(
'sendMessage'
)
...
...
@@ -482,26 +467,18 @@ class SyncMLSubscription(XMLObject):
def
_getDeletedData
(
self
,
syncml_response
):
"""
Return list of deleted data base on validation state of signature
"""
return
None
# XXX Do nothing for now, must introduce a new state to distinguisehd
# from not-synchronized object for which we wait for a status answer
# Maybe signature can be make "synchronized" without the status
# and changed if status not ok
deleted_signature_list
=
self
.
searchFolder
(
validation_state
=
"not_synchronized"
)
# Slow method
# deleted_signature_list = [x for x in self.contentValues() if x.getValidationState() == "not_synchronized"]
syncml_logger
.
info
(
"Got %d deleted objects list in %s"
%
(
len
(
deleted_signature_list
),
self
.
getPath
(),))
for
signature
in
deleted_signature_list
:
syncml_response
.
addDeleteCommand
(
gid
=
signature
.
getId
(),)
Add delete command to syncml resposne
XXX Delete signature from database when we receive confirmation message
"""
# XXX not efficient at all, must be review later
id_list
=
[
x
.
getId
()
for
x
in
self
.
contentValues
()
if
x
.
getValidationState
()
==
"not_synchronized"
]
for
gid
in
id_list
:
syncml_response
.
addDeleteCommand
(
gid
=
gid
)
def
_getSyncMLData
(
self
,
syncml_response
,
id_list
=
None
):
"""
XXX Comment to be fixed
if object is not None, this usually means we want to set the
actual xupdate on the signature.
"""
if
not
id_list
:
syncml_logger
.
warning
(
"Non optimal call to _getSyncMLData, no id list provided"
)
...
...
@@ -586,6 +563,7 @@ class SyncMLSubscription(XMLObject):
# The data will be copied in 'data' property once we get
# confirmation that the document was well synchronized
signature
.
setTemporaryData
(
document_data
)
signature
.
doSync
()
# Generate the message
syncml_response
.
addSyncCommand
(
...
...
@@ -613,10 +591,8 @@ class SyncMLSubscription(XMLObject):
sync_code
=
'conflict_resolved_with_merge'
,
command
=
'Replace'
)
set_synchronized
=
True
if
not
signature
.
checkMD5
(
xml_object
):
# MD5 checksum tell there is a modification of the object
set_synchronized
=
False
if
conduit
.
getContentType
()
!=
'text/xml'
:
# If there is no xml, we re-send the whole object
# XXX this must be managed by conduit ?
...
...
@@ -661,11 +637,12 @@ class SyncMLSubscription(XMLObject):
data
=
data_diff
,
more_data
=
more_data
,
media_type
=
conduit
.
getContentType
())
signature
.
doSync
()
if
set_synchronized
and
\
signature
.
getValidationState
()
!=
'synchronized'
:
elif
signature
.
getValidationState
()
!=
'synchronized'
:
# We should not have this case when we are in CONFLICT_MERGE
signature
.
synchronize
()
elif
signature
.
getValidationState
()
==
\
'conflict_resolved_with_client_command_winning'
:
# We have decided to apply the update
...
...
@@ -705,6 +682,9 @@ class SyncMLSubscription(XMLObject):
more_data
=
more_data
,
media_type
=
self
.
getContentType
())
if
not
more_data
:
signature
.
doSync
()
if
not
more_data
:
pass
#self.removeRemainingObjectPath(object_path)
...
...
product/ERP5SyncML/Engine/AsynchronousEngine.py
View file @
78cb52bc
...
...
@@ -218,7 +218,7 @@ class SyncMLAsynchronousEngine(EngineMixin):
activity_created
=
self
.
runGetAndActivate
(
subscription
=
subscriber
,
after_method_id
=
after_method_id
,
tag
=
tag
)
syncml_logger
.
info
(
"X--> Server is sending modifications in activities
"
)
syncml_logger
.
info
(
"X--> Server is sending modifications in activities
%s"
%
(
activity_created
)
)
if
not
activity_created
:
# Server has no modification to send to client, return final message
syncml_logger
.
info
(
"X-> Server sending final message"
)
...
...
@@ -257,14 +257,21 @@ class SyncMLAsynchronousEngine(EngineMixin):
'subscription_path'
:
subscription
.
getRelativeUrl
(),
}
pref
=
getSite
().
portal_preferences
return
subscription
.
getAndActivate
(
count
=
subscription
.
getAndActivate
(
callback
=
"sendSyncCommand"
,
method_kw
=
method_kw
,
activate_kw
=
activate_kw
,
final_activate_kw
=
final_activate_kw
,
packet_size
=
pref
.
getPreferredDocumentRetrievedPerActivityCount
(),
activity_count
=
pref
.
getPreferredRetrievalActivityCount
(),
)
# Then get deleted document
# this will act as the final message of this sync part
activate
=
subscription
.
getPortalObject
().
portal_synchronizations
.
activate
callback_method
=
getattr
(
activate
(
**
activate_kw
),
"sendDeleteCommand"
)
callback_method
(
message_id
=
subscription
.
getNextMessageId
(),
activate_kw
=
activate_kw
,
**
method_kw
)
return
True
def
runApplySyncCommand
(
self
,
subscription
,
syncml_request
,
tag
):
...
...
product/ERP5SyncML/Tool/SynchronizationTool.py
View file @
78cb52bc
...
...
@@ -463,4 +463,36 @@ class SynchronizationTool(BaseTool):
subscription
.
activate
(
**
activate_kw
).
sendMessage
(
xml
=
str
(
syncml_response
))
def
sendDeleteCommand
(
self
,
message_id
,
subscription_path
,
activate_kw
):
"""
This methods is intented to be called by asynchronous engine in activity to
send delete sync commands for a set of data
As engines are not zodb object, the tool acts as a placeholder for method
that need to be called in activities
"""
subscription
=
self
.
restrictedTraverse
(
subscription_path
)
assert
subscription
is
not
None
,
"Impossible to find subscription %s"
\
%
(
subscription_path
)
# Build Message
syncml_response
=
SyncMLResponse
()
syncml_response
.
addHeader
(
session_id
=
subscription
.
getSessionId
(),
message_id
=
message_id
,
target
=
subscription
.
getUrlString
(),
source
=
subscription
.
getSubscriptionUrlString
())
syncml_response
.
addBody
()
subscription
.
_getDeletedData
(
syncml_response
=
syncml_response
,
)
# Notify that all modifications were sent
syncml_response
.
addFinal
()
# Send the message in activity to prevent recomputing data in case of
# transport failure
subscription
.
activate
(
**
activate_kw
).
sendMessage
(
xml
=
str
(
syncml_response
))
InitializeClass
(
SynchronizationTool
)
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