3 /// Wrapper class for opensync 0.22 syncing behaviour
7 Copyright (C) 2009-2013, 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>
31 #include <barry/common.h>
38 // use relative paths to backtrack enough to specify only 0.22 includes
39 #include <../opensync-1.0/opensync/opensync.h>
40 #include <../opensync-1.0/osengine/engine.h>
43 using namespace Barry
;
47 typedef Barry::vLateSmartPtr
<OSyncEngine
, void(*)(OSyncEngine
*)> EngineHandle
;
49 class OpenSync22Private
53 const char* (*osync_get_version
)();
54 OSyncEnv
* (*osync_env_new
)();
55 void (*osync_env_free
)(OSyncEnv
*env
);
56 void (*osync_env_set_option
)(OSyncEnv
*env
,
57 const char *name
, const char *value
);
58 osync_bool (*osync_env_finalize
)(OSyncEnv
*env
,
60 int (*osync_env_num_plugins
)(OSyncEnv
*env
);
61 OSyncPlugin
* (*osync_env_nth_plugin
)(OSyncEnv
*env
, int nth
);
62 const char* (*osync_plugin_get_name
)(OSyncPlugin
*plugin
);
63 void (*osync_error_free
)(OSyncError
**error
);
64 const char* (*osync_error_print
)(OSyncError
**error
);
65 osync_bool (*osync_env_initialize
)(OSyncEnv
*env
,
67 int (*osync_env_num_groups
)(OSyncEnv
*env
);
68 OSyncGroup
* (*osync_env_nth_group
)(OSyncEnv
*env
, int nth
);
69 const char* (*osync_group_get_name
)(OSyncGroup
*group
);
70 OSyncGroup
* (*osync_env_find_group
)(OSyncEnv
*env
,
72 int (*osync_group_num_members
)(OSyncGroup
*group
);
73 OSyncMember
* (*osync_group_nth_member
)(OSyncGroup
*group
,
75 long long int (*osync_member_get_id
)(OSyncMember
*member
);
76 const char* (*osync_member_get_pluginname
)(
78 OSyncFormatEnv
* (*osync_conv_env_new
)(OSyncEnv
*env
);
79 void (*osync_conv_env_free
)(OSyncFormatEnv
*env
);
80 int (*osync_conv_num_objtypes
)(OSyncFormatEnv
*env
);
81 OSyncObjType
* (*osync_conv_nth_objtype
)(OSyncFormatEnv
*env
,
83 int (*osync_conv_num_objformats
)(
85 OSyncObjFormat
* (*osync_conv_nth_objformat
)(OSyncObjType
*type
,
87 const char* (*osync_objformat_get_name
)(
88 OSyncObjFormat
*format
);
89 const char* (*osync_objtype_get_name
)(OSyncObjType
*type
);
90 OSyncGroup
* (*osync_group_new
)(OSyncEnv
*env
);
91 void (*osync_group_set_name
)(OSyncGroup
*group
,
93 osync_bool (*osync_group_save
)(OSyncGroup
*group
,
95 osync_bool (*osync_group_delete
)(OSyncGroup
*group
,
97 OSyncMember
* (*osync_member_new
)(OSyncGroup
*group
);
98 osync_bool (*osync_member_instance_plugin
)(
100 const char *pluginname
,
102 osync_bool (*osync_member_save
)(OSyncMember
*member
,
104 OSyncMember
* (*osync_member_from_id
)(OSyncGroup
*group
,
106 osync_bool (*osync_member_need_config
)(OSyncMember
*member
,
107 OSyncConfigurationTypes
*type
,
109 osync_bool (*osync_member_get_config_or_default
)(
111 char **data
, int *size
,
113 void (*osync_member_set_config
)(OSyncMember
*member
,
114 const char *data
, int size
);
115 osync_bool (*osengine_mapping_ignore_supported
)(
117 OSyncMapping
*mapping
);
118 osync_bool (*osengine_mapping_check_timestamps
)(
120 OSyncMapping
*mapping
,
122 OSyncChange
* (*osengine_mapping_nth_change
)(
123 OSyncMapping
*mapping
, int nth
);
124 void (*osengine_mapping_solve
)(OSyncEngine
*engine
,
125 OSyncMapping
*mapping
,
126 OSyncChange
*change
);
127 void (*osengine_mapping_duplicate
)(
129 OSyncMapping
*dupe_mapping
);
130 osync_bool (*osengine_mapping_ignore_conflict
)(
132 OSyncMapping
*mapping
,
134 osync_bool (*osengine_mapping_solve_latest
)(
136 OSyncMapping
*mapping
,
138 const char* (*osync_change_get_uid
)(OSyncChange
*change
);
139 osync_bool (*osengine_init
)(OSyncEngine
*engine
,
141 OSyncMember
* (*osync_change_get_member
)(OSyncChange
*change
);
142 int (*osync_change_get_datasize
)(
143 OSyncChange
*change
);
144 OSyncEngine
* (*osengine_new
)(OSyncGroup
*group
,
146 void (*osengine_free
)(OSyncEngine
*engine
);
147 void (*osengine_finalize
)(OSyncEngine
*engine
);
148 osync_bool (*osengine_sync_and_block
)(OSyncEngine
*engine
,
150 void (*osengine_set_memberstatus_callback
)(
152 void (* function
) (OSyncMemberUpdate
*,
155 void (*osengine_set_changestatus_callback
)(
157 void (* function
) (OSyncEngine
*,
161 void (*osengine_set_enginestatus_callback
)(
163 void (* function
) (OSyncEngine
*,
167 void (*osengine_set_mappingstatus_callback
)(
169 void (* function
) (OSyncMappingUpdate
*,
172 void (*osengine_set_conflict_callback
)(
174 void (* function
) (OSyncEngine
*,
178 int (*osengine_mapping_num_changes
)(
179 OSyncMapping
*mapping
);
180 OSyncChangeType (*osync_change_get_changetype
)(
181 OSyncChange
*change
);
182 char* (*osync_change_get_printable
)(
183 OSyncChange
*change
);
184 void (*osync_group_set_objtype_enabled
)(
186 const char *objtypestr
,
192 Converter22 converter
;
194 OpenSync22Private(OpenSync22
&api
)
201 class SyncConflict22Private
: public SyncConflictPrivateBase
203 OpenSync22Private
*m_priv
;
204 OSyncEngine
*m_engine
;
205 OSyncMapping
*m_mapping
;
208 SyncConflict22Private(OpenSync22Private
*priv
,
209 OSyncEngine
*engine
, OSyncMapping
*mapping
);
210 ~SyncConflict22Private();
212 virtual bool IsAbortSupported() const;
213 virtual bool IsIgnoreSupported() const;
214 virtual bool IsKeepNewerSupported() const;
216 virtual void Select(int change_id
); // takes id of SyncChange object
217 virtual void Abort(); // not supported in 0.22
218 virtual void Duplicate();
219 virtual void Ignore();
220 virtual void KeepNewer();
222 void AppendChanges(std::vector
<SyncChange
> &list
);
225 struct CallbackBundle22
227 OpenSync22Private
*m_priv
;
228 SyncStatus
*m_status
;
230 CallbackBundle22(OpenSync22Private
*priv
, SyncStatus
&status
)
237 void member_status(OSyncMemberUpdate
*, void *);
238 void entry_status(OSyncEngine
*, OSyncChangeUpdate
*, void *);
239 void engine_status(OSyncEngine
*, OSyncEngineUpdate
*,void *);
240 void mapping_status(OSyncMappingUpdate
*, void *);
241 void conflict_handler(OSyncEngine
*, OSyncMapping
*, void *);
244 /////////////////////////////////////////////////////////////////////////////
245 // Static helper functions
247 static const char *OSyncChangeType2String(OSyncChangeType c
)
250 case CHANGE_ADDED
: return _C("ADDED");
251 case CHANGE_UNMODIFIED
: return _C("UNMODIFIED");
252 case CHANGE_DELETED
: return _C("DELETED");
253 case CHANGE_MODIFIED
: return _C("MODIFIED");
255 case CHANGE_UNKNOWN
: return "?";
259 /////////////////////////////////////////////////////////////////////////////
260 // SyncConflict22Private member functions
262 SyncConflict22Private::SyncConflict22Private(OpenSync22Private
*priv
,
263 OSyncEngine
*engine
, OSyncMapping
*mapping
)
270 SyncConflict22Private::~SyncConflict22Private()
274 bool SyncConflict22Private::IsAbortSupported() const
276 return false; // Abort not explicitly supported in 0.22
279 bool SyncConflict22Private::IsIgnoreSupported() const
281 return m_priv
->osengine_mapping_ignore_supported(m_engine
, m_mapping
);
284 bool SyncConflict22Private::IsKeepNewerSupported() const
286 return m_priv
->osengine_mapping_check_timestamps(m_engine
, m_mapping
, NULL
);
289 void SyncConflict22Private::Select(int change_id
)
291 OSyncChange
*change
= m_priv
->osengine_mapping_nth_change(m_mapping
, change_id
);
293 throw std::runtime_error(_C("Bad change_id, or error getting nth change object."));
296 m_priv
->osengine_mapping_solve(m_engine
, m_mapping
, change
);
299 void SyncConflict22Private::Abort()
301 throw std::logic_error("Conflict::Abort() not supported in 0.22");
304 void SyncConflict22Private::Duplicate()
306 m_priv
->osengine_mapping_duplicate(m_engine
, m_mapping
);
309 void SyncConflict22Private::Ignore()
311 if( !IsIgnoreSupported() )
312 throw std::logic_error("Ignore not supported, yet Ignore() called.");
314 OSyncError
*error
= NULL
;
315 if( !m_priv
->osengine_mapping_ignore_conflict(m_engine
, m_mapping
, &error
)) {
317 oss
<< _C("Conflict not ignored: ")
318 << m_priv
->osync_error_print(&error
);
319 m_priv
->osync_error_free(&error
);
320 throw std::runtime_error(oss
.str());
324 void SyncConflict22Private::KeepNewer()
326 if( !IsKeepNewerSupported() )
327 throw std::logic_error("Keep Newer not supported, yet KeepNewer() called.");
329 OSyncError
*error
= NULL
;
330 if( !m_priv
->osengine_mapping_solve_latest(m_engine
, m_mapping
, &error
)) {
332 oss
<< _C("Conflict not resolved: ")
333 << m_priv
->osync_error_print(&error
);
334 m_priv
->osync_error_free(&error
);
335 throw std::runtime_error(oss
.str());
339 void SyncConflict22Private::AppendChanges(std::vector
<SyncChange
> &list
)
341 for( int i
= 0; i
< m_priv
->osengine_mapping_num_changes(m_mapping
); i
++ ) {
342 OSyncChange
*change
= m_priv
->osengine_mapping_nth_change(m_mapping
, i
);
343 if( m_priv
->osync_change_get_changetype(change
) != CHANGE_UNKNOWN
) {
347 char *printable
= m_priv
->osync_change_get_printable(change
);
349 entry
.printable_data
= printable
;
353 OSyncMember
*member
= m_priv
->osync_change_get_member(change
);
356 entry
.member_id
= m_priv
->osync_member_get_id(member
);
357 entry
.plugin_name
= m_priv
->osync_member_get_pluginname(member
);
358 entry
.uid
= m_priv
->osync_change_get_uid(change
);
361 list
.push_back(entry
);
367 /////////////////////////////////////////////////////////////////////////////
368 // Callback functions
370 void member_status(OSyncMemberUpdate
*status
, void *cbdata
)
372 CallbackBundle22
*cb
= (CallbackBundle22
*) cbdata
;
375 bool error_event
= false;
380 switch( status
->type
)
382 case MEMBER_CONNECTED
:
383 fmt
= _C("Member %lld (%s) just connected");
385 case MEMBER_DISCONNECTED
:
386 fmt
= _C("Member %lld (%s) just disconnected");
388 case MEMBER_SENT_CHANGES
:
389 fmt
= _C("Member %lld (%s) just sent all changes");
391 case MEMBER_COMMITTED_ALL
:
392 fmt
= _C("Member %lld (%s) committed all changes");
394 case MEMBER_CONNECT_ERROR
:
395 fmt
= _C("Member %lld (%s) had an error while connecting: %s");
396 trailer
= cb
->m_priv
->osync_error_print(&status
->error
);
398 case MEMBER_GET_CHANGES_ERROR
:
399 fmt
= _C("Member %lld (%s) had an error while getting changes: %s");
400 trailer
= cb
->m_priv
->osync_error_print(&status
->error
);
403 case MEMBER_SYNC_DONE_ERROR
:
404 fmt
= _C("Member %lld (%s) had an error while calling sync done: %s");
405 trailer
= cb
->m_priv
->osync_error_print(&status
->error
);
408 case MEMBER_DISCONNECT_ERROR
:
409 fmt
= _C("Member %lld (%s) had an error while disconnecting: %s");
410 trailer
= cb
->m_priv
->osync_error_print(&status
->error
);
413 case MEMBER_COMMITTED_ALL_ERROR
:
414 fmt
= _C("Member %lld (%s) had an error while commiting changes: %s");
415 trailer
= cb
->m_priv
->osync_error_print(&status
->error
);
423 // combine the message
424 string msg
= string_vprintf(fmt
.c_str(),
425 cb
->m_priv
->osync_member_get_id(status
->member
),
426 cb
->m_priv
->osync_member_get_pluginname(status
->member
),
429 // call the status handler
430 if( msg
.size() && valid
) {
431 cb
->m_status
->MemberStatus(
432 cb
->m_priv
->osync_member_get_id(status
->member
),
433 cb
->m_priv
->osync_member_get_pluginname(status
->member
),
437 catch( std::exception
&e
) {
438 cb
->m_status
->ReportError(
439 string(_C("member_status error: ")) + e
.what());
442 cb
->m_status
->ReportError(
443 _C("Unknown exception caught in member_status()"));
448 void entry_status(OSyncEngine
*engine
, OSyncChangeUpdate
*status
, void *cbdata
)
450 CallbackBundle22
*cb
= (CallbackBundle22
*) cbdata
;
453 OSyncMember
*member
= cb
->m_priv
->osync_change_get_member(status
->change
);
454 bool error_event
= false;
458 switch( status
->type
)
460 case CHANGE_RECEIVED_INFO
:
461 msg
= string_vprintf(_C("Received an entry %s without data from member %d (%s). Change type: %s"),
462 cb
->m_priv
->osync_change_get_uid(status
->change
),
464 cb
->m_priv
->osync_member_get_pluginname(member
),
465 OSyncChangeType2String(cb
->m_priv
->osync_change_get_changetype(status
->change
)));
467 case CHANGE_RECEIVED
:
468 msg
= string_vprintf(_C("Received an entry %s with data of size %d from member %d (%s). Change type: %s"),
469 cb
->m_priv
->osync_change_get_uid(status
->change
),
470 cb
->m_priv
->osync_change_get_datasize(status
->change
),
472 cb
->m_priv
->osync_member_get_pluginname(member
),
473 OSyncChangeType2String(cb
->m_priv
->osync_change_get_changetype(status
->change
)));
476 msg
= string_vprintf(_C("Sent an entry %s of size %d to member %d (%s). Change type: %s"),
477 cb
->m_priv
->osync_change_get_uid(status
->change
),
478 cb
->m_priv
->osync_change_get_datasize(status
->change
),
480 cb
->m_priv
->osync_member_get_pluginname(member
),
481 OSyncChangeType2String(cb
->m_priv
->osync_change_get_changetype(status
->change
)));
483 case CHANGE_WRITE_ERROR
:
485 msg
= string_vprintf(_C("Error writing entry %s to member %d (%s): %s"),
486 cb
->m_priv
->osync_change_get_uid(status
->change
),
488 cb
->m_priv
->osync_member_get_pluginname(member
),
489 cb
->m_priv
->osync_error_print(&status
->error
));
491 case CHANGE_RECV_ERROR
:
493 msg
= string_vprintf(_C("Error reading entry %s from member %d (%s): %s"),
494 cb
->m_priv
->osync_change_get_uid(status
->change
),
496 cb
->m_priv
->osync_member_get_pluginname(member
),
497 cb
->m_priv
->osync_error_print(&(status
->error
)));
501 // call the status handler
503 cb
->m_status
->EntryStatus(msg
, error_event
);
506 catch( std::exception
&e
) {
507 cb
->m_status
->ReportError(
508 string(_C("entry_status error:")) + e
.what());
511 cb
->m_status
->ReportError(
512 _C("Unknown exception caught in entry_status()"));
516 void engine_status(OSyncEngine
*engine
, OSyncEngineUpdate
*status
, void *cbdata
)
518 CallbackBundle22
*cb
= (CallbackBundle22
*) cbdata
;
522 bool error_event
= false;
524 switch( status
->type
)
526 case ENG_PREV_UNCLEAN
:
527 oss
<< _C("The previous synchronization was unclean. Slow-syncing.");
529 case ENG_ENDPHASE_CON
:
530 oss
<< _C("All clients connected or error");
532 case ENG_END_CONFLICTS
:
533 oss
<< _C("All conflicts have been reported");
535 case ENG_ENDPHASE_READ
:
536 oss
<< _C("All clients sent changes or error");
538 case ENG_ENDPHASE_WRITE
:
539 oss
<< _C("All clients have written");
541 case ENG_ENDPHASE_DISCON
:
542 oss
<< _C("All clients have disconnected");
544 case ENG_SYNC_SUCCESSFULL
:
545 oss
<< _C("The sync was successful");
548 oss
<< _C("The sync failed: ")
549 << cb
->m_priv
->osync_error_print(&status
->error
);
554 // call the status handler
555 if( oss
.str().size() )
556 cb
->m_status
->EngineStatus(oss
.str(),
558 status
->type
== ENG_PREV_UNCLEAN
);
560 catch( std::exception
&e
) {
561 cb
->m_status
->ReportError(
562 string(_C("engine_status error: ")) + e
.what());
565 cb
->m_status
->ReportError(
566 _C("Unknown exception caught in engine_status()"));
570 void mapping_status(OSyncMappingUpdate
*status
, void *cbdata
)
572 CallbackBundle22
*cb
= (CallbackBundle22
*) cbdata
;
576 bool error_event
= false;
578 switch( status
->type
)
581 oss
<< _C("Mapping solved");
584 oss
<< _C("Mapping Synced");
586 case MAPPING_WRITE_ERROR
:
588 oss
<< _C("Mapping Write Error: ")
589 << cb
->m_priv
->osync_error_print(&status
->error
);
593 // call the status handler
594 if( oss
.str().size() )
595 cb
->m_status
->MappingStatus(oss
.str(), error_event
);
597 catch( std::exception
&e
) {
598 cb
->m_status
->ReportError(
599 string(_C("mapping_status error: ")) + e
.what());
602 cb
->m_status
->ReportError(
603 _C("Unknown exception caught in mapping_status()"));
607 void conflict_handler(OSyncEngine
*engine
, OSyncMapping
*mapping
, void *cbdata
)
609 CallbackBundle22
*cb
= (CallbackBundle22
*) cbdata
;
612 // build the SyncConflict object
613 SyncConflict22Private
scp(cb
->m_priv
, engine
, mapping
);
614 SyncConflict
conflict(scp
);
616 // append all conflicting changes as vector objects in the same
617 // order as the opensync library mapping
618 scp
.AppendChanges(conflict
);
620 // call the status handler
621 cb
->m_status
->HandleConflict(conflict
);
623 catch( std::exception
&e
) {
624 cb
->m_status
->ReportError(
625 string(_C("Conflict not resolved. ")) + e
.what());
628 cb
->m_status
->ReportError(
629 _C("Unknown exception caught in conflict_handler()"));
634 /////////////////////////////////////////////////////////////////////////////
635 // OpenSync22 - public members
637 bool OpenSync22::symbols_loaded
= false;
639 OpenSync22::OpenSync22()
641 if( !Open("libosengine.so.0") )
642 throw DlError("Can't dlopen libosengine.so.0");
644 // the symbol table is now thoroughly polluted...
645 symbols_loaded
= true;
647 // store locally in case of constructor exception in LoadSym
648 std::auto_ptr
<OpenSync22Private
> p(new OpenSync22Private(*this));
650 // load all required symbols...
651 // we don't need to use try/catch here, since the base
652 // class destructor will clean up for us if LoadSym() throws
653 LoadSym(p
->osync_get_version
, "osync_get_version");
654 LoadSym(p
->osync_env_new
, "osync_env_new");
655 LoadSym(p
->osync_env_free
, "osync_env_free");
656 LoadSym(p
->osync_env_set_option
, "osync_env_set_option");
657 LoadSym(p
->osync_env_finalize
, "osync_env_finalize");
658 LoadSym(p
->osync_env_num_plugins
, "osync_env_num_plugins");
659 LoadSym(p
->osync_env_nth_plugin
, "osync_env_nth_plugin");
660 LoadSym(p
->osync_plugin_get_name
, "osync_plugin_get_name");
661 LoadSym(p
->osync_error_free
, "osync_error_free");
662 LoadSym(p
->osync_error_print
, "osync_error_print");
663 LoadSym(p
->osync_env_initialize
, "osync_env_initialize");
664 LoadSym(p
->osync_env_num_groups
, "osync_env_num_groups");
665 LoadSym(p
->osync_env_nth_group
, "osync_env_nth_group");
666 LoadSym(p
->osync_group_get_name
, "osync_group_get_name");
667 LoadSym(p
->osync_env_find_group
, "osync_env_find_group");
668 LoadSym(p
->osync_group_num_members
, "osync_group_num_members");
669 LoadSym(p
->osync_group_nth_member
, "osync_group_nth_member");
670 LoadSym(p
->osync_member_get_id
, "osync_member_get_id");
671 LoadSym(p
->osync_member_get_pluginname
, "osync_member_get_pluginname");
672 LoadSym(p
->osync_conv_env_new
, "osync_conv_env_new");
673 LoadSym(p
->osync_conv_env_free
, "osync_conv_env_free");
674 LoadSym(p
->osync_conv_num_objtypes
, "osync_conv_num_objtypes");
675 LoadSym(p
->osync_conv_nth_objtype
, "osync_conv_nth_objtype");
676 LoadSym(p
->osync_conv_num_objformats
, "osync_conv_num_objformats");
677 LoadSym(p
->osync_conv_nth_objformat
, "osync_conv_nth_objformat");
678 LoadSym(p
->osync_objformat_get_name
, "osync_objformat_get_name");
679 LoadSym(p
->osync_objtype_get_name
, "osync_objtype_get_name");
680 LoadSym(p
->osync_group_new
, "osync_group_new");
681 LoadSym(p
->osync_group_set_name
, "osync_group_set_name");
682 LoadSym(p
->osync_group_save
, "osync_group_save");
683 LoadSym(p
->osync_group_delete
, "osync_group_delete");
684 LoadSym(p
->osync_member_new
, "osync_member_new");
685 LoadSym(p
->osync_member_instance_plugin
,"osync_member_instance_plugin");
686 LoadSym(p
->osync_member_save
, "osync_member_save");
687 LoadSym(p
->osync_member_from_id
, "osync_member_from_id");
688 LoadSym(p
->osync_member_need_config
, "osync_member_need_config");
689 LoadSym(p
->osync_member_get_config_or_default
,
690 "osync_member_get_config_or_default");
691 LoadSym(p
->osync_member_set_config
, "osync_member_set_config");
692 LoadSym(p
->osengine_mapping_ignore_supported
,
693 "osengine_mapping_ignore_supported");
694 LoadSym(p
->osengine_mapping_check_timestamps
,
695 "osengine_mapping_check_timestamps");
696 LoadSym(p
->osengine_mapping_nth_change
, "osengine_mapping_nth_change");
697 LoadSym(p
->osengine_mapping_solve
, "osengine_mapping_solve");
698 LoadSym(p
->osengine_mapping_duplicate
, "osengine_mapping_duplicate");
699 LoadSym(p
->osengine_mapping_ignore_conflict
,
700 "osengine_mapping_ignore_conflict");
701 LoadSym(p
->osengine_mapping_solve_latest
,
702 "osengine_mapping_solve_latest");
703 LoadSym(p
->osync_change_get_uid
, "osync_change_get_uid");
704 LoadSym(p
->osengine_init
, "osengine_init");
705 LoadSym(p
->osync_change_get_member
, "osync_change_get_member");
706 LoadSym(p
->osync_change_get_datasize
, "osync_change_get_datasize");
707 LoadSym(p
->osengine_new
, "osengine_new");
708 LoadSym(p
->osengine_free
, "osengine_free");
709 LoadSym(p
->osengine_finalize
, "osengine_finalize");
710 LoadSym(p
->osengine_sync_and_block
, "osengine_sync_and_block");
711 LoadSym(p
->osengine_set_memberstatus_callback
,
712 "osengine_set_memberstatus_callback");
713 LoadSym(p
->osengine_set_changestatus_callback
,
714 "osengine_set_changestatus_callback");
715 LoadSym(p
->osengine_set_enginestatus_callback
,
716 "osengine_set_enginestatus_callback");
717 LoadSym(p
->osengine_set_mappingstatus_callback
,
718 "osengine_set_mappingstatus_callback");
719 LoadSym(p
->osengine_set_conflict_callback
,
720 "osengine_set_conflict_callback");
721 LoadSym(p
->osengine_mapping_num_changes
,
722 "osengine_mapping_num_changes");
723 LoadSym(p
->osync_change_get_changetype
, "osync_change_get_changetype");
724 LoadSym(p
->osync_change_get_printable
, "osync_change_get_printable");
725 LoadSym(p
->osync_group_set_objtype_enabled
,
726 "osync_group_set_objtype_enabled");
728 // do common initialization of opensync environment
729 SetupEnvironment(p
.get());
731 // this pointer is ours now
732 m_priv
= p
.release();
735 OpenSync22::~OpenSync22()
737 // clean up opensync environment, closing plugins, etc.
739 m_priv
->osync_env_finalize(m_priv
->env
, NULL
);
740 m_priv
->osync_env_free(m_priv
->env
);
743 // free private class data
748 void OpenSync22::SetupEnvironment(OpenSync22Private
*p
)
750 // we are fully responsible for this pointer, since
751 // we run inside the constructor... only on success
752 // will responsibility be transferred to the destructor
753 p
->env
= p
->osync_env_new();
755 throw std::runtime_error(_C("Error allocating opensync 0.22 environment"));
757 p
->osync_env_set_option(p
->env
, "GROUPS_DIRECTORY", NULL
);
758 p
->osync_env_set_option(p
->env
, "LOAD_GROUPS", "TRUE");
759 p
->osync_env_set_option(p
->env
, "LOAD_PLUGINS", "TRUE");
760 p
->osync_env_set_option(p
->env
, "LOAD_FORMATS", "TRUE");
762 OSyncError
*error
= NULL
;
763 if( !p
->osync_env_initialize(p
->env
, &error
) ) {
764 // grab error message
765 std::runtime_error
err(m_priv
->osync_error_print(&error
));
768 p
->osync_error_free(&error
);
769 p
->osync_env_free(m_priv
->env
);
776 const char* OpenSync22::GetVersion() const
778 return m_priv
->osync_get_version();
781 const char* OpenSync22::GetEngineName() const
786 void OpenSync22::GetPluginNames(string_list_type
&plugins
)
792 for( int i
= 0; i
< m_priv
->osync_env_num_plugins(m_priv
->env
); i
++) {
793 p
= m_priv
->osync_env_nth_plugin(m_priv
->env
, i
);
794 plugins
.push_back(m_priv
->osync_plugin_get_name(p
));
798 void OpenSync22::GetFormats(format_list_type
&formats
)
803 // cycle through all object types and simulate a 0.4x-like
804 // list based on the attached formats
806 OSyncFormatEnv
*fenv
= m_priv
->osync_conv_env_new(m_priv
->env
);
808 throw std::runtime_error(string("GetFormats(): ") + _C("Unable to load format environment in GetFormats (22)"));
811 for( int i
= 0; i
< m_priv
->osync_conv_num_objtypes(fenv
); i
++ ) {
812 OSyncObjType
*type
= m_priv
->osync_conv_nth_objtype(fenv
, i
);
814 for( int i
= 0; i
< m_priv
->osync_conv_num_objformats(type
); i
++ ) {
815 OSyncObjFormat
*format
= m_priv
->osync_conv_nth_objformat(type
, i
);
816 const char *objformat_name
= m_priv
->osync_objformat_get_name(format
);
818 if( !formats
.Find(objformat_name
) ) {
820 new_format
.name
= objformat_name
;
821 new_format
.object_type
= m_priv
->osync_objtype_get_name(type
);
822 formats
.push_back(new_format
);
827 m_priv
->osync_conv_env_free(fenv
);
830 void OpenSync22::GetGroupNames(string_list_type
&groups
)
836 for( int i
= 0; i
< m_priv
->osync_env_num_groups(m_priv
->env
); i
++ ) {
837 g
= m_priv
->osync_env_nth_group(m_priv
->env
, i
);
838 groups
.push_back(m_priv
->osync_group_get_name(g
));
842 void OpenSync22::GetMembers(const std::string
&group_name
,
843 member_list_type
&members
)
848 OSyncGroup
*group
= m_priv
->osync_env_find_group(m_priv
->env
, group_name
.c_str());
850 throw std::runtime_error(string("GetMembers(): ") + _C("Unable to find group with name: ") + group_name
);
853 for( int i
= 0; i
< m_priv
->osync_group_num_members(group
); i
++ ) {
854 OSyncMember
*member
= m_priv
->osync_group_nth_member(group
, i
);
858 new_member
.group_name
= group_name
;
859 new_member
.id
= m_priv
->osync_member_get_id(member
);
860 new_member
.plugin_name
= m_priv
->osync_member_get_pluginname(member
);
862 // we are switching opensync's long long int ID to
863 // our long... to double check they are equal after
865 if( new_member
.id
!= m_priv
->osync_member_get_id(member
) ) {
866 throw std::logic_error("GetMembers(): OpenSync's member ID is too large to fit in OpenSyncAPI (22)");
869 // add to member list
870 members
.push_back(new_member
);
874 void OpenSync22::AddGroup(const std::string
&group_name
)
876 if( m_priv
->osync_env_find_group(m_priv
->env
, group_name
.c_str()) )
877 throw std::runtime_error(string("AddGroup(): ") + _C("Group already exists: ") + group_name
);
879 OSyncGroup
*group
= m_priv
->osync_group_new(m_priv
->env
);
880 m_priv
->osync_group_set_name(group
, group_name
.c_str());
882 OSyncError
*error
= NULL
;
883 if( !m_priv
->osync_group_save(group
, &error
) ) {
884 // grab error message
885 std::runtime_error
err(string("AddGroup(): ") + _C("Unable to save group: ") + m_priv
->osync_error_print(&error
));
888 m_priv
->osync_error_free(&error
);
894 void OpenSync22::DeleteGroup(const std::string
&group_name
)
896 OSyncGroup
*group
= m_priv
->osync_env_find_group(m_priv
->env
, group_name
.c_str());
898 throw std::runtime_error(string("DeleteGroup(): ") + _C("Group not found: ") + group_name
);
900 OSyncError
*error
= NULL
;
901 if( !m_priv
->osync_group_delete(group
, &error
) ) {
902 std::runtime_error
err(string("DeleteGroup(): ") + _C("Unable to delete group: ") + m_priv
->osync_error_print(&error
));
903 m_priv
->osync_error_free(&error
);
908 Converter
& OpenSync22::GetConverter()
910 return m_priv
->converter
;
913 long OpenSync22::AddMember(const std::string
&group_name
,
914 const std::string
&plugin_name
,
915 const std::string
&member_name
)
917 OSyncGroup
*group
= m_priv
->osync_env_find_group(m_priv
->env
, group_name
.c_str());
919 throw std::runtime_error(string("AddMember(): ") + _C("Group not found: ") + group_name
);
921 OSyncMember
*member
= m_priv
->osync_member_new(group
);
923 OSyncError
*error
= NULL
;
924 if( !m_priv
->osync_member_instance_plugin(member
, plugin_name
.c_str(), &error
) ) {
925 std::runtime_error
err(string("AddMember(): ") + _C("Unable to connect plugin with member: ") + member_name
+ "/" + plugin_name
+ ": " + m_priv
->osync_error_print(&error
));
926 m_priv
->osync_error_free(&error
);
930 if( !m_priv
->osync_member_save(member
, &error
) ) {
931 std::runtime_error
err(string("AddMember(): ") + _C("Unable to save member: ") + member_name
+ "/" + plugin_name
+ ": " + m_priv
->osync_error_print(&error
));
932 m_priv
->osync_error_free(&error
);
936 return m_priv
->osync_member_get_id(member
);
939 bool OpenSync22::IsConfigurable(const std::string
&group_name
,
942 OSyncGroup
*group
= m_priv
->osync_env_find_group(m_priv
->env
, group_name
.c_str());
944 throw std::runtime_error(_C("Group not found: ") + group_name
);
946 OSyncMember
*member
= m_priv
->osync_member_from_id(group
, member_id
);
949 oss
<< "IsConfigurable(): " << _C("Member not found: ") << member_id
;
950 throw std::runtime_error(oss
.str());
953 OSyncConfigurationTypes type
= NO_CONFIGURATION
;
954 OSyncError
*error
= NULL
;
955 if( !m_priv
->osync_member_need_config(member
, &type
, &error
) ) {
956 std::runtime_error
err(string(_C("Unable to determine needed config: ")) + m_priv
->osync_error_print(&error
));
957 m_priv
->osync_error_free(&error
);
961 return type
!= NO_CONFIGURATION
;
964 std::string
OpenSync22::GetConfiguration(const std::string
&group_name
,
967 if( !IsConfigurable(group_name
, member_id
) ) {
968 throw std::runtime_error(string("GetConfiguration(): ") + string_vprintf(_C("Member %ld of group '%s' does not accept configuration."),
970 group_name
.c_str()));
973 OSyncGroup
*group
= m_priv
->osync_env_find_group(m_priv
->env
, group_name
.c_str());
975 throw std::runtime_error(string("GetConfiguration(): ") + _C("Group not found: ") + group_name
);
977 OSyncMember
*member
= m_priv
->osync_member_from_id(group
, member_id
);
979 throw std::runtime_error(string("GetConfiguration(): ") + string_vprintf(_C("Member %ld not found."), member_id
));
982 OSyncError
*error
= NULL
;
985 if( !m_priv
->osync_member_get_config_or_default(member
, &data
, &size
, &error
)) {
986 std::runtime_error
err(string("GetConfiguration(): ") + _C("Unable to retrieve config: ") + m_priv
->osync_error_print(&error
));
987 m_priv
->osync_error_free(&error
);
991 std::string
config(data
, size
);
997 void OpenSync22::SetConfiguration(const std::string
&group_name
,
999 const std::string
&config_data
)
1001 if( !IsConfigurable(group_name
, member_id
) ) {
1002 throw std::runtime_error(string("SetConfiguration(): ") + string_vprintf(_C("Member %ld of group '%s' does not accept configuration."),
1004 group_name
.c_str()));
1007 OSyncGroup
*group
= m_priv
->osync_env_find_group(m_priv
->env
, group_name
.c_str());
1009 throw std::runtime_error(string("SetConfiguration(): ") + _C("Group not found: ") + group_name
);
1011 OSyncMember
*member
= m_priv
->osync_member_from_id(group
, member_id
);
1013 throw std::runtime_error(string("SetConfiguration(): ") + string_vprintf(_C("Member %ld not found."), member_id
));
1016 m_priv
->osync_member_set_config(member
, config_data
.c_str(), config_data
.size());
1018 OSyncError
*error
= NULL
;
1019 if( !m_priv
->osync_member_save(member
, &error
) ) {
1020 std::runtime_error
err(string("SetConfiguration(): ") + _C("Unable to save member's config: ") + m_priv
->osync_error_print(&error
));
1021 m_priv
->osync_error_free(&error
);
1026 void OpenSync22::Discover(const std::string
&group_name
)
1028 // Discover is a successful noop on 0.22
1031 void OpenSync22::Sync(const std::string
&group_name
,
1032 SyncStatus
&status_callback
,
1033 Config::pst_type sync_types
)
1035 OSyncGroup
*group
= m_priv
->osync_env_find_group(m_priv
->env
, group_name
.c_str());
1037 throw std::runtime_error(string("Sync(): ") + _C("Group not found: ") + group_name
);
1039 // enable/disable each objtype, as per sync_types
1040 if( !(sync_types
& PST_DO_NOT_SET
) ) {
1041 cerr
<< "enabling objtypes: " << sync_types
<< endl
;
1042 m_priv
->osync_group_set_objtype_enabled(group
, "contact",
1043 (sync_types
& PST_CONTACTS
) ? TRUE
: FALSE
);
1044 m_priv
->osync_group_set_objtype_enabled(group
, "event",
1045 (sync_types
& PST_EVENTS
) ? TRUE
: FALSE
);
1046 m_priv
->osync_group_set_objtype_enabled(group
, "note",
1047 (sync_types
& PST_NOTES
) ? TRUE
: FALSE
);
1048 m_priv
->osync_group_set_objtype_enabled(group
, "todo",
1049 (sync_types
& PST_TODOS
) ? TRUE
: FALSE
);
1052 OSyncError
*error
= NULL
;
1053 EngineHandle
engine(m_priv
->osengine_free
);
1054 engine
= m_priv
->osengine_new(group
, &error
);
1055 if( !engine
.get() ) {
1056 std::ostringstream oss
;
1057 oss
<< _C("Error while synchronizing: ")
1058 << m_priv
->osync_error_print(&error
);
1059 m_priv
->osync_error_free(&error
);
1060 throw std::runtime_error(oss
.str());
1063 CallbackBundle22
cbdata(m_priv
, status_callback
);
1065 m_priv
->osengine_set_memberstatus_callback(engine
.get(),
1066 &member_status
, &cbdata
);
1067 m_priv
->osengine_set_changestatus_callback(engine
.get(),
1068 &entry_status
, &cbdata
);
1069 m_priv
->osengine_set_enginestatus_callback(engine
.get(),
1070 &engine_status
, &cbdata
);
1071 m_priv
->osengine_set_mappingstatus_callback(engine
.get(),
1072 &mapping_status
, &cbdata
);
1073 m_priv
->osengine_set_conflict_callback(engine
.get(),
1074 &conflict_handler
, &cbdata
);
1076 if( !m_priv
->osengine_init(engine
.get(), &error
) ) {
1078 oss
<< _C("Error initializing osengine: ")
1079 << m_priv
->osync_error_print(&error
);
1080 m_priv
->osync_error_free(&error
);
1081 throw std::runtime_error(oss
.str());
1084 // successfully initialized, so finalize must be called
1085 EngineHandle
initialized_engine(m_priv
->osengine_finalize
);
1086 initialized_engine
= engine
.get();
1088 if( !m_priv
->osengine_sync_and_block(engine
.get(), &error
) ) {
1090 oss
<< _C("Error during sync: ")
1091 << m_priv
->osync_error_print(&error
);
1092 m_priv
->osync_error_free(&error
);
1093 throw std::runtime_error(oss
.str());
1097 } // namespace OpenSync