3 /// Wrapper class for opensync 0.22 syncing behaviour
7 Copyright (C) 2009-2010, Net Direct Inc. (http://www.netdirect.ca/)
9 Used code from msynctool (GPL v2+) as a guide to the API,
10 and copied some of its status messages and one function directly:
11 static const char *OSyncChangeType2String(OSyncChangeType c);
12 Copyright (C) 2004-2005 Armin Bauer <armin.bauer@opensync.org>
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
23 See the GNU General Public License in the COPYING file at the
24 root directory of this project for more details.
28 #include "osprivatebase.h"
30 #include <barry/barry.h>
31 #include <barry/vsmartptr.h>
35 #include <../opensync-1.0/opensync/opensync.h>
36 #include <../opensync-1.0/osengine/engine.h>
42 typedef Barry::vLateSmartPtr
<OSyncEngine
, void(*)(OSyncEngine
*)> EngineHandle
;
44 class OpenSync22Private
48 const char* (*osync_get_version
)();
49 OSyncEnv
* (*osync_env_new
)();
50 void (*osync_env_free
)(OSyncEnv
*env
);
51 void (*osync_env_set_option
)(OSyncEnv
*env
,
52 const char *name
, const char *value
);
53 osync_bool (*osync_env_finalize
)(OSyncEnv
*env
,
55 int (*osync_env_num_plugins
)(OSyncEnv
*env
);
56 OSyncPlugin
* (*osync_env_nth_plugin
)(OSyncEnv
*env
, int nth
);
57 const char* (*osync_plugin_get_name
)(OSyncPlugin
*plugin
);
58 void (*osync_error_free
)(OSyncError
**error
);
59 const char* (*osync_error_print
)(OSyncError
**error
);
60 osync_bool (*osync_env_initialize
)(OSyncEnv
*env
,
62 int (*osync_env_num_groups
)(OSyncEnv
*env
);
63 OSyncGroup
* (*osync_env_nth_group
)(OSyncEnv
*env
, int nth
);
64 const char* (*osync_group_get_name
)(OSyncGroup
*group
);
65 OSyncGroup
* (*osync_env_find_group
)(OSyncEnv
*env
,
67 int (*osync_group_num_members
)(OSyncGroup
*group
);
68 OSyncMember
* (*osync_group_nth_member
)(OSyncGroup
*group
,
70 long long int (*osync_member_get_id
)(OSyncMember
*member
);
71 const char* (*osync_member_get_pluginname
)(
73 OSyncFormatEnv
* (*osync_conv_env_new
)(OSyncEnv
*env
);
74 void (*osync_conv_env_free
)(OSyncFormatEnv
*env
);
75 int (*osync_conv_num_objtypes
)(OSyncFormatEnv
*env
);
76 OSyncObjType
* (*osync_conv_nth_objtype
)(OSyncFormatEnv
*env
,
78 int (*osync_conv_num_objformats
)(
80 OSyncObjFormat
* (*osync_conv_nth_objformat
)(OSyncObjType
*type
,
82 const char* (*osync_objformat_get_name
)(
83 OSyncObjFormat
*format
);
84 const char* (*osync_objtype_get_name
)(OSyncObjType
*type
);
85 OSyncGroup
* (*osync_group_new
)(OSyncEnv
*env
);
86 void (*osync_group_set_name
)(OSyncGroup
*group
,
88 osync_bool (*osync_group_save
)(OSyncGroup
*group
,
90 osync_bool (*osync_group_delete
)(OSyncGroup
*group
,
92 OSyncMember
* (*osync_member_new
)(OSyncGroup
*group
);
93 osync_bool (*osync_member_instance_plugin
)(
95 const char *pluginname
,
97 osync_bool (*osync_member_save
)(OSyncMember
*member
,
99 OSyncMember
* (*osync_member_from_id
)(OSyncGroup
*group
,
101 osync_bool (*osync_member_need_config
)(OSyncMember
*member
,
102 OSyncConfigurationTypes
*type
,
104 osync_bool (*osync_member_get_config_or_default
)(
106 char **data
, int *size
,
108 void (*osync_member_set_config
)(OSyncMember
*member
,
109 const char *data
, int size
);
110 osync_bool (*osengine_mapping_ignore_supported
)(
112 OSyncMapping
*mapping
);
113 osync_bool (*osengine_mapping_check_timestamps
)(
115 OSyncMapping
*mapping
,
117 OSyncChange
* (*osengine_mapping_nth_change
)(
118 OSyncMapping
*mapping
, int nth
);
119 void (*osengine_mapping_solve
)(OSyncEngine
*engine
,
120 OSyncMapping
*mapping
,
121 OSyncChange
*change
);
122 void (*osengine_mapping_duplicate
)(
124 OSyncMapping
*dupe_mapping
);
125 osync_bool (*osengine_mapping_ignore_conflict
)(
127 OSyncMapping
*mapping
,
129 osync_bool (*osengine_mapping_solve_latest
)(
131 OSyncMapping
*mapping
,
133 const char* (*osync_change_get_uid
)(OSyncChange
*change
);
134 osync_bool (*osengine_init
)(OSyncEngine
*engine
,
136 OSyncMember
* (*osync_change_get_member
)(OSyncChange
*change
);
137 int (*osync_change_get_datasize
)(
138 OSyncChange
*change
);
139 OSyncEngine
* (*osengine_new
)(OSyncGroup
*group
,
141 void (*osengine_free
)(OSyncEngine
*engine
);
142 void (*osengine_finalize
)(OSyncEngine
*engine
);
143 osync_bool (*osengine_sync_and_block
)(OSyncEngine
*engine
,
145 void (*osengine_set_memberstatus_callback
)(
147 void (* function
) (OSyncMemberUpdate
*,
150 void (*osengine_set_changestatus_callback
)(
152 void (* function
) (OSyncEngine
*,
156 void (*osengine_set_enginestatus_callback
)(
158 void (* function
) (OSyncEngine
*,
162 void (*osengine_set_mappingstatus_callback
)(
164 void (* function
) (OSyncMappingUpdate
*,
167 void (*osengine_set_conflict_callback
)(
169 void (* function
) (OSyncEngine
*,
173 int (*osengine_mapping_num_changes
)(
174 OSyncMapping
*mapping
);
175 OSyncChangeType (*osync_change_get_changetype
)(
176 OSyncChange
*change
);
177 char* (*osync_change_get_printable
)(
178 OSyncChange
*change
);
183 Converter22 converter
;
185 OpenSync22Private(OpenSync22
&api
)
192 class SyncConflict22Private
: public SyncConflictPrivateBase
194 OpenSync22Private
*m_priv
;
195 OSyncEngine
*m_engine
;
196 OSyncMapping
*m_mapping
;
199 SyncConflict22Private(OpenSync22Private
*priv
,
200 OSyncEngine
*engine
, OSyncMapping
*mapping
);
201 ~SyncConflict22Private();
203 virtual bool IsAbortSupported() const;
204 virtual bool IsIgnoreSupported() const;
205 virtual bool IsKeepNewerSupported() const;
207 virtual void Select(int change_id
); // takes id of SyncChange object
208 virtual void Abort(); // not supported in 0.22
209 virtual void Duplicate();
210 virtual void Ignore();
211 virtual void KeepNewer();
213 void AppendChanges(std::vector
<SyncChange
> &list
);
216 struct CallbackBundle22
218 OpenSync22Private
*m_priv
;
219 SyncStatus
*m_status
;
221 CallbackBundle22(OpenSync22Private
*priv
, SyncStatus
&status
)
228 void member_status(OSyncMemberUpdate
*, void *);
229 void entry_status(OSyncEngine
*, OSyncChangeUpdate
*, void *);
230 void engine_status(OSyncEngine
*, OSyncEngineUpdate
*,void *);
231 void mapping_status(OSyncMappingUpdate
*, void *);
232 void conflict_handler(OSyncEngine
*, OSyncMapping
*, void *);
235 /////////////////////////////////////////////////////////////////////////////
236 // Static helper functions
238 static const char *OSyncChangeType2String(OSyncChangeType c
)
241 case CHANGE_ADDED
: return "ADDED";
242 case CHANGE_UNMODIFIED
: return "UNMODIFIED";
243 case CHANGE_DELETED
: return "DELETED";
244 case CHANGE_MODIFIED
: return "MODIFIED";
246 case CHANGE_UNKNOWN
: return "?";
250 /////////////////////////////////////////////////////////////////////////////
251 // SyncConflict22Private member functions
253 SyncConflict22Private::SyncConflict22Private(OpenSync22Private
*priv
,
254 OSyncEngine
*engine
, OSyncMapping
*mapping
)
261 SyncConflict22Private::~SyncConflict22Private()
265 bool SyncConflict22Private::IsAbortSupported() const
267 return false; // Abort not explicitly supported in 0.22
270 bool SyncConflict22Private::IsIgnoreSupported() const
272 return m_priv
->osengine_mapping_ignore_supported(m_engine
, m_mapping
);
275 bool SyncConflict22Private::IsKeepNewerSupported() const
277 return m_priv
->osengine_mapping_check_timestamps(m_engine
, m_mapping
, NULL
);
280 void SyncConflict22Private::Select(int change_id
)
282 OSyncChange
*change
= m_priv
->osengine_mapping_nth_change(m_mapping
, change_id
);
284 throw std::runtime_error("Bad change_id, or error getting nth change object.");
287 m_priv
->osengine_mapping_solve(m_engine
, m_mapping
, change
);
290 void SyncConflict22Private::Abort()
292 throw std::logic_error("Conflict::Abort() not supported in 0.22");
295 void SyncConflict22Private::Duplicate()
297 m_priv
->osengine_mapping_duplicate(m_engine
, m_mapping
);
300 void SyncConflict22Private::Ignore()
302 if( !IsIgnoreSupported() )
303 throw std::logic_error("Ignore not supported, yet Ignore() called.");
305 OSyncError
*error
= NULL
;
306 if( !m_priv
->osengine_mapping_ignore_conflict(m_engine
, m_mapping
, &error
)) {
308 oss
<< "Conflict not ignored: "
309 << m_priv
->osync_error_print(&error
);
310 m_priv
->osync_error_free(&error
);
311 throw std::runtime_error(oss
.str());
315 void SyncConflict22Private::KeepNewer()
317 if( !IsKeepNewerSupported() )
318 throw std::logic_error("Keep Newer not supported, yet KeepNewer() called.");
320 OSyncError
*error
= NULL
;
321 if( !m_priv
->osengine_mapping_solve_latest(m_engine
, m_mapping
, &error
)) {
323 oss
<< "Conflict not resolved: "
324 << m_priv
->osync_error_print(&error
);
325 m_priv
->osync_error_free(&error
);
326 throw std::runtime_error(oss
.str());
330 void SyncConflict22Private::AppendChanges(std::vector
<SyncChange
> &list
)
332 for( int i
= 0; i
< m_priv
->osengine_mapping_num_changes(m_mapping
); i
++ ) {
333 OSyncChange
*change
= m_priv
->osengine_mapping_nth_change(m_mapping
, i
);
334 if( m_priv
->osync_change_get_changetype(change
) != CHANGE_UNKNOWN
) {
338 char *printable
= m_priv
->osync_change_get_printable(change
);
340 entry
.printable_data
= printable
;
344 OSyncMember
*member
= m_priv
->osync_change_get_member(change
);
347 entry
.member_id
= m_priv
->osync_member_get_id(member
);
348 entry
.plugin_name
= m_priv
->osync_member_get_pluginname(member
);
349 entry
.uid
= m_priv
->osync_change_get_uid(change
);
352 list
.push_back(entry
);
358 /////////////////////////////////////////////////////////////////////////////
359 // Callback functions
361 void member_status(OSyncMemberUpdate
*status
, void *cbdata
)
363 CallbackBundle22
*cb
= (CallbackBundle22
*) cbdata
;
367 bool error_event
= false;
371 << cb
->m_priv
->osync_member_get_id(status
->member
)
373 << cb
->m_priv
->osync_member_get_pluginname(status
->member
)
376 switch( status
->type
)
378 case MEMBER_CONNECTED
:
379 oss
<< " just connected";
381 case MEMBER_DISCONNECTED
:
382 oss
<< " just disconnected";
384 case MEMBER_SENT_CHANGES
:
385 oss
<< " just sent all changes";
387 case MEMBER_COMMITTED_ALL
:
388 oss
<< " committed all changes";
390 case MEMBER_CONNECT_ERROR
:
391 oss
<< " had an error while connecting: "
392 << cb
->m_priv
->osync_error_print(&status
->error
);
394 case MEMBER_GET_CHANGES_ERROR
:
395 oss
<< " had an error while getting changes: "
396 << cb
->m_priv
->osync_error_print(&status
->error
);
399 case MEMBER_SYNC_DONE_ERROR
:
400 oss
<< " had an error while calling sync done: "
401 << cb
->m_priv
->osync_error_print(&status
->error
);
404 case MEMBER_DISCONNECT_ERROR
:
405 oss
<< " had an error while disconnecting: "
406 << cb
->m_priv
->osync_error_print(&status
->error
);
409 case MEMBER_COMMITTED_ALL_ERROR
:
410 oss
<< " had an error while commiting changes: "
411 << cb
->m_priv
->osync_error_print(&status
->error
);
419 // call the status handler
420 if( oss
.str().size() && valid
) {
421 cb
->m_status
->MemberStatus(
422 cb
->m_priv
->osync_member_get_id(status
->member
),
423 cb
->m_priv
->osync_member_get_pluginname(status
->member
),
424 oss
.str(), error_event
);
427 catch( std::exception
&e
) {
428 cb
->m_status
->ReportError(
429 string("member_status error: ") + e
.what());
432 cb
->m_status
->ReportError(
433 "Unknown exception caught in member_status()");
438 void entry_status(OSyncEngine
*engine
, OSyncChangeUpdate
*status
, void *cbdata
)
440 CallbackBundle22
*cb
= (CallbackBundle22
*) cbdata
;
445 OSyncMember
*member
= cb
->m_priv
->osync_change_get_member(status
->change
);
446 bool error_event
= false;
448 switch( status
->type
)
450 case CHANGE_RECEIVED_INFO
:
451 oss
<< "Received an entry "
452 << cb
->m_priv
->osync_change_get_uid(status
->change
)
453 << " without data from member "
456 << cb
->m_priv
->osync_member_get_pluginname(member
)
459 << OSyncChangeType2String(cb
->m_priv
->osync_change_get_changetype(status
->change
));
461 case CHANGE_RECEIVED
:
462 oss
<< "Received an entry "
463 << cb
->m_priv
->osync_change_get_uid(status
->change
)
464 << " with data of size "
465 << cb
->m_priv
->osync_change_get_datasize(status
->change
)
469 << cb
->m_priv
->osync_member_get_pluginname(member
)
471 << OSyncChangeType2String(cb
->m_priv
->osync_change_get_changetype(status
->change
));
474 oss
<< "Sent an entry "
475 << cb
->m_priv
->osync_change_get_uid(status
->change
)
477 << cb
->m_priv
->osync_change_get_datasize(status
->change
)
481 << cb
->m_priv
->osync_member_get_pluginname(member
)
483 << OSyncChangeType2String(cb
->m_priv
->osync_change_get_changetype(status
->change
));
485 case CHANGE_WRITE_ERROR
:
487 oss
<< "Error writing entry "
488 << cb
->m_priv
->osync_change_get_uid(status
->change
)
492 << cb
->m_priv
->osync_member_get_pluginname(member
)
494 << cb
->m_priv
->osync_error_print(&status
->error
);
496 case CHANGE_RECV_ERROR
:
498 oss
<< "Error reading entry "
499 << cb
->m_priv
->osync_change_get_uid(status
->change
)
503 << cb
->m_priv
->osync_member_get_pluginname(member
)
505 << cb
->m_priv
->osync_error_print(&(status
->error
));
509 // call the status handler
510 if( oss
.str().size() ) {
511 cb
->m_status
->EntryStatus(oss
.str(), error_event
);
514 catch( std::exception
&e
) {
515 cb
->m_status
->ReportError(
516 string("entry_status error:") + e
.what());
519 cb
->m_status
->ReportError(
520 "Unknown exception caught in entry_status()");
524 void engine_status(OSyncEngine
*engine
, OSyncEngineUpdate
*status
, void *cbdata
)
526 CallbackBundle22
*cb
= (CallbackBundle22
*) cbdata
;
530 bool error_event
= false;
532 switch( status
->type
)
534 case ENG_PREV_UNCLEAN
:
535 oss
<< "The previous synchronization was unclean. Slow-syncing.";
537 case ENG_ENDPHASE_CON
:
538 oss
<< "All clients connected or error";
540 case ENG_END_CONFLICTS
:
541 oss
<< "All conflicts have been reported";
543 case ENG_ENDPHASE_READ
:
544 oss
<< "All clients sent changes or error";
546 case ENG_ENDPHASE_WRITE
:
547 oss
<< "All clients have written";
549 case ENG_ENDPHASE_DISCON
:
550 oss
<< "All clients have disconnected";
552 case ENG_SYNC_SUCCESSFULL
:
553 oss
<< "The sync was successful";
556 oss
<< "The sync failed: "
557 << cb
->m_priv
->osync_error_print(&status
->error
);
562 // call the status handler
563 if( oss
.str().size() )
564 cb
->m_status
->EngineStatus(oss
.str(),
566 status
->type
== ENG_PREV_UNCLEAN
);
568 catch( std::exception
&e
) {
569 cb
->m_status
->ReportError(
570 string("engine_status error: ") + e
.what());
573 cb
->m_status
->ReportError(
574 "Unknown exception caught in engine_status()");
578 void mapping_status(OSyncMappingUpdate
*status
, void *cbdata
)
580 CallbackBundle22
*cb
= (CallbackBundle22
*) cbdata
;
584 bool error_event
= false;
586 switch( status
->type
)
589 oss
<< "Mapping solved";
592 oss
<< "Mapping Synced";
594 case MAPPING_WRITE_ERROR
:
596 oss
<< "Mapping Write Error: "
597 << cb
->m_priv
->osync_error_print(&status
->error
);
601 // call the status handler
602 if( oss
.str().size() )
603 cb
->m_status
->MappingStatus(oss
.str(), error_event
);
605 catch( std::exception
&e
) {
606 cb
->m_status
->ReportError(
607 string("mapping_status error: ") + e
.what());
610 cb
->m_status
->ReportError(
611 "Unknown exception caught in mapping_status()");
615 void conflict_handler(OSyncEngine
*engine
, OSyncMapping
*mapping
, void *cbdata
)
617 CallbackBundle22
*cb
= (CallbackBundle22
*) cbdata
;
620 // build the SyncConflict object
621 SyncConflict22Private
scp(cb
->m_priv
, engine
, mapping
);
622 SyncConflict
conflict(scp
);
624 // append all conflicting changes as vector objects in the same
625 // order as the opensync library mapping
626 scp
.AppendChanges(conflict
);
628 // call the status handler
629 cb
->m_status
->HandleConflict(conflict
);
631 catch( std::exception
&e
) {
632 cb
->m_status
->ReportError(
633 string("Conflict not resolved. ") + e
.what());
636 cb
->m_status
->ReportError(
637 "Unknown exception caught in conflict_handler()");
642 /////////////////////////////////////////////////////////////////////////////
643 // OpenSync22 - public members
645 bool OpenSync22::symbols_loaded
= false;
647 OpenSync22::OpenSync22()
649 if( !Open("libosengine.so.0") )
650 throw DlError("Can't dlopen libosengine.so.0");
652 // the symbol table is now thoroughly polluted...
653 symbols_loaded
= true;
655 // store locally in case of constructor exception in LoadSym
656 std::auto_ptr
<OpenSync22Private
> p(new OpenSync22Private(*this));
658 // load all required symbols...
659 // we don't need to use try/catch here, since the base
660 // class destructor will clean up for us if LoadSym() throws
661 LoadSym(p
->osync_get_version
, "osync_get_version");
662 LoadSym(p
->osync_env_new
, "osync_env_new");
663 LoadSym(p
->osync_env_free
, "osync_env_free");
664 LoadSym(p
->osync_env_set_option
, "osync_env_set_option");
665 LoadSym(p
->osync_env_finalize
, "osync_env_finalize");
666 LoadSym(p
->osync_env_num_plugins
, "osync_env_num_plugins");
667 LoadSym(p
->osync_env_nth_plugin
, "osync_env_nth_plugin");
668 LoadSym(p
->osync_plugin_get_name
, "osync_plugin_get_name");
669 LoadSym(p
->osync_error_free
, "osync_error_free");
670 LoadSym(p
->osync_error_print
, "osync_error_print");
671 LoadSym(p
->osync_env_initialize
, "osync_env_initialize");
672 LoadSym(p
->osync_env_num_groups
, "osync_env_num_groups");
673 LoadSym(p
->osync_env_nth_group
, "osync_env_nth_group");
674 LoadSym(p
->osync_group_get_name
, "osync_group_get_name");
675 LoadSym(p
->osync_env_find_group
, "osync_env_find_group");
676 LoadSym(p
->osync_group_num_members
, "osync_group_num_members");
677 LoadSym(p
->osync_group_nth_member
, "osync_group_nth_member");
678 LoadSym(p
->osync_member_get_id
, "osync_member_get_id");
679 LoadSym(p
->osync_member_get_pluginname
, "osync_member_get_pluginname");
680 LoadSym(p
->osync_conv_env_new
, "osync_conv_env_new");
681 LoadSym(p
->osync_conv_env_free
, "osync_conv_env_free");
682 LoadSym(p
->osync_conv_num_objtypes
, "osync_conv_num_objtypes");
683 LoadSym(p
->osync_conv_nth_objtype
, "osync_conv_nth_objtype");
684 LoadSym(p
->osync_conv_num_objformats
, "osync_conv_num_objformats");
685 LoadSym(p
->osync_conv_nth_objformat
, "osync_conv_nth_objformat");
686 LoadSym(p
->osync_objformat_get_name
, "osync_objformat_get_name");
687 LoadSym(p
->osync_objtype_get_name
, "osync_objtype_get_name");
688 LoadSym(p
->osync_group_new
, "osync_group_new");
689 LoadSym(p
->osync_group_set_name
, "osync_group_set_name");
690 LoadSym(p
->osync_group_save
, "osync_group_save");
691 LoadSym(p
->osync_group_delete
, "osync_group_delete");
692 LoadSym(p
->osync_member_new
, "osync_member_new");
693 LoadSym(p
->osync_member_instance_plugin
,"osync_member_instance_plugin");
694 LoadSym(p
->osync_member_save
, "osync_member_save");
695 LoadSym(p
->osync_member_from_id
, "osync_member_from_id");
696 LoadSym(p
->osync_member_need_config
, "osync_member_need_config");
697 LoadSym(p
->osync_member_get_config_or_default
,
698 "osync_member_get_config_or_default");
699 LoadSym(p
->osync_member_set_config
, "osync_member_set_config");
700 LoadSym(p
->osengine_mapping_ignore_supported
,
701 "osengine_mapping_ignore_supported");
702 LoadSym(p
->osengine_mapping_check_timestamps
,
703 "osengine_mapping_check_timestamps");
704 LoadSym(p
->osengine_mapping_nth_change
, "osengine_mapping_nth_change");
705 LoadSym(p
->osengine_mapping_solve
, "osengine_mapping_solve");
706 LoadSym(p
->osengine_mapping_duplicate
, "osengine_mapping_duplicate");
707 LoadSym(p
->osengine_mapping_ignore_conflict
,
708 "osengine_mapping_ignore_conflict");
709 LoadSym(p
->osengine_mapping_solve_latest
,
710 "osengine_mapping_solve_latest");
711 LoadSym(p
->osync_change_get_uid
, "osync_change_get_uid");
712 LoadSym(p
->osengine_init
, "osengine_init");
713 LoadSym(p
->osync_change_get_member
, "osync_change_get_member");
714 LoadSym(p
->osync_change_get_datasize
, "osync_change_get_datasize");
715 LoadSym(p
->osengine_new
, "osengine_new");
716 LoadSym(p
->osengine_free
, "osengine_free");
717 LoadSym(p
->osengine_finalize
, "osengine_finalize");
718 LoadSym(p
->osengine_sync_and_block
, "osengine_sync_and_block");
719 LoadSym(p
->osengine_set_memberstatus_callback
,
720 "osengine_set_memberstatus_callback");
721 LoadSym(p
->osengine_set_changestatus_callback
,
722 "osengine_set_changestatus_callback");
723 LoadSym(p
->osengine_set_enginestatus_callback
,
724 "osengine_set_enginestatus_callback");
725 LoadSym(p
->osengine_set_mappingstatus_callback
,
726 "osengine_set_mappingstatus_callback");
727 LoadSym(p
->osengine_set_conflict_callback
,
728 "osengine_set_conflict_callback");
729 LoadSym(p
->osengine_mapping_num_changes
,
730 "osengine_mapping_num_changes");
731 LoadSym(p
->osync_change_get_changetype
, "osync_change_get_changetype");
732 LoadSym(p
->osync_change_get_printable
, "osync_change_get_printable");
734 // do common initialization of opensync environment
735 SetupEnvironment(p
.get());
737 // this pointer is ours now
738 m_priv
= p
.release();
741 OpenSync22::~OpenSync22()
743 // clean up opensync environment, closing plugins, etc.
745 m_priv
->osync_env_finalize(m_priv
->env
, NULL
);
746 m_priv
->osync_env_free(m_priv
->env
);
749 // free private class data
754 void OpenSync22::SetupEnvironment(OpenSync22Private
*p
)
756 // we are fully responsible for this pointer, since
757 // we run inside the constructor... only on success
758 // will responsibility be transferred to the destructor
759 p
->env
= p
->osync_env_new();
761 throw std::runtime_error("Error allocating opensync 0.22 environment");
763 p
->osync_env_set_option(p
->env
, "GROUPS_DIRECTORY", NULL
);
764 p
->osync_env_set_option(p
->env
, "LOAD_GROUPS", "TRUE");
765 p
->osync_env_set_option(p
->env
, "LOAD_PLUGINS", "TRUE");
766 p
->osync_env_set_option(p
->env
, "LOAD_FORMATS", "TRUE");
768 OSyncError
*error
= NULL
;
769 if( !p
->osync_env_initialize(p
->env
, &error
) ) {
770 // grab error message
771 std::runtime_error
err(m_priv
->osync_error_print(&error
));
774 p
->osync_error_free(&error
);
775 p
->osync_env_free(m_priv
->env
);
782 const char* OpenSync22::GetVersion() const
784 return m_priv
->osync_get_version();
787 const char* OpenSync22::GetEngineName() const
792 void OpenSync22::GetPluginNames(string_list_type
&plugins
)
798 for( int i
= 0; i
< m_priv
->osync_env_num_plugins(m_priv
->env
); i
++) {
799 p
= m_priv
->osync_env_nth_plugin(m_priv
->env
, i
);
800 plugins
.push_back(m_priv
->osync_plugin_get_name(p
));
804 void OpenSync22::GetFormats(format_list_type
&formats
)
809 // cycle through all object types and simulate a 0.4x-like
810 // list based on the attached formats
812 OSyncFormatEnv
*fenv
= m_priv
->osync_conv_env_new(m_priv
->env
);
814 throw std::runtime_error("GetFormats(): Unable to load format environment in GetFormats (22)");
817 for( int i
= 0; i
< m_priv
->osync_conv_num_objtypes(fenv
); i
++ ) {
818 OSyncObjType
*type
= m_priv
->osync_conv_nth_objtype(fenv
, i
);
820 for( int i
= 0; i
< m_priv
->osync_conv_num_objformats(type
); i
++ ) {
821 OSyncObjFormat
*format
= m_priv
->osync_conv_nth_objformat(type
, i
);
822 const char *objformat_name
= m_priv
->osync_objformat_get_name(format
);
824 if( !formats
.Find(objformat_name
) ) {
826 new_format
.name
= objformat_name
;
827 new_format
.object_type
= m_priv
->osync_objtype_get_name(type
);
828 formats
.push_back(new_format
);
833 m_priv
->osync_conv_env_free(fenv
);
836 void OpenSync22::GetGroupNames(string_list_type
&groups
)
842 for( int i
= 0; i
< m_priv
->osync_env_num_groups(m_priv
->env
); i
++ ) {
843 g
= m_priv
->osync_env_nth_group(m_priv
->env
, i
);
844 groups
.push_back(m_priv
->osync_group_get_name(g
));
848 void OpenSync22::GetMembers(const std::string
&group_name
,
849 member_list_type
&members
)
854 OSyncGroup
*group
= m_priv
->osync_env_find_group(m_priv
->env
, group_name
.c_str());
856 throw std::runtime_error("GetMembers(): Unable to find group with name: " + group_name
);
859 for( int i
= 0; i
< m_priv
->osync_group_num_members(group
); i
++ ) {
860 OSyncMember
*member
= m_priv
->osync_group_nth_member(group
, i
);
864 new_member
.group_name
= group_name
;
865 new_member
.id
= m_priv
->osync_member_get_id(member
);
866 new_member
.plugin_name
= m_priv
->osync_member_get_pluginname(member
);
868 // we are switching opensync's long long int ID to
869 // our long... to double check they are equal after
871 if( new_member
.id
!= m_priv
->osync_member_get_id(member
) ) {
872 throw std::logic_error("GetMembers(): OpenSync's member ID is too large to fit in OpenSyncAPI (22)");
875 // add to member list
876 members
.push_back(new_member
);
880 void OpenSync22::AddGroup(const std::string
&group_name
)
882 if( m_priv
->osync_env_find_group(m_priv
->env
, group_name
.c_str()) )
883 throw std::runtime_error("AddGroup(): Group already exists: " + group_name
);
885 OSyncGroup
*group
= m_priv
->osync_group_new(m_priv
->env
);
886 m_priv
->osync_group_set_name(group
, group_name
.c_str());
888 OSyncError
*error
= NULL
;
889 if( !m_priv
->osync_group_save(group
, &error
) ) {
890 // grab error message
891 std::runtime_error
err(string("AddGroup(): Unable to save group: ") + m_priv
->osync_error_print(&error
));
894 m_priv
->osync_error_free(&error
);
900 void OpenSync22::DeleteGroup(const std::string
&group_name
)
902 OSyncGroup
*group
= m_priv
->osync_env_find_group(m_priv
->env
, group_name
.c_str());
904 throw std::runtime_error("DeleteGroup(): Group not found: " + group_name
);
906 OSyncError
*error
= NULL
;
907 if( !m_priv
->osync_group_delete(group
, &error
) ) {
908 std::runtime_error
err(string("DeleteGroup(): Unable to delete group: ") + m_priv
->osync_error_print(&error
));
909 m_priv
->osync_error_free(&error
);
914 Converter
& OpenSync22::GetConverter()
916 return m_priv
->converter
;
919 long OpenSync22::AddMember(const std::string
&group_name
,
920 const std::string
&plugin_name
,
921 const std::string
&member_name
)
923 OSyncGroup
*group
= m_priv
->osync_env_find_group(m_priv
->env
, group_name
.c_str());
925 throw std::runtime_error("AddMember(): Group not found: " + group_name
);
927 OSyncMember
*member
= m_priv
->osync_member_new(group
);
929 OSyncError
*error
= NULL
;
930 if( !m_priv
->osync_member_instance_plugin(member
, plugin_name
.c_str(), &error
) ) {
931 std::runtime_error
err(string("AddMember(): Unable to connect plugin with member: ") + m_priv
->osync_error_print(&error
));
932 m_priv
->osync_error_free(&error
);
936 if( !m_priv
->osync_member_save(member
, &error
) ) {
937 std::runtime_error
err(string("AddMember(): Unable to save member: ") + m_priv
->osync_error_print(&error
));
938 m_priv
->osync_error_free(&error
);
942 return m_priv
->osync_member_get_id(member
);
945 bool OpenSync22::IsConfigurable(const std::string
&group_name
,
948 OSyncGroup
*group
= m_priv
->osync_env_find_group(m_priv
->env
, group_name
.c_str());
950 throw std::runtime_error("Group not found: " + group_name
);
952 OSyncMember
*member
= m_priv
->osync_member_from_id(group
, member_id
);
955 oss
<< "IsConfigurable(): Member " << member_id
<< " not found.";
956 throw std::runtime_error(oss
.str());
959 OSyncConfigurationTypes type
= NO_CONFIGURATION
;
960 OSyncError
*error
= NULL
;
961 if( !m_priv
->osync_member_need_config(member
, &type
, &error
) ) {
962 std::runtime_error
err(string("Unable to determine needed config: ") + m_priv
->osync_error_print(&error
));
963 m_priv
->osync_error_free(&error
);
967 return type
!= NO_CONFIGURATION
;
970 std::string
OpenSync22::GetConfiguration(const std::string
&group_name
,
973 if( !IsConfigurable(group_name
, member_id
) ) {
975 oss
<< "GetConfiguration(): Member " << member_id
<< " of group '" << group_name
<< "' does not accept configuration.";
976 throw std::runtime_error(oss
.str());
979 OSyncGroup
*group
= m_priv
->osync_env_find_group(m_priv
->env
, group_name
.c_str());
981 throw std::runtime_error("GetConfiguration(): Group not found: " + group_name
);
983 OSyncMember
*member
= m_priv
->osync_member_from_id(group
, member_id
);
986 oss
<< "GetConfiguration(): Member " << member_id
<< " not found.";
987 throw std::runtime_error(oss
.str());
990 OSyncError
*error
= NULL
;
993 if( !m_priv
->osync_member_get_config_or_default(member
, &data
, &size
, &error
)) {
994 std::runtime_error
err(string("GetConfiguration(): Unable to retrieve config: ") + m_priv
->osync_error_print(&error
));
995 m_priv
->osync_error_free(&error
);
999 std::string
config(data
, size
);
1005 void OpenSync22::SetConfiguration(const std::string
&group_name
,
1007 const std::string
&config_data
)
1009 if( !IsConfigurable(group_name
, member_id
) ) {
1011 oss
<< "SetConfiguration(): Member " << member_id
<< " of group '" << group_name
<< "' does not accept configuration.";
1012 throw std::runtime_error(oss
.str());
1015 OSyncGroup
*group
= m_priv
->osync_env_find_group(m_priv
->env
, group_name
.c_str());
1017 throw std::runtime_error("SetConfiguration(): Group not found: " + group_name
);
1019 OSyncMember
*member
= m_priv
->osync_member_from_id(group
, member_id
);
1022 oss
<< "SetConfiguration(): Member " << member_id
<< " not found.";
1023 throw std::runtime_error(oss
.str());
1026 m_priv
->osync_member_set_config(member
, config_data
.c_str(), config_data
.size());
1028 OSyncError
*error
= NULL
;
1029 if( !m_priv
->osync_member_save(member
, &error
) ) {
1030 std::runtime_error
err(string("SetConfiguration(): Unable to save member's config: ") + m_priv
->osync_error_print(&error
));
1031 m_priv
->osync_error_free(&error
);
1036 void OpenSync22::Discover(const std::string
&group_name
)
1038 // Discover is a successful noop on 0.22
1041 void OpenSync22::Sync(const std::string
&group_name
,
1042 SyncStatus
&status_callback
)
1044 OSyncGroup
*group
= m_priv
->osync_env_find_group(m_priv
->env
, group_name
.c_str());
1046 throw std::runtime_error("Sync(): Group not found: " + group_name
);
1048 OSyncError
*error
= NULL
;
1049 EngineHandle
engine(m_priv
->osengine_free
);
1050 engine
= m_priv
->osengine_new(group
, &error
);
1051 if( !engine
.get() ) {
1052 std::ostringstream oss
;
1053 oss
<< "Error while synchronizing: "
1054 << m_priv
->osync_error_print(&error
);
1055 m_priv
->osync_error_free(&error
);
1056 throw std::runtime_error(oss
.str());
1059 CallbackBundle22
cbdata(m_priv
, status_callback
);
1061 m_priv
->osengine_set_memberstatus_callback(engine
.get(),
1062 &member_status
, &cbdata
);
1063 m_priv
->osengine_set_changestatus_callback(engine
.get(),
1064 &entry_status
, &cbdata
);
1065 m_priv
->osengine_set_enginestatus_callback(engine
.get(),
1066 &engine_status
, &cbdata
);
1067 m_priv
->osengine_set_mappingstatus_callback(engine
.get(),
1068 &mapping_status
, &cbdata
);
1069 m_priv
->osengine_set_conflict_callback(engine
.get(),
1070 &conflict_handler
, &cbdata
);
1072 if( !m_priv
->osengine_init(engine
.get(), &error
) ) {
1074 oss
<< "Error initializing osengine: "
1075 << m_priv
->osync_error_print(&error
);
1076 m_priv
->osync_error_free(&error
);
1077 throw std::runtime_error(oss
.str());
1080 // successfully initialized, so finalize must be called
1081 EngineHandle
initialized_engine(m_priv
->osengine_finalize
);
1082 initialized_engine
= engine
.get();
1084 if( !m_priv
->osengine_sync_and_block(engine
.get(), &error
) ) {
1086 oss
<< "Error during sync: "
1087 << m_priv
->osync_error_print(&error
);
1088 m_priv
->osync_error_free(&error
);
1089 throw std::runtime_error(oss
.str());
1093 } // namespace OpenSync