lib: added implicit ctor converter from DatabaseDatabase to DBListType
[barry/progweb.git] / desktop / src / bsyncjail.cc
blob2471d0869e832af944e5b567d07600ad685cc34d
1 ///
2 /// \file bsyncjail.cc
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.
8 ///
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.
26 #include <wx/wx.h>
27 #include <iostream>
28 #include <sstream>
29 #include "ipc.h"
30 #include "os22.h"
31 #include "os40.h"
32 #include "tempdir.h"
33 #include "ostypes.h"
35 using namespace std;
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;
40 SillyBuffer sb;
42 class ClientConnection : public wxConnection
44 public:
45 ClientConnection() {}
48 class Client : public wxClient
50 public:
51 Client() {}
52 ClientConnection* OnMakeConnection()
54 return new ClientConnection;
58 class BarrySyncJail : public OpenSync::SyncStatus
60 private:
61 TempDir m_temp;
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
67 int m_sequenceID;
68 public:
69 BarrySyncJail();
70 ~BarrySyncJail();
73 // overrides
75 virtual bool OnInit();
76 virtual int OnExit();
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,
85 bool slowsync);
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 //////////////////////////////////////////////////////////////////////////////
96 // BarrySyncJail
98 BarrySyncJail::BarrySyncJail()
99 : m_temp("bsyncjail")
100 , m_status_con(0)
101 , m_conflict_con(0)
102 , m_sequenceID(0)
104 OnInit();
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;
123 return false;
126 // load opensync engine
127 try {
128 if( g_argv_version.substr(0, 3) == "0.2" )
129 m_engine.reset( new OpenSync::OpenSync22 );
130 else {
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;
139 return false;
142 if( !m_engine.get() ) {
143 m_status_con->Poke(STATUS_ITEM_ERROR, sb.buf(string("Unknown engine number: ") + g_argv_version));
144 return false;
147 // start the sync
148 try {
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;
155 return true;
158 return true;
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
167 m_client.reset();
169 return 0;
173 // OpenSync::SyncStatus virtual overrides
176 void BarrySyncJail::HandleConflict(OpenSync::SyncConflict &conflict)
178 OpenSync::SyncConflict::iterator i;
179 int size = 0;
180 wxChar *buf = 0;
182 // start with a new sequence ID
183 m_sequenceID++;
184 int offset = 0;
186 // msg 1: sequence ID, offset 0
187 // send available menu / functions possible, and number of
188 // changes that conflict
190 ostringstream oss;
191 oss << m_sequenceID << " " << offset << " " << conflict.size()
192 << " " << "SD";
193 if( conflict.IsAbortSupported() )
194 oss << "A";
195 if( conflict.IsIgnoreSupported() )
196 oss << "I";
197 if( conflict.IsKeepNewerSupported() )
198 oss << "N";
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 ) {
207 oss.str("");
208 offset++;
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);
221 if( buf ) {
222 wxString msg(buf);
223 istringstream iss(string(msg.utf8_str()));
224 int sequenceID = 0;
225 string command;
226 int id;
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()));
234 switch( command[0] )
236 case 'S': // Select
237 iss >> id;
238 if( !iss )
239 throw std::runtime_error("Invalid Select command from server: " + string(msg.utf8_str()));
240 conflict.Select(id);
241 break;
243 case 'D': // Duplicate
244 conflict.Duplicate();
245 break;
247 case 'A': // Abort
248 if( !conflict.IsAbortSupported() )
249 throw std::runtime_error("Abort not supported, and server sent Abort command.");
250 conflict.Abort();
251 break;
253 case 'I': // Ignore
254 if( !conflict.IsIgnoreSupported() )
255 throw std::runtime_error("Ignore not supported, and server sent Ignore command.");
256 conflict.Ignore();
257 break;
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();
263 break;
265 default:
266 throw std::runtime_error("Invalid command from server: " + string(msg.utf8_str()));
269 // all done!
270 return;
273 connection_lost:
274 if( conflict.IsAbortSupported() )
275 conflict.Abort();
276 else
277 throw std::runtime_error("Lost connection with server");
280 void BarrySyncJail::EntryStatus(const std::string &msg, bool error)
282 if( error )
283 ReportError(msg);
284 else
285 m_status_con->Poke(STATUS_ITEM_ENTRY, sb.buf(msg));
288 void BarrySyncJail::MappingStatus(const std::string &msg, bool error)
290 if( error )
291 ReportError(msg);
292 else
293 m_status_con->Poke(STATUS_ITEM_MAPPING, sb.buf(msg));
296 void BarrySyncJail::EngineStatus(const std::string &msg, bool error, bool slowsync)
298 if( error )
299 ReportError(msg);
300 else
301 m_status_con->Poke(STATUS_ITEM_ENGINE, sb.buf(msg));
303 // slow sync on 0.22 is unreliable... send a special notice
304 // to the GUI
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)
313 if( error )
314 ReportError(msg);
315 else
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;
323 // summary.Abort();
324 summary.Continue();
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;
340 if( argc != 4 ) {
341 cerr << "This is a helper program for barrydesktop, and\n"
342 "not intended to be called directly.\n" << endl;
343 return 1;
346 g_argv_version = argv[1];
347 g_argv_group_name = argv[2];
348 g_sync_types = atoi(argv[3]);
350 wxInitializer initializer;
351 if( !initializer ) {
352 cerr << "Unable to initialize wxWidgets library, aborting." << endl;
353 return 1;
356 BarrySyncJail app;
357 int ret = app.OnExit();
358 cerr << "bsyncjail exiting with code: " << ret << endl;
359 return ret;