3 /// Wrapper class for opensync 0.22 syncing behaviour
7 Copyright (C) 2009-2012, 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/vsmartptr.h>
36 // use relative paths to backtrack enough to specify only 0.22 includes
37 #include <../opensync-1.0/opensync/opensync.h>
38 #include <../opensync-1.0/osengine/engine.h>
44 typedef Barry::vLateSmartPtr
<OSyncEngine
, void(*)(OSyncEngine
*)> EngineHandle
;
46 class OpenSync22Private
50 const char* (*osync_get_version
)();
51 OSyncEnv
* (*osync_env_new
)();
52 void (*osync_env_free
)(OSyncEnv
*env
);
53 void (*osync_env_set_option
)(OSyncEnv
*env
,
54 const char *name
, const char *value
);
55 osync_bool (*osync_env_finalize
)(OSyncEnv
*env
,
57 int (*osync_env_num_plugins
)(OSyncEnv
*env
);
58 OSyncPlugin
* (*osync_env_nth_plugin
)(OSyncEnv
*env
, int nth
);
59 const char* (*osync_plugin_get_name
)(OSyncPlugin
*plugin
);
60 void (*osync_error_free
)(OSyncError
**error
);
61 const char* (*osync_error_print
)(OSyncError
**error
);
62 osync_bool (*osync_env_initialize
)(OSyncEnv
*env
,
64 int (*osync_env_num_groups
)(OSyncEnv
*env
);
65 OSyncGroup
* (*osync_env_nth_group
)(OSyncEnv
*env
, int nth
);
66 const char* (*osync_group_get_name
)(OSyncGroup
*group
);
67 OSyncGroup
* (*osync_env_find_group
)(OSyncEnv
*env
,
69 int (*osync_group_num_members
)(OSyncGroup
*group
);
70 OSyncMember
* (*osync_group_nth_member
)(OSyncGroup
*group
,
72 long long int (*osync_member_get_id
)(OSyncMember
*member
);
73 const char* (*osync_member_get_pluginname
)(
75 OSyncFormatEnv
* (*osync_conv_env_new
)(OSyncEnv
*env
);
76 void (*osync_conv_env_free
)(OSyncFormatEnv
*env
);
77 int (*osync_conv_num_objtypes
)(OSyncFormatEnv
*env
);
78 OSyncObjType
* (*osync_conv_nth_objtype
)(OSyncFormatEnv
*env
,
80 int (*osync_conv_num_objformats
)(
82 OSyncObjFormat
* (*osync_conv_nth_objformat
)(OSyncObjType
*type
,
84 const char* (*osync_objformat_get_name
)(
85 OSyncObjFormat
*format
);
86 const char* (*osync_objtype_get_name
)(OSyncObjType
*type
);
87 OSyncGroup
* (*osync_group_new
)(OSyncEnv
*env
);
88 void (*osync_group_set_name
)(OSyncGroup
*group
,
90 osync_bool (*osync_group_save
)(OSyncGroup
*group
,
92 osync_bool (*osync_group_delete
)(OSyncGroup
*group
,
94 OSyncMember
* (*osync_member_new
)(OSyncGroup
*group
);
95 osync_bool (*osync_member_instance_plugin
)(
97 const char *pluginname
,
99 osync_bool (*osync_member_save
)(OSyncMember
*member
,
101 OSyncMember
* (*osync_member_from_id
)(OSyncGroup
*group
,
103 osync_bool (*osync_member_need_config
)(OSyncMember
*member
,
104 OSyncConfigurationTypes
*type
,
106 osync_bool (*osync_member_get_config_or_default
)(
108 char **data
, int *size
,
110 void (*osync_member_set_config
)(OSyncMember
*member
,
111 const char *data
, int size
);
112 osync_bool (*osengine_mapping_ignore_supported
)(
114 OSyncMapping
*mapping
);
115 osync_bool (*osengine_mapping_check_timestamps
)(
117 OSyncMapping
*mapping
,
119 OSyncChange
* (*osengine_mapping_nth_change
)(
120 OSyncMapping
*mapping
, int nth
);
121 void (*osengine_mapping_solve
)(OSyncEngine
*engine
,
122 OSyncMapping
*mapping
,
123 OSyncChange
*change
);
124 void (*osengine_mapping_duplicate
)(
126 OSyncMapping
*dupe_mapping
);
127 osync_bool (*osengine_mapping_ignore_conflict
)(
129 OSyncMapping
*mapping
,
131 osync_bool (*osengine_mapping_solve_latest
)(
133 OSyncMapping
*mapping
,
135 const char* (*osync_change_get_uid
)(OSyncChange
*change
);
136 osync_bool (*osengine_init
)(OSyncEngine
*engine
,
138 OSyncMember
* (*osync_change_get_member
)(OSyncChange
*change
);
139 int (*osync_change_get_datasize
)(
140 OSyncChange
*change
);
141 OSyncEngine
* (*osengine_new
)(OSyncGroup
*group
,
143 void (*osengine_free
)(OSyncEngine
*engine
);
144 void (*osengine_finalize
)(OSyncEngine
*engine
);
145 osync_bool (*osengine_sync_and_block
)(OSyncEngine
*engine
,
147 void (*osengine_set_memberstatus_callback
)(
149 void (* function
) (OSyncMemberUpdate
*,
152 void (*osengine_set_changestatus_callback
)(
154 void (* function
) (OSyncEngine
*,
158 void (*osengine_set_enginestatus_callback
)(
160 void (* function
) (OSyncEngine
*,
164 void (*osengine_set_mappingstatus_callback
)(
166 void (* function
) (OSyncMappingUpdate
*,
169 void (*osengine_set_conflict_callback
)(
171 void (* function
) (OSyncEngine
*,
175 int (*osengine_mapping_num_changes
)(
176 OSyncMapping
*mapping
);
177 OSyncChangeType (*osync_change_get_changetype
)(
178 OSyncChange
*change
);
179 char* (*osync_change_get_printable
)(
180 OSyncChange
*change
);
181 void (*osync_group_set_objtype_enabled
)(
183 const char *objtypestr
,
189 Converter22 converter
;
191 OpenSync22Private(OpenSync22
&api
)
198 class SyncConflict22Private
: public SyncConflictPrivateBase
200 OpenSync22Private
*m_priv
;
201 OSyncEngine
*m_engine
;
202 OSyncMapping
*m_mapping
;
205 SyncConflict22Private(OpenSync22Private
*priv
,
206 OSyncEngine
*engine
, OSyncMapping
*mapping
);
207 ~SyncConflict22Private();
209 virtual bool IsAbortSupported() const;
210 virtual bool IsIgnoreSupported() const;
211 virtual bool IsKeepNewerSupported() const;
213 virtual void Select(int change_id
); // takes id of SyncChange object
214 virtual void Abort(); // not supported in 0.22
215 virtual void Duplicate();
216 virtual void Ignore();
217 virtual void KeepNewer();
219 void AppendChanges(std::vector
<SyncChange
> &list
);
222 struct CallbackBundle22
224 OpenSync22Private
*m_priv
;
225 SyncStatus
*m_status
;
227 CallbackBundle22(OpenSync22Private
*priv
, SyncStatus
&status
)
234 void member_status(OSyncMemberUpdate
*, void *);
235 void entry_status(OSyncEngine
*, OSyncChangeUpdate
*, void *);
236 void engine_status(OSyncEngine
*, OSyncEngineUpdate
*,void *);
237 void mapping_status(OSyncMappingUpdate
*, void *);
238 void conflict_handler(OSyncEngine
*, OSyncMapping
*, void *);
241 /////////////////////////////////////////////////////////////////////////////
242 // Static helper functions
244 static const char *OSyncChangeType2String(OSyncChangeType c
)
247 case CHANGE_ADDED
: return "ADDED";
248 case CHANGE_UNMODIFIED
: return "UNMODIFIED";
249 case CHANGE_DELETED
: return "DELETED";
250 case CHANGE_MODIFIED
: return "MODIFIED";
252 case CHANGE_UNKNOWN
: return "?";
256 /////////////////////////////////////////////////////////////////////////////
257 // SyncConflict22Private member functions
259 SyncConflict22Private::SyncConflict22Private(OpenSync22Private
*priv
,
260 OSyncEngine
*engine
, OSyncMapping
*mapping
)
267 SyncConflict22Private::~SyncConflict22Private()
271 bool SyncConflict22Private::IsAbortSupported() const
273 return false; // Abort not explicitly supported in 0.22
276 bool SyncConflict22Private::IsIgnoreSupported() const
278 return m_priv
->osengine_mapping_ignore_supported(m_engine
, m_mapping
);
281 bool SyncConflict22Private::IsKeepNewerSupported() const
283 return m_priv
->osengine_mapping_check_timestamps(m_engine
, m_mapping
, NULL
);
286 void SyncConflict22Private::Select(int change_id
)
288 OSyncChange
*change
= m_priv
->osengine_mapping_nth_change(m_mapping
, change_id
);
290 throw std::runtime_error("Bad change_id, or error getting nth change object.");
293 m_priv
->osengine_mapping_solve(m_engine
, m_mapping
, change
);
296 void SyncConflict22Private::Abort()
298 throw std::logic_error("Conflict::Abort() not supported in 0.22");
301 void SyncConflict22Private::Duplicate()
303 m_priv
->osengine_mapping_duplicate(m_engine
, m_mapping
);
306 void SyncConflict22Private::Ignore()
308 if( !IsIgnoreSupported() )
309 throw std::logic_error("Ignore not supported, yet Ignore() called.");
311 OSyncError
*error
= NULL
;
312 if( !m_priv
->osengine_mapping_ignore_conflict(m_engine
, m_mapping
, &error
)) {
314 oss
<< "Conflict not ignored: "
315 << m_priv
->osync_error_print(&error
);
316 m_priv
->osync_error_free(&error
);
317 throw std::runtime_error(oss
.str());
321 void SyncConflict22Private::KeepNewer()
323 if( !IsKeepNewerSupported() )
324 throw std::logic_error("Keep Newer not supported, yet KeepNewer() called.");
326 OSyncError
*error
= NULL
;
327 if( !m_priv
->osengine_mapping_solve_latest(m_engine
, m_mapping
, &error
)) {
329 oss
<< "Conflict not resolved: "
330 << m_priv
->osync_error_print(&error
);
331 m_priv
->osync_error_free(&error
);
332 throw std::runtime_error(oss
.str());
336 void SyncConflict22Private::AppendChanges(std::vector
<SyncChange
> &list
)
338 for( int i
= 0; i
< m_priv
->osengine_mapping_num_changes(m_mapping
); i
++ ) {
339 OSyncChange
*change
= m_priv
->osengine_mapping_nth_change(m_mapping
, i
);
340 if( m_priv
->osync_change_get_changetype(change
) != CHANGE_UNKNOWN
) {
344 char *printable
= m_priv
->osync_change_get_printable(change
);
346 entry
.printable_data
= printable
;
350 OSyncMember
*member
= m_priv
->osync_change_get_member(change
);
353 entry
.member_id
= m_priv
->osync_member_get_id(member
);
354 entry
.plugin_name
= m_priv
->osync_member_get_pluginname(member
);
355 entry
.uid
= m_priv
->osync_change_get_uid(change
);
358 list
.push_back(entry
);
364 /////////////////////////////////////////////////////////////////////////////
365 // Callback functions
367 void member_status(OSyncMemberUpdate
*status
, void *cbdata
)
369 CallbackBundle22
*cb
= (CallbackBundle22
*) cbdata
;
373 bool error_event
= false;
377 << cb
->m_priv
->osync_member_get_id(status
->member
)
379 << cb
->m_priv
->osync_member_get_pluginname(status
->member
)
382 switch( status
->type
)
384 case MEMBER_CONNECTED
:
385 oss
<< " just connected";
387 case MEMBER_DISCONNECTED
:
388 oss
<< " just disconnected";
390 case MEMBER_SENT_CHANGES
:
391 oss
<< " just sent all changes";
393 case MEMBER_COMMITTED_ALL
:
394 oss
<< " committed all changes";
396 case MEMBER_CONNECT_ERROR
:
397 oss
<< " had an error while connecting: "
398 << cb
->m_priv
->osync_error_print(&status
->error
);
400 case MEMBER_GET_CHANGES_ERROR
:
401 oss
<< " had an error while getting changes: "
402 << cb
->m_priv
->osync_error_print(&status
->error
);
405 case MEMBER_SYNC_DONE_ERROR
:
406 oss
<< " had an error while calling sync done: "
407 << cb
->m_priv
->osync_error_print(&status
->error
);
410 case MEMBER_DISCONNECT_ERROR
:
411 oss
<< " had an error while disconnecting: "
412 << cb
->m_priv
->osync_error_print(&status
->error
);
415 case MEMBER_COMMITTED_ALL_ERROR
:
416 oss
<< " had an error while commiting changes: "
417 << cb
->m_priv
->osync_error_print(&status
->error
);
425 // call the status handler
426 if( oss
.str().size() && valid
) {
427 cb
->m_status
->MemberStatus(
428 cb
->m_priv
->osync_member_get_id(status
->member
),
429 cb
->m_priv
->osync_member_get_pluginname(status
->member
),
430 oss
.str(), error_event
);
433 catch( std::exception
&e
) {
434 cb
->m_status
->ReportError(
435 string("member_status error: ") + e
.what());
438 cb
->m_status
->ReportError(
439 "Unknown exception caught in member_status()");
444 void entry_status(OSyncEngine
*engine
, OSyncChangeUpdate
*status
, void *cbdata
)
446 CallbackBundle22
*cb
= (CallbackBundle22
*) cbdata
;
451 OSyncMember
*member
= cb
->m_priv
->osync_change_get_member(status
->change
);
452 bool error_event
= false;
454 switch( status
->type
)
456 case CHANGE_RECEIVED_INFO
:
457 oss
<< "Received an entry "
458 << cb
->m_priv
->osync_change_get_uid(status
->change
)
459 << " without data from member "
462 << cb
->m_priv
->osync_member_get_pluginname(member
)
465 << OSyncChangeType2String(cb
->m_priv
->osync_change_get_changetype(status
->change
));
467 case CHANGE_RECEIVED
:
468 oss
<< "Received an entry "
469 << cb
->m_priv
->osync_change_get_uid(status
->change
)
470 << " with data of size "
471 << cb
->m_priv
->osync_change_get_datasize(status
->change
)
475 << cb
->m_priv
->osync_member_get_pluginname(member
)
477 << OSyncChangeType2String(cb
->m_priv
->osync_change_get_changetype(status
->change
));
480 oss
<< "Sent an entry "
481 << cb
->m_priv
->osync_change_get_uid(status
->change
)
483 << cb
->m_priv
->osync_change_get_datasize(status
->change
)
487 << cb
->m_priv
->osync_member_get_pluginname(member
)
489 << OSyncChangeType2String(cb
->m_priv
->osync_change_get_changetype(status
->change
));
491 case CHANGE_WRITE_ERROR
:
493 oss
<< "Error writing entry "
494 << cb
->m_priv
->osync_change_get_uid(status
->change
)
498 << cb
->m_priv
->osync_member_get_pluginname(member
)
500 << cb
->m_priv
->osync_error_print(&status
->error
);
502 case CHANGE_RECV_ERROR
:
504 oss
<< "Error reading entry "
505 << cb
->m_priv
->osync_change_get_uid(status
->change
)
509 << cb
->m_priv
->osync_member_get_pluginname(member
)
511 << cb
->m_priv
->osync_error_print(&(status
->error
));
515 // call the status handler
516 if( oss
.str().size() ) {
517 cb
->m_status
->EntryStatus(oss
.str(), error_event
);
520 catch( std::exception
&e
) {
521 cb
->m_status
->ReportError(
522 string("entry_status error:") + e
.what());
525 cb
->m_status
->ReportError(
526 "Unknown exception caught in entry_status()");
530 void engine_status(OSyncEngine
*engine
, OSyncEngineUpdate
*status
, void *cbdata
)
532 CallbackBundle22
*cb
= (CallbackBundle22
*) cbdata
;
536 bool error_event
= false;
538 switch( status
->type
)
540 case ENG_PREV_UNCLEAN
:
541 oss
<< "The previous synchronization was unclean. Slow-syncing.";
543 case ENG_ENDPHASE_CON
:
544 oss
<< "All clients connected or error";
546 case ENG_END_CONFLICTS
:
547 oss
<< "All conflicts have been reported";
549 case ENG_ENDPHASE_READ
:
550 oss
<< "All clients sent changes or error";
552 case ENG_ENDPHASE_WRITE
:
553 oss
<< "All clients have written";
555 case ENG_ENDPHASE_DISCON
:
556 oss
<< "All clients have disconnected";
558 case ENG_SYNC_SUCCESSFULL
:
559 oss
<< "The sync was successful";
562 oss
<< "The sync failed: "
563 << cb
->m_priv
->osync_error_print(&status
->error
);
568 // call the status handler
569 if( oss
.str().size() )
570 cb
->m_status
->EngineStatus(oss
.str(),
572 status
->type
== ENG_PREV_UNCLEAN
);
574 catch( std::exception
&e
) {
575 cb
->m_status
->ReportError(
576 string("engine_status error: ") + e
.what());
579 cb
->m_status
->ReportError(
580 "Unknown exception caught in engine_status()");
584 void mapping_status(OSyncMappingUpdate
*status
, void *cbdata
)
586 CallbackBundle22
*cb
= (CallbackBundle22
*) cbdata
;
590 bool error_event
= false;
592 switch( status
->type
)
595 oss
<< "Mapping solved";
598 oss
<< "Mapping Synced";
600 case MAPPING_WRITE_ERROR
:
602 oss
<< "Mapping Write Error: "
603 << cb
->m_priv
->osync_error_print(&status
->error
);
607 // call the status handler
608 if( oss
.str().size() )
609 cb
->m_status
->MappingStatus(oss
.str(), error_event
);
611 catch( std::exception
&e
) {
612 cb
->m_status
->ReportError(
613 string("mapping_status error: ") + e
.what());
616 cb
->m_status
->ReportError(
617 "Unknown exception caught in mapping_status()");
621 void conflict_handler(OSyncEngine
*engine
, OSyncMapping
*mapping
, void *cbdata
)
623 CallbackBundle22
*cb
= (CallbackBundle22
*) cbdata
;
626 // build the SyncConflict object
627 SyncConflict22Private
scp(cb
->m_priv
, engine
, mapping
);
628 SyncConflict
conflict(scp
);
630 // append all conflicting changes as vector objects in the same
631 // order as the opensync library mapping
632 scp
.AppendChanges(conflict
);
634 // call the status handler
635 cb
->m_status
->HandleConflict(conflict
);
637 catch( std::exception
&e
) {
638 cb
->m_status
->ReportError(
639 string("Conflict not resolved. ") + e
.what());
642 cb
->m_status
->ReportError(
643 "Unknown exception caught in conflict_handler()");
648 /////////////////////////////////////////////////////////////////////////////
649 // OpenSync22 - public members
651 bool OpenSync22::symbols_loaded
= false;
653 OpenSync22::OpenSync22()
655 if( !Open("libosengine.so.0") )
656 throw DlError("Can't dlopen libosengine.so.0");
658 // the symbol table is now thoroughly polluted...
659 symbols_loaded
= true;
661 // store locally in case of constructor exception in LoadSym
662 std::auto_ptr
<OpenSync22Private
> p(new OpenSync22Private(*this));
664 // load all required symbols...
665 // we don't need to use try/catch here, since the base
666 // class destructor will clean up for us if LoadSym() throws
667 LoadSym(p
->osync_get_version
, "osync_get_version");
668 LoadSym(p
->osync_env_new
, "osync_env_new");
669 LoadSym(p
->osync_env_free
, "osync_env_free");
670 LoadSym(p
->osync_env_set_option
, "osync_env_set_option");
671 LoadSym(p
->osync_env_finalize
, "osync_env_finalize");
672 LoadSym(p
->osync_env_num_plugins
, "osync_env_num_plugins");
673 LoadSym(p
->osync_env_nth_plugin
, "osync_env_nth_plugin");
674 LoadSym(p
->osync_plugin_get_name
, "osync_plugin_get_name");
675 LoadSym(p
->osync_error_free
, "osync_error_free");
676 LoadSym(p
->osync_error_print
, "osync_error_print");
677 LoadSym(p
->osync_env_initialize
, "osync_env_initialize");
678 LoadSym(p
->osync_env_num_groups
, "osync_env_num_groups");
679 LoadSym(p
->osync_env_nth_group
, "osync_env_nth_group");
680 LoadSym(p
->osync_group_get_name
, "osync_group_get_name");
681 LoadSym(p
->osync_env_find_group
, "osync_env_find_group");
682 LoadSym(p
->osync_group_num_members
, "osync_group_num_members");
683 LoadSym(p
->osync_group_nth_member
, "osync_group_nth_member");
684 LoadSym(p
->osync_member_get_id
, "osync_member_get_id");
685 LoadSym(p
->osync_member_get_pluginname
, "osync_member_get_pluginname");
686 LoadSym(p
->osync_conv_env_new
, "osync_conv_env_new");
687 LoadSym(p
->osync_conv_env_free
, "osync_conv_env_free");
688 LoadSym(p
->osync_conv_num_objtypes
, "osync_conv_num_objtypes");
689 LoadSym(p
->osync_conv_nth_objtype
, "osync_conv_nth_objtype");
690 LoadSym(p
->osync_conv_num_objformats
, "osync_conv_num_objformats");
691 LoadSym(p
->osync_conv_nth_objformat
, "osync_conv_nth_objformat");
692 LoadSym(p
->osync_objformat_get_name
, "osync_objformat_get_name");
693 LoadSym(p
->osync_objtype_get_name
, "osync_objtype_get_name");
694 LoadSym(p
->osync_group_new
, "osync_group_new");
695 LoadSym(p
->osync_group_set_name
, "osync_group_set_name");
696 LoadSym(p
->osync_group_save
, "osync_group_save");
697 LoadSym(p
->osync_group_delete
, "osync_group_delete");
698 LoadSym(p
->osync_member_new
, "osync_member_new");
699 LoadSym(p
->osync_member_instance_plugin
,"osync_member_instance_plugin");
700 LoadSym(p
->osync_member_save
, "osync_member_save");
701 LoadSym(p
->osync_member_from_id
, "osync_member_from_id");
702 LoadSym(p
->osync_member_need_config
, "osync_member_need_config");
703 LoadSym(p
->osync_member_get_config_or_default
,
704 "osync_member_get_config_or_default");
705 LoadSym(p
->osync_member_set_config
, "osync_member_set_config");
706 LoadSym(p
->osengine_mapping_ignore_supported
,
707 "osengine_mapping_ignore_supported");
708 LoadSym(p
->osengine_mapping_check_timestamps
,
709 "osengine_mapping_check_timestamps");
710 LoadSym(p
->osengine_mapping_nth_change
, "osengine_mapping_nth_change");
711 LoadSym(p
->osengine_mapping_solve
, "osengine_mapping_solve");
712 LoadSym(p
->osengine_mapping_duplicate
, "osengine_mapping_duplicate");
713 LoadSym(p
->osengine_mapping_ignore_conflict
,
714 "osengine_mapping_ignore_conflict");
715 LoadSym(p
->osengine_mapping_solve_latest
,
716 "osengine_mapping_solve_latest");
717 LoadSym(p
->osync_change_get_uid
, "osync_change_get_uid");
718 LoadSym(p
->osengine_init
, "osengine_init");
719 LoadSym(p
->osync_change_get_member
, "osync_change_get_member");
720 LoadSym(p
->osync_change_get_datasize
, "osync_change_get_datasize");
721 LoadSym(p
->osengine_new
, "osengine_new");
722 LoadSym(p
->osengine_free
, "osengine_free");
723 LoadSym(p
->osengine_finalize
, "osengine_finalize");
724 LoadSym(p
->osengine_sync_and_block
, "osengine_sync_and_block");
725 LoadSym(p
->osengine_set_memberstatus_callback
,
726 "osengine_set_memberstatus_callback");
727 LoadSym(p
->osengine_set_changestatus_callback
,
728 "osengine_set_changestatus_callback");
729 LoadSym(p
->osengine_set_enginestatus_callback
,
730 "osengine_set_enginestatus_callback");
731 LoadSym(p
->osengine_set_mappingstatus_callback
,
732 "osengine_set_mappingstatus_callback");
733 LoadSym(p
->osengine_set_conflict_callback
,
734 "osengine_set_conflict_callback");
735 LoadSym(p
->osengine_mapping_num_changes
,
736 "osengine_mapping_num_changes");
737 LoadSym(p
->osync_change_get_changetype
, "osync_change_get_changetype");
738 LoadSym(p
->osync_change_get_printable
, "osync_change_get_printable");
739 LoadSym(p
->osync_group_set_objtype_enabled
,
740 "osync_group_set_objtype_enabled");
742 // do common initialization of opensync environment
743 SetupEnvironment(p
.get());
745 // this pointer is ours now
746 m_priv
= p
.release();
749 OpenSync22::~OpenSync22()
751 // clean up opensync environment, closing plugins, etc.
753 m_priv
->osync_env_finalize(m_priv
->env
, NULL
);
754 m_priv
->osync_env_free(m_priv
->env
);
757 // free private class data
762 void OpenSync22::SetupEnvironment(OpenSync22Private
*p
)
764 // we are fully responsible for this pointer, since
765 // we run inside the constructor... only on success
766 // will responsibility be transferred to the destructor
767 p
->env
= p
->osync_env_new();
769 throw std::runtime_error("Error allocating opensync 0.22 environment");
771 p
->osync_env_set_option(p
->env
, "GROUPS_DIRECTORY", NULL
);
772 p
->osync_env_set_option(p
->env
, "LOAD_GROUPS", "TRUE");
773 p
->osync_env_set_option(p
->env
, "LOAD_PLUGINS", "TRUE");
774 p
->osync_env_set_option(p
->env
, "LOAD_FORMATS", "TRUE");
776 OSyncError
*error
= NULL
;
777 if( !p
->osync_env_initialize(p
->env
, &error
) ) {
778 // grab error message
779 std::runtime_error
err(m_priv
->osync_error_print(&error
));
782 p
->osync_error_free(&error
);
783 p
->osync_env_free(m_priv
->env
);
790 const char* OpenSync22::GetVersion() const
792 return m_priv
->osync_get_version();
795 const char* OpenSync22::GetEngineName() const
800 void OpenSync22::GetPluginNames(string_list_type
&plugins
)
806 for( int i
= 0; i
< m_priv
->osync_env_num_plugins(m_priv
->env
); i
++) {
807 p
= m_priv
->osync_env_nth_plugin(m_priv
->env
, i
);
808 plugins
.push_back(m_priv
->osync_plugin_get_name(p
));
812 void OpenSync22::GetFormats(format_list_type
&formats
)
817 // cycle through all object types and simulate a 0.4x-like
818 // list based on the attached formats
820 OSyncFormatEnv
*fenv
= m_priv
->osync_conv_env_new(m_priv
->env
);
822 throw std::runtime_error("GetFormats(): Unable to load format environment in GetFormats (22)");
825 for( int i
= 0; i
< m_priv
->osync_conv_num_objtypes(fenv
); i
++ ) {
826 OSyncObjType
*type
= m_priv
->osync_conv_nth_objtype(fenv
, i
);
828 for( int i
= 0; i
< m_priv
->osync_conv_num_objformats(type
); i
++ ) {
829 OSyncObjFormat
*format
= m_priv
->osync_conv_nth_objformat(type
, i
);
830 const char *objformat_name
= m_priv
->osync_objformat_get_name(format
);
832 if( !formats
.Find(objformat_name
) ) {
834 new_format
.name
= objformat_name
;
835 new_format
.object_type
= m_priv
->osync_objtype_get_name(type
);
836 formats
.push_back(new_format
);
841 m_priv
->osync_conv_env_free(fenv
);
844 void OpenSync22::GetGroupNames(string_list_type
&groups
)
850 for( int i
= 0; i
< m_priv
->osync_env_num_groups(m_priv
->env
); i
++ ) {
851 g
= m_priv
->osync_env_nth_group(m_priv
->env
, i
);
852 groups
.push_back(m_priv
->osync_group_get_name(g
));
856 void OpenSync22::GetMembers(const std::string
&group_name
,
857 member_list_type
&members
)
862 OSyncGroup
*group
= m_priv
->osync_env_find_group(m_priv
->env
, group_name
.c_str());
864 throw std::runtime_error("GetMembers(): Unable to find group with name: " + group_name
);
867 for( int i
= 0; i
< m_priv
->osync_group_num_members(group
); i
++ ) {
868 OSyncMember
*member
= m_priv
->osync_group_nth_member(group
, i
);
872 new_member
.group_name
= group_name
;
873 new_member
.id
= m_priv
->osync_member_get_id(member
);
874 new_member
.plugin_name
= m_priv
->osync_member_get_pluginname(member
);
876 // we are switching opensync's long long int ID to
877 // our long... to double check they are equal after
879 if( new_member
.id
!= m_priv
->osync_member_get_id(member
) ) {
880 throw std::logic_error("GetMembers(): OpenSync's member ID is too large to fit in OpenSyncAPI (22)");
883 // add to member list
884 members
.push_back(new_member
);
888 void OpenSync22::AddGroup(const std::string
&group_name
)
890 if( m_priv
->osync_env_find_group(m_priv
->env
, group_name
.c_str()) )
891 throw std::runtime_error("AddGroup(): Group already exists: " + group_name
);
893 OSyncGroup
*group
= m_priv
->osync_group_new(m_priv
->env
);
894 m_priv
->osync_group_set_name(group
, group_name
.c_str());
896 OSyncError
*error
= NULL
;
897 if( !m_priv
->osync_group_save(group
, &error
) ) {
898 // grab error message
899 std::runtime_error
err(string("AddGroup(): Unable to save group: ") + m_priv
->osync_error_print(&error
));
902 m_priv
->osync_error_free(&error
);
908 void OpenSync22::DeleteGroup(const std::string
&group_name
)
910 OSyncGroup
*group
= m_priv
->osync_env_find_group(m_priv
->env
, group_name
.c_str());
912 throw std::runtime_error("DeleteGroup(): Group not found: " + group_name
);
914 OSyncError
*error
= NULL
;
915 if( !m_priv
->osync_group_delete(group
, &error
) ) {
916 std::runtime_error
err(string("DeleteGroup(): Unable to delete group: ") + m_priv
->osync_error_print(&error
));
917 m_priv
->osync_error_free(&error
);
922 Converter
& OpenSync22::GetConverter()
924 return m_priv
->converter
;
927 long OpenSync22::AddMember(const std::string
&group_name
,
928 const std::string
&plugin_name
,
929 const std::string
&member_name
)
931 OSyncGroup
*group
= m_priv
->osync_env_find_group(m_priv
->env
, group_name
.c_str());
933 throw std::runtime_error("AddMember(): Group not found: " + group_name
);
935 OSyncMember
*member
= m_priv
->osync_member_new(group
);
937 OSyncError
*error
= NULL
;
938 if( !m_priv
->osync_member_instance_plugin(member
, plugin_name
.c_str(), &error
) ) {
939 std::runtime_error
err(string("AddMember(): Unable to connect plugin with member ") + member_name
+ "/" + plugin_name
+ ": " + m_priv
->osync_error_print(&error
));
940 m_priv
->osync_error_free(&error
);
944 if( !m_priv
->osync_member_save(member
, &error
) ) {
945 std::runtime_error
err(string("AddMember(): Unable to save member ") + member_name
+ "/" + plugin_name
+ ": " + m_priv
->osync_error_print(&error
));
946 m_priv
->osync_error_free(&error
);
950 return m_priv
->osync_member_get_id(member
);
953 bool OpenSync22::IsConfigurable(const std::string
&group_name
,
956 OSyncGroup
*group
= m_priv
->osync_env_find_group(m_priv
->env
, group_name
.c_str());
958 throw std::runtime_error("Group not found: " + group_name
);
960 OSyncMember
*member
= m_priv
->osync_member_from_id(group
, member_id
);
963 oss
<< "IsConfigurable(): Member " << member_id
<< " not found.";
964 throw std::runtime_error(oss
.str());
967 OSyncConfigurationTypes type
= NO_CONFIGURATION
;
968 OSyncError
*error
= NULL
;
969 if( !m_priv
->osync_member_need_config(member
, &type
, &error
) ) {
970 std::runtime_error
err(string("Unable to determine needed config: ") + m_priv
->osync_error_print(&error
));
971 m_priv
->osync_error_free(&error
);
975 return type
!= NO_CONFIGURATION
;
978 std::string
OpenSync22::GetConfiguration(const std::string
&group_name
,
981 if( !IsConfigurable(group_name
, member_id
) ) {
983 oss
<< "GetConfiguration(): Member " << member_id
<< " of group '" << group_name
<< "' does not accept configuration.";
984 throw std::runtime_error(oss
.str());
987 OSyncGroup
*group
= m_priv
->osync_env_find_group(m_priv
->env
, group_name
.c_str());
989 throw std::runtime_error("GetConfiguration(): Group not found: " + group_name
);
991 OSyncMember
*member
= m_priv
->osync_member_from_id(group
, member_id
);
994 oss
<< "GetConfiguration(): Member " << member_id
<< " not found.";
995 throw std::runtime_error(oss
.str());
998 OSyncError
*error
= NULL
;
1001 if( !m_priv
->osync_member_get_config_or_default(member
, &data
, &size
, &error
)) {
1002 std::runtime_error
err(string("GetConfiguration(): Unable to retrieve config: ") + m_priv
->osync_error_print(&error
));
1003 m_priv
->osync_error_free(&error
);
1007 std::string
config(data
, size
);
1013 void OpenSync22::SetConfiguration(const std::string
&group_name
,
1015 const std::string
&config_data
)
1017 if( !IsConfigurable(group_name
, member_id
) ) {
1019 oss
<< "SetConfiguration(): Member " << member_id
<< " of group '" << group_name
<< "' does not accept configuration.";
1020 throw std::runtime_error(oss
.str());
1023 OSyncGroup
*group
= m_priv
->osync_env_find_group(m_priv
->env
, group_name
.c_str());
1025 throw std::runtime_error("SetConfiguration(): Group not found: " + group_name
);
1027 OSyncMember
*member
= m_priv
->osync_member_from_id(group
, member_id
);
1030 oss
<< "SetConfiguration(): Member " << member_id
<< " not found.";
1031 throw std::runtime_error(oss
.str());
1034 m_priv
->osync_member_set_config(member
, config_data
.c_str(), config_data
.size());
1036 OSyncError
*error
= NULL
;
1037 if( !m_priv
->osync_member_save(member
, &error
) ) {
1038 std::runtime_error
err(string("SetConfiguration(): Unable to save member's config: ") + m_priv
->osync_error_print(&error
));
1039 m_priv
->osync_error_free(&error
);
1044 void OpenSync22::Discover(const std::string
&group_name
)
1046 // Discover is a successful noop on 0.22
1049 void OpenSync22::Sync(const std::string
&group_name
,
1050 SyncStatus
&status_callback
,
1051 Config::pst_type sync_types
)
1053 OSyncGroup
*group
= m_priv
->osync_env_find_group(m_priv
->env
, group_name
.c_str());
1055 throw std::runtime_error("Sync(): Group not found: " + group_name
);
1057 // enable/disable each objtype, as per sync_types
1058 if( !(sync_types
& PST_DO_NOT_SET
) ) {
1059 cerr
<< "enabling objtypes: " << sync_types
<< endl
;
1060 m_priv
->osync_group_set_objtype_enabled(group
, "contact",
1061 (sync_types
& PST_CONTACTS
) ? TRUE
: FALSE
);
1062 m_priv
->osync_group_set_objtype_enabled(group
, "event",
1063 (sync_types
& PST_EVENTS
) ? TRUE
: FALSE
);
1064 m_priv
->osync_group_set_objtype_enabled(group
, "note",
1065 (sync_types
& PST_NOTES
) ? TRUE
: FALSE
);
1066 m_priv
->osync_group_set_objtype_enabled(group
, "todo",
1067 (sync_types
& PST_TODOS
) ? TRUE
: FALSE
);
1070 OSyncError
*error
= NULL
;
1071 EngineHandle
engine(m_priv
->osengine_free
);
1072 engine
= m_priv
->osengine_new(group
, &error
);
1073 if( !engine
.get() ) {
1074 std::ostringstream oss
;
1075 oss
<< "Error while synchronizing: "
1076 << m_priv
->osync_error_print(&error
);
1077 m_priv
->osync_error_free(&error
);
1078 throw std::runtime_error(oss
.str());
1081 CallbackBundle22
cbdata(m_priv
, status_callback
);
1083 m_priv
->osengine_set_memberstatus_callback(engine
.get(),
1084 &member_status
, &cbdata
);
1085 m_priv
->osengine_set_changestatus_callback(engine
.get(),
1086 &entry_status
, &cbdata
);
1087 m_priv
->osengine_set_enginestatus_callback(engine
.get(),
1088 &engine_status
, &cbdata
);
1089 m_priv
->osengine_set_mappingstatus_callback(engine
.get(),
1090 &mapping_status
, &cbdata
);
1091 m_priv
->osengine_set_conflict_callback(engine
.get(),
1092 &conflict_handler
, &cbdata
);
1094 if( !m_priv
->osengine_init(engine
.get(), &error
) ) {
1096 oss
<< "Error initializing osengine: "
1097 << m_priv
->osync_error_print(&error
);
1098 m_priv
->osync_error_free(&error
);
1099 throw std::runtime_error(oss
.str());
1102 // successfully initialized, so finalize must be called
1103 EngineHandle
initialized_engine(m_priv
->osengine_finalize
);
1104 initialized_engine
= engine
.get();
1106 if( !m_priv
->osengine_sync_and_block(engine
.get(), &error
) ) {
1108 oss
<< "Error during sync: "
1109 << m_priv
->osync_error_print(&error
);
1110 m_priv
->osync_error_free(&error
);
1111 throw std::runtime_error(oss
.str());
1115 } // namespace OpenSync