desktop: fixed bug in GroupCfgDlg that gave mistaken "not configured" error
[barry/progweb.git] / desktop / src / os22.cc
blob6cbde75248aa639e7698a6981a6b57fc4c5d9a76
1 ///
2 /// \file os22.cc
3 /// Wrapper class for opensync 0.22 syncing behaviour
4 ///
6 /*
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.
27 #include "os22.h"
28 #include "osprivatebase.h"
29 #include "osconv22.h"
30 #include <barry/barry.h>
31 #include <barry/vsmartptr.h>
32 #include <memory>
33 #include <glib.h>
35 #include <../opensync-1.0/opensync/opensync.h>
36 #include <../opensync-1.0/osengine/engine.h>
38 using namespace std;
40 namespace OpenSync {
42 typedef Barry::vLateSmartPtr<OSyncEngine, void(*)(OSyncEngine*)> EngineHandle;
44 class OpenSync22Private
46 public:
47 // function pointers
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,
54 OSyncError **error);
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,
61 OSyncError **error);
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,
66 const char *name);
67 int (*osync_group_num_members)(OSyncGroup *group);
68 OSyncMember* (*osync_group_nth_member)(OSyncGroup *group,
69 int nth);
70 long long int (*osync_member_get_id)(OSyncMember *member);
71 const char* (*osync_member_get_pluginname)(
72 OSyncMember *member);
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,
77 int nth);
78 int (*osync_conv_num_objformats)(
79 OSyncObjType *type);
80 OSyncObjFormat* (*osync_conv_nth_objformat)(OSyncObjType *type,
81 int nth);
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,
87 const char *name);
88 osync_bool (*osync_group_save)(OSyncGroup *group,
89 OSyncError **error);
90 osync_bool (*osync_group_delete)(OSyncGroup *group,
91 OSyncError **error);
92 OSyncMember* (*osync_member_new)(OSyncGroup *group);
93 osync_bool (*osync_member_instance_plugin)(
94 OSyncMember *member,
95 const char *pluginname,
96 OSyncError **error);
97 osync_bool (*osync_member_save)(OSyncMember *member,
98 OSyncError **error);
99 OSyncMember* (*osync_member_from_id)(OSyncGroup *group,
100 int id);
101 osync_bool (*osync_member_need_config)(OSyncMember *member,
102 OSyncConfigurationTypes *type,
103 OSyncError **error);
104 osync_bool (*osync_member_get_config_or_default)(
105 OSyncMember *member,
106 char **data, int *size,
107 OSyncError **error);
108 void (*osync_member_set_config)(OSyncMember *member,
109 const char *data, int size);
110 osync_bool (*osengine_mapping_ignore_supported)(
111 OSyncEngine *engine,
112 OSyncMapping *mapping);
113 osync_bool (*osengine_mapping_check_timestamps)(
114 OSyncEngine *engine,
115 OSyncMapping *mapping,
116 OSyncError **error);
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)(
123 OSyncEngine *engine,
124 OSyncMapping *dupe_mapping);
125 osync_bool (*osengine_mapping_ignore_conflict)(
126 OSyncEngine *engine,
127 OSyncMapping *mapping,
128 OSyncError **error);
129 osync_bool (*osengine_mapping_solve_latest)(
130 OSyncEngine *engine,
131 OSyncMapping *mapping,
132 OSyncError **error);
133 const char* (*osync_change_get_uid)(OSyncChange *change);
134 osync_bool (*osengine_init)(OSyncEngine *engine,
135 OSyncError **error);
136 OSyncMember* (*osync_change_get_member)(OSyncChange *change);
137 int (*osync_change_get_datasize)(
138 OSyncChange *change);
139 OSyncEngine* (*osengine_new)(OSyncGroup *group,
140 OSyncError **error);
141 void (*osengine_free)(OSyncEngine *engine);
142 void (*osengine_finalize)(OSyncEngine *engine);
143 osync_bool (*osengine_sync_and_block)(OSyncEngine *engine,
144 OSyncError **error);
145 void (*osengine_set_memberstatus_callback)(
146 OSyncEngine *engine,
147 void (* function) (OSyncMemberUpdate *,
148 void *),
149 void *user_data);
150 void (*osengine_set_changestatus_callback)(
151 OSyncEngine *engine,
152 void (* function) (OSyncEngine *,
153 OSyncChangeUpdate *,
154 void *),
155 void *user_data);
156 void (*osengine_set_enginestatus_callback)(
157 OSyncEngine *engine,
158 void (* function) (OSyncEngine *,
159 OSyncEngineUpdate *,
160 void *),
161 void *user_data);
162 void (*osengine_set_mappingstatus_callback)(
163 OSyncEngine *engine,
164 void (* function) (OSyncMappingUpdate *,
165 void *),
166 void *user_data);
167 void (*osengine_set_conflict_callback)(
168 OSyncEngine *engine,
169 void (* function) (OSyncEngine *,
170 OSyncMapping *,
171 void *),
172 void *user_data);
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);
180 // data pointers
181 OSyncEnv *env;
183 Converter22 converter;
185 OpenSync22Private(OpenSync22 &api)
186 : env(0)
187 , converter(api)
192 class SyncConflict22Private : public SyncConflictPrivateBase
194 OpenSync22Private *m_priv;
195 OSyncEngine *m_engine;
196 OSyncMapping *m_mapping;
198 public:
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)
222 : m_priv(priv)
223 , m_status(&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)
240 switch (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";
245 default:
246 case CHANGE_UNKNOWN: return "?";
250 /////////////////////////////////////////////////////////////////////////////
251 // SyncConflict22Private member functions
253 SyncConflict22Private::SyncConflict22Private(OpenSync22Private *priv,
254 OSyncEngine *engine, OSyncMapping *mapping)
255 : m_priv(priv)
256 , m_engine(engine)
257 , m_mapping(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);
283 if( !change ) {
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)) {
307 ostringstream oss;
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)) {
322 ostringstream oss;
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 ) {
336 SyncChange entry;
338 char *printable = m_priv->osync_change_get_printable(change);
339 if( printable ) {
340 entry.printable_data = printable;
341 g_free(printable);
344 OSyncMember *member = m_priv->osync_change_get_member(change);
346 entry.id = i;
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);
351 // add to list
352 list.push_back(entry);
358 /////////////////////////////////////////////////////////////////////////////
359 // Callback functions
361 void member_status(OSyncMemberUpdate *status, void *cbdata)
363 CallbackBundle22 *cb = (CallbackBundle22*) cbdata;
365 try {
366 ostringstream oss;
367 bool error_event = false;
368 bool valid = true;
370 oss << "Member "
371 << cb->m_priv->osync_member_get_id(status->member)
372 << " ("
373 << cb->m_priv->osync_member_get_pluginname(status->member)
374 << ")";
376 switch( status->type )
378 case MEMBER_CONNECTED:
379 oss << " just connected";
380 break;
381 case MEMBER_DISCONNECTED:
382 oss << " just disconnected";
383 break;
384 case MEMBER_SENT_CHANGES:
385 oss << " just sent all changes";
386 break;
387 case MEMBER_COMMITTED_ALL:
388 oss << " committed all changes";
389 break;
390 case MEMBER_CONNECT_ERROR:
391 oss << " had an error while connecting: "
392 << cb->m_priv->osync_error_print(&status->error);
393 break;
394 case MEMBER_GET_CHANGES_ERROR:
395 oss << " had an error while getting changes: "
396 << cb->m_priv->osync_error_print(&status->error);
397 error_event = true;
398 break;
399 case MEMBER_SYNC_DONE_ERROR:
400 oss << " had an error while calling sync done: "
401 << cb->m_priv->osync_error_print(&status->error);
402 error_event = true;
403 break;
404 case MEMBER_DISCONNECT_ERROR:
405 oss << " had an error while disconnecting: "
406 << cb->m_priv->osync_error_print(&status->error);
407 error_event = true;
408 break;
409 case MEMBER_COMMITTED_ALL_ERROR:
410 oss << " had an error while commiting changes: "
411 << cb->m_priv->osync_error_print(&status->error);
412 error_event = true;
413 break;
414 default:
415 valid = false;
416 break;
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());
431 catch( ... ) {
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;
442 try {
443 ostringstream oss;
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 "
454 << status->member_id
455 << " ("
456 << cb->m_priv->osync_member_get_pluginname(member)
457 << "). "
458 << "Changetype "
459 << OSyncChangeType2String(cb->m_priv->osync_change_get_changetype(status->change));
460 break;
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)
466 << " from member "
467 << status->member_id
468 << " ("
469 << cb->m_priv->osync_member_get_pluginname(member)
470 << "). Changetype "
471 << OSyncChangeType2String(cb->m_priv->osync_change_get_changetype(status->change));
472 break;
473 case CHANGE_SENT:
474 oss << "Sent an entry "
475 << cb->m_priv->osync_change_get_uid(status->change)
476 << " of size "
477 << cb->m_priv->osync_change_get_datasize(status->change)
478 << " to member "
479 << status->member_id
480 << " ("
481 << cb->m_priv->osync_member_get_pluginname(member)
482 << "). Changetype "
483 << OSyncChangeType2String(cb->m_priv->osync_change_get_changetype(status->change));
484 break;
485 case CHANGE_WRITE_ERROR:
486 error_event = true;
487 oss << "Error writing entry "
488 << cb->m_priv->osync_change_get_uid(status->change)
489 << " to member "
490 << status->member_id
491 << " ("
492 << cb->m_priv->osync_member_get_pluginname(member)
493 << "): "
494 << cb->m_priv->osync_error_print(&status->error);
495 break;
496 case CHANGE_RECV_ERROR:
497 error_event = true;
498 oss << "Error reading entry "
499 << cb->m_priv->osync_change_get_uid(status->change)
500 << " from member "
501 << status->member_id
502 << " ("
503 << cb->m_priv->osync_member_get_pluginname(member)
504 << "): "
505 << cb->m_priv->osync_error_print(&(status->error));
506 break;
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());
518 catch( ... ) {
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;
528 try {
529 ostringstream oss;
530 bool error_event = false;
532 switch( status->type )
534 case ENG_PREV_UNCLEAN:
535 oss << "The previous synchronization was unclean. Slow-syncing.";
536 break;
537 case ENG_ENDPHASE_CON:
538 oss << "All clients connected or error";
539 break;
540 case ENG_END_CONFLICTS:
541 oss << "All conflicts have been reported";
542 break;
543 case ENG_ENDPHASE_READ:
544 oss << "All clients sent changes or error";
545 break;
546 case ENG_ENDPHASE_WRITE:
547 oss << "All clients have written";
548 break;
549 case ENG_ENDPHASE_DISCON:
550 oss << "All clients have disconnected";
551 break;
552 case ENG_SYNC_SUCCESSFULL:
553 oss << "The sync was successful";
554 break;
555 case ENG_ERROR:
556 oss << "The sync failed: "
557 << cb->m_priv->osync_error_print(&status->error);
558 error_event = true;
559 break;
562 // call the status handler
563 if( oss.str().size() )
564 cb->m_status->EngineStatus(oss.str(),
565 error_event,
566 status->type == ENG_PREV_UNCLEAN);
568 catch( std::exception &e ) {
569 cb->m_status->ReportError(
570 string("engine_status error: ") + e.what());
572 catch( ... ) {
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;
582 try {
583 ostringstream oss;
584 bool error_event = false;
586 switch( status->type )
588 case MAPPING_SOLVED:
589 oss << "Mapping solved";
590 break;
591 case MAPPING_SYNCED:
592 oss << "Mapping Synced";
593 break;
594 case MAPPING_WRITE_ERROR:
595 error_event = true;
596 oss << "Mapping Write Error: "
597 << cb->m_priv->osync_error_print(&status->error);
598 break;
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());
609 catch( ... ) {
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;
619 try {
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());
635 catch( ... ) {
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.
744 if( m_priv->env ) {
745 m_priv->osync_env_finalize(m_priv->env, NULL);
746 m_priv->osync_env_free(m_priv->env);
749 // free private class data
750 delete m_priv;
751 m_priv = 0;
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();
760 if( !p->env )
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));
773 // cleanup
774 p->osync_error_free(&error);
775 p->osync_env_free(m_priv->env);
777 // throw
778 throw err;
782 const char* OpenSync22::GetVersion() const
784 return m_priv->osync_get_version();
787 const char* OpenSync22::GetEngineName() const
789 return "0.22";
792 void OpenSync22::GetPluginNames(string_list_type &plugins)
794 // start fresh
795 plugins.clear();
797 OSyncPlugin *p;
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)
806 // start fresh
807 formats.clear();
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);
813 if( !fenv ) {
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) ) {
825 Format new_format;
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)
838 // start fresh
839 groups.clear();
841 OSyncGroup *g;
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)
851 // start fresh
852 members.clear();
854 OSyncGroup *group = m_priv->osync_env_find_group(m_priv->env, group_name.c_str());
855 if( !group ) {
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);
862 Member new_member;
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
870 // the conversion
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));
893 // cleanup
894 m_priv->osync_error_free(&error);
896 throw err;
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());
903 if( !group )
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);
910 throw err;
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());
924 if( !group )
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);
933 throw err;
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);
939 throw err;
942 return m_priv->osync_member_get_id(member);
945 bool OpenSync22::IsConfigurable(const std::string &group_name,
946 long member_id)
948 OSyncGroup *group = m_priv->osync_env_find_group(m_priv->env, group_name.c_str());
949 if( !group )
950 throw std::runtime_error("Group not found: " + group_name);
952 OSyncMember *member = m_priv->osync_member_from_id(group, member_id);
953 if( !member ) {
954 ostringstream oss;
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);
964 throw err;
967 return type != NO_CONFIGURATION;
970 std::string OpenSync22::GetConfiguration(const std::string &group_name,
971 long member_id)
973 if( !IsConfigurable(group_name, member_id) ) {
974 ostringstream oss;
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());
980 if( !group )
981 throw std::runtime_error("GetConfiguration(): Group not found: " + group_name);
983 OSyncMember *member = m_priv->osync_member_from_id(group, member_id);
984 if( !member ) {
985 ostringstream oss;
986 oss << "GetConfiguration(): Member " << member_id << " not found.";
987 throw std::runtime_error(oss.str());
990 OSyncError *error = NULL;
991 char *data = NULL;
992 int size = 0;
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);
996 throw err;
999 std::string config(data, size);
1000 g_free(data);
1002 return config;
1005 void OpenSync22::SetConfiguration(const std::string &group_name,
1006 long member_id,
1007 const std::string &config_data)
1009 if( !IsConfigurable(group_name, member_id) ) {
1010 ostringstream oss;
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());
1016 if( !group )
1017 throw std::runtime_error("SetConfiguration(): Group not found: " + group_name);
1019 OSyncMember *member = m_priv->osync_member_from_id(group, member_id);
1020 if( !member ) {
1021 ostringstream oss;
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);
1032 throw err;
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());
1045 if( !group )
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) ) {
1073 ostringstream oss;
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) ) {
1085 ostringstream oss;
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