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-2013, 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.
38 // command line arguments
39 string g_argv_version
, g_argv_group_name
;
40 OpenSync::Config::pst_type g_sync_types
= PST_DO_NOT_SET
;
43 class ClientConnection
: public wxConnection
49 class Client
: public wxClient
53 ClientConnection
* OnMakeConnection()
55 return new ClientConnection
;
59 class BarrySyncJail
: public OpenSync::SyncStatus
63 std::auto_ptr
<OpenSync::API
> m_engine
;
64 std::auto_ptr
<wxClient
> m_client
;
65 wxConnectionBase
*m_status_con
, *m_conflict_con
;
67 // communication variables
76 virtual bool OnInit();
80 // OpenSync::SyncStatus virtual overrides
82 virtual void HandleConflict(OpenSync::SyncConflict
&conflict
);
83 virtual void EntryStatus(const std::string
&msg
, bool error
);
84 virtual void MappingStatus(const std::string
&msg
, bool error
);
85 virtual void EngineStatus(const std::string
&msg
, bool error
,
87 virtual void MemberStatus(long member_id
,
88 const std::string
&plugin_name
,
89 const std::string
&msg
, bool error
);
90 virtual void CheckSummary(OpenSync::SyncSummary
&summary
);
91 virtual void ReportError(const std::string
&msg
);
94 DECLARE_APP(BarrySyncJail
)
96 //////////////////////////////////////////////////////////////////////////////
99 BarrySyncJail::BarrySyncJail()
100 : m_temp("bsyncjail")
108 BarrySyncJail::~BarrySyncJail()
112 bool BarrySyncJail::OnInit()
114 cerr
<< "OnInit()" << endl
;
116 // connect to parent app
117 m_client
.reset( new Client
);
118 m_status_con
= m_client
->MakeConnection(_T("localhost"),
119 SERVER_SERVICE_NAME
, TOPIC_STATUS
);
120 m_conflict_con
= m_client
->MakeConnection(_T("localhost"),
121 SERVER_SERVICE_NAME
, TOPIC_CONFLICT
);
122 if( !m_status_con
|| !m_conflict_con
) {
123 cerr
<< _C("Unable to connect to server.") << endl
;
127 // load opensync engine
129 if( g_argv_version
.substr(0, 3) == "0.2" )
130 m_engine
.reset( new OpenSync::OpenSync22
);
132 m_engine
.reset( new OpenSync::OpenSync40
);
133 if( g_argv_version
!= m_engine
->GetVersion() )
134 throw std::runtime_error(_C("Can't find matching engine for: ") + g_argv_version
);
137 catch( std::exception
&e
) {
138 m_status_con
->Poke(STATUS_ITEM_ERROR
, sb
.buf(e
.what()));
139 cerr
<< e
.what() << endl
;
143 if( !m_engine
.get() ) {
144 m_status_con
->Poke(STATUS_ITEM_ERROR
, sb
.buf(string(_C("Unknown engine number: ")) + g_argv_version
));
150 m_engine
->Discover(g_argv_group_name
);
151 m_engine
->Sync(g_argv_group_name
, *this, g_sync_types
);
153 catch( std::exception
&e
) {
154 m_status_con
->Poke(STATUS_ITEM_ERROR
, sb
.buf(e
.what()));
155 cerr
<< e
.what() << endl
;
162 int BarrySyncJail::OnExit()
164 cerr
<< "OnExit()" << endl
;
166 // clean up the client connection... do this early, so that
167 // TempDir can clean up the files if necessary
174 // OpenSync::SyncStatus virtual overrides
177 void BarrySyncJail::HandleConflict(OpenSync::SyncConflict
&conflict
)
179 OpenSync::SyncConflict::iterator i
;
183 // start with a new sequence ID
187 // msg 1: sequence ID, offset 0
188 // send available menu / functions possible, and number of
189 // changes that conflict
192 oss
<< m_sequenceID
<< " " << offset
<< " " << conflict
.size()
194 if( conflict
.IsAbortSupported() )
196 if( conflict
.IsIgnoreSupported() )
198 if( conflict
.IsKeepNewerSupported() )
201 if( !m_conflict_con
->Poke(CONFLICT_ITEM_START
, sb
.buf(oss
.str())) )
202 goto connection_lost
;
204 // all following messages contain the sequence ID,
205 // the change ID, and the change data
206 i
= conflict
.begin();
207 for( ; i
!= conflict
.end(); ++i
) {
211 oss
<< m_sequenceID
<< " " << offset
<< " " << i
->id
<< " \n";
212 oss
<< i
->plugin_name
<< "\n";
213 oss
<< i
->uid
<< "\n";
214 oss
<< i
->printable_data
;
216 if( !m_conflict_con
->Poke(CONFLICT_ITEM_CHANGE
, sb
.buf(oss
.str())) )
217 goto connection_lost
;
220 // then wait on the server to tell us what choice was made
221 buf
= m_conflict_con
->Request(CONFLICT_ITEM_ANSWER
, &size
);
224 istringstream
iss(string(msg
.utf8_str()));
229 iss
>> sequenceID
>> command
;
230 if( !iss
|| sequenceID
!= m_sequenceID
) {
231 // invalid command from server, something is wrong
232 throw std::runtime_error(_C("Invalid server response: ") + string(msg
.utf8_str()));
240 throw std::runtime_error(_C("Invalid Select command from server: ") + string(msg
.utf8_str()));
244 case 'D': // Duplicate
245 conflict
.Duplicate();
249 if( !conflict
.IsAbortSupported() )
250 throw std::runtime_error(_C("Abort not supported, and server sent Abort command."));
255 if( !conflict
.IsIgnoreSupported() )
256 throw std::runtime_error(_C("Ignore not supported, and server sent Ignore command."));
260 case 'N': // Keep Newer
261 if( !conflict
.IsKeepNewerSupported() )
262 throw std::runtime_error(_C("Keep Newer not supported, and server sent Keep Newer command."));
263 conflict
.KeepNewer();
267 throw std::runtime_error(_C("Invalid command from server: ") + string(msg
.utf8_str()));
275 if( conflict
.IsAbortSupported() )
278 throw std::runtime_error(_C("Lost connection with server"));
281 void BarrySyncJail::EntryStatus(const std::string
&msg
, bool error
)
286 m_status_con
->Poke(STATUS_ITEM_ENTRY
, sb
.buf(msg
));
289 void BarrySyncJail::MappingStatus(const std::string
&msg
, bool error
)
294 m_status_con
->Poke(STATUS_ITEM_MAPPING
, sb
.buf(msg
));
297 void BarrySyncJail::EngineStatus(const std::string
&msg
, bool error
, bool slowsync
)
302 m_status_con
->Poke(STATUS_ITEM_ENGINE
, sb
.buf(msg
));
304 // slow sync on 0.22 is unreliable... send a special notice
306 if( slowsync
&& !m_engine
->IsSlowSyncSupported() )
307 m_status_con
->Poke(STATUS_ITEM_ENGINE
, sb
.buf(ENGINE_STATUS_SLOW_SYNC
));
310 void BarrySyncJail::MemberStatus(long member_id
,
311 const std::string
&plugin_name
,
312 const std::string
&msg
, bool error
)
317 m_status_con
->Poke(STATUS_ITEM_MEMBER
, sb
.buf(msg
));
320 void BarrySyncJail::CheckSummary(OpenSync::SyncSummary
&summary
)
322 // FIXME: not currently supported... abort every time
323 // cerr << "FIXME: CheckSummary() not implemented, aborting" << endl;
328 void BarrySyncJail::ReportError(const std::string
&msg
)
330 m_status_con
->Poke(STATUS_ITEM_ERROR
, sb
.buf(msg
));
331 cerr
<< "ReportError(): " << msg
<< endl
;
335 int main(int argc
, char *argv
[])
339 wxApp::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE
, "bsyncjail");
341 cerr
<< "bsyncjail startup" << endl
;
344 cerr
<< _C("This is a helper program for barrydesktop, and\n"
345 "is not intended to be called directly.\n") << endl
;
349 g_argv_version
= argv
[1];
350 g_argv_group_name
= argv
[2];
351 g_sync_types
= atoi(argv
[3]);
353 wxInitializer initializer
;
355 cerr
<< _C("Unable to initialize wxWidgets library, aborting.") << endl
;
360 int ret
= app
.OnExit();
361 cerr
<< _C("bsyncjail exiting with code: ") << ret
<< endl
;