3 /// Helper program to isolate the actual syncing into its
4 /// own process. Communicates with the main barrydesktop
5 /// via wxWidgets IPC communication. This belongs in its
6 /// own process since the sync can hang, and may need to
7 /// be killed from the GUI.
11 Copyright (C) 2010-2012, Net Direct Inc. (http://www.netdirect.ca/)
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
22 See the GNU General Public License in the COPYING file at the
23 root directory of this project for more details.
37 // command line arguments
38 string g_argv_version
, g_argv_group_name
;
39 OpenSync::Config::pst_type g_sync_types
= PST_DO_NOT_SET
;
42 class ClientConnection
: public wxConnection
48 class Client
: public wxClient
52 ClientConnection
* OnMakeConnection()
54 return new ClientConnection
;
58 class BarrySyncJail
: public OpenSync::SyncStatus
62 std::auto_ptr
<OpenSync::API
> m_engine
;
63 std::auto_ptr
<wxClient
> m_client
;
64 wxConnectionBase
*m_status_con
, *m_conflict_con
;
66 // communication variables
75 virtual bool OnInit();
79 // OpenSync::SyncStatus virtual overrides
81 virtual void HandleConflict(OpenSync::SyncConflict
&conflict
);
82 virtual void EntryStatus(const std::string
&msg
, bool error
);
83 virtual void MappingStatus(const std::string
&msg
, bool error
);
84 virtual void EngineStatus(const std::string
&msg
, bool error
,
86 virtual void MemberStatus(long member_id
,
87 const std::string
&plugin_name
,
88 const std::string
&msg
, bool error
);
89 virtual void CheckSummary(OpenSync::SyncSummary
&summary
);
90 virtual void ReportError(const std::string
&msg
);
93 DECLARE_APP(BarrySyncJail
)
95 //////////////////////////////////////////////////////////////////////////////
98 BarrySyncJail::BarrySyncJail()
107 BarrySyncJail::~BarrySyncJail()
111 bool BarrySyncJail::OnInit()
113 cerr
<< "OnInit()" << endl
;
115 // connect to parent app
116 m_client
.reset( new Client
);
117 m_status_con
= m_client
->MakeConnection(_T("localhost"),
118 SERVER_SERVICE_NAME
, TOPIC_STATUS
);
119 m_conflict_con
= m_client
->MakeConnection(_T("localhost"),
120 SERVER_SERVICE_NAME
, TOPIC_CONFLICT
);
121 if( !m_status_con
|| !m_conflict_con
) {
122 cerr
<< "Unable to connect to server." << endl
;
126 // load opensync engine
128 if( g_argv_version
.substr(0, 3) == "0.2" )
129 m_engine
.reset( new OpenSync::OpenSync22
);
131 m_engine
.reset( new OpenSync::OpenSync40
);
132 if( g_argv_version
!= m_engine
->GetVersion() )
133 throw std::runtime_error("Can't find matching engine for: " + g_argv_version
);
136 catch( std::exception
&e
) {
137 m_status_con
->Poke(STATUS_ITEM_ERROR
, sb
.buf(e
.what()));
138 cerr
<< e
.what() << endl
;
142 if( !m_engine
.get() ) {
143 m_status_con
->Poke(STATUS_ITEM_ERROR
, sb
.buf(string("Unknown engine number: ") + g_argv_version
));
149 m_engine
->Discover(g_argv_group_name
);
150 m_engine
->Sync(g_argv_group_name
, *this, g_sync_types
);
152 catch( std::exception
&e
) {
153 m_status_con
->Poke(STATUS_ITEM_ERROR
, sb
.buf(e
.what()));
154 cerr
<< e
.what() << endl
;
161 int BarrySyncJail::OnExit()
163 cerr
<< "OnExit()" << endl
;
165 // clean up the client connection... do this early, so that
166 // TempDir can clean up the files if necessary
173 // OpenSync::SyncStatus virtual overrides
176 void BarrySyncJail::HandleConflict(OpenSync::SyncConflict
&conflict
)
178 OpenSync::SyncConflict::iterator i
;
182 // start with a new sequence ID
186 // msg 1: sequence ID, offset 0
187 // send available menu / functions possible, and number of
188 // changes that conflict
191 oss
<< m_sequenceID
<< " " << offset
<< " " << conflict
.size()
193 if( conflict
.IsAbortSupported() )
195 if( conflict
.IsIgnoreSupported() )
197 if( conflict
.IsKeepNewerSupported() )
200 if( !m_conflict_con
->Poke(CONFLICT_ITEM_START
, sb
.buf(oss
.str())) )
201 goto connection_lost
;
203 // all following messages contain the sequence ID,
204 // the change ID, and the change data
205 i
= conflict
.begin();
206 for( ; i
!= conflict
.end(); ++i
) {
210 oss
<< m_sequenceID
<< " " << offset
<< " " << i
->id
<< " \n";
211 oss
<< i
->plugin_name
<< "\n";
212 oss
<< i
->uid
<< "\n";
213 oss
<< i
->printable_data
;
215 if( !m_conflict_con
->Poke(CONFLICT_ITEM_CHANGE
, sb
.buf(oss
.str())) )
216 goto connection_lost
;
219 // then wait on the server to tell us what choice was made
220 buf
= m_conflict_con
->Request(CONFLICT_ITEM_ANSWER
, &size
);
223 istringstream
iss(string(msg
.utf8_str()));
228 iss
>> sequenceID
>> command
;
229 if( !iss
|| sequenceID
!= m_sequenceID
) {
230 // invalid command from server, something is wrong
231 throw std::runtime_error("Invalid server response: " + string(msg
.utf8_str()));
239 throw std::runtime_error("Invalid Select command from server: " + string(msg
.utf8_str()));
243 case 'D': // Duplicate
244 conflict
.Duplicate();
248 if( !conflict
.IsAbortSupported() )
249 throw std::runtime_error("Abort not supported, and server sent Abort command.");
254 if( !conflict
.IsIgnoreSupported() )
255 throw std::runtime_error("Ignore not supported, and server sent Ignore command.");
259 case 'N': // Keep Newer
260 if( !conflict
.IsKeepNewerSupported() )
261 throw std::runtime_error("Keep Newer not supported, and server sent Keep Newer command.");
262 conflict
.KeepNewer();
266 throw std::runtime_error("Invalid command from server: " + string(msg
.utf8_str()));
274 if( conflict
.IsAbortSupported() )
277 throw std::runtime_error("Lost connection with server");
280 void BarrySyncJail::EntryStatus(const std::string
&msg
, bool error
)
285 m_status_con
->Poke(STATUS_ITEM_ENTRY
, sb
.buf(msg
));
288 void BarrySyncJail::MappingStatus(const std::string
&msg
, bool error
)
293 m_status_con
->Poke(STATUS_ITEM_MAPPING
, sb
.buf(msg
));
296 void BarrySyncJail::EngineStatus(const std::string
&msg
, bool error
, bool slowsync
)
301 m_status_con
->Poke(STATUS_ITEM_ENGINE
, sb
.buf(msg
));
303 // slow sync on 0.22 is unreliable... send a special notice
305 if( slowsync
&& !m_engine
->IsSlowSyncSupported() )
306 m_status_con
->Poke(STATUS_ITEM_ENGINE
, sb
.buf(ENGINE_STATUS_SLOW_SYNC
));
309 void BarrySyncJail::MemberStatus(long member_id
,
310 const std::string
&plugin_name
,
311 const std::string
&msg
, bool error
)
316 m_status_con
->Poke(STATUS_ITEM_MEMBER
, sb
.buf(msg
));
319 void BarrySyncJail::CheckSummary(OpenSync::SyncSummary
&summary
)
321 // FIXME: not currently supported... abort every time
322 // cerr << "FIXME: CheckSummary() not implemented, aborting" << endl;
327 void BarrySyncJail::ReportError(const std::string
&msg
)
329 m_status_con
->Poke(STATUS_ITEM_ERROR
, sb
.buf(msg
));
330 cerr
<< "ReportError(): " << msg
<< endl
;
334 int main(int argc
, char *argv
[])
336 wxApp::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE
, "bsyncjail");
338 cerr
<< "bsyncjail startup" << endl
;
341 cerr
<< "This is a helper program for barrydesktop, and\n"
342 "not intended to be called directly.\n" << endl
;
346 g_argv_version
= argv
[1];
347 g_argv_group_name
= argv
[2];
348 g_sync_types
= atoi(argv
[3]);
350 wxInitializer initializer
;
352 cerr
<< "Unable to initialize wxWidgets library, aborting." << endl
;
357 int ret
= app
.OnExit();
358 cerr
<< "bsyncjail exiting with code: " << ret
<< endl
;