2 // \file environment.cc
3 // Container / environment class for the sync module.
7 Copyright (C) 2006-2013, Net Direct Inc. (http://www.netdirect.ca/)
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 See the GNU General Public License in the COPYING file at the
19 root directory of this project for more details.
22 #include "environment.h"
33 using namespace Barry
;
35 //////////////////////////////////////////////////////////////////////////////
38 DatabaseSyncState::DatabaseSyncState(OSyncMember
*pm
, const char *description
)
43 m_CacheFilename
= m_MapFilename
=
44 osync_member_get_configdir(pm
);
45 m_CacheFilename
+= "/barry_" + m_Desc
+ "_cache.txt";
46 m_MapFilename
+= "/barry_" + m_Desc
+ "_idmap.txt";
49 DatabaseSyncState::~DatabaseSyncState()
53 bool DatabaseSyncState::LoadCache()
55 Trace
trace("LoadCache", m_Desc
.c_str());
58 std::ifstream
ifs(m_CacheFilename
.c_str());
63 uint32_t recordId
= 0;
66 m_Cache
[recordId
] = false;
71 m_Cache
.clear(); // assume full sync
72 trace
.log("Load failed!");
78 bool DatabaseSyncState::SaveCache()
80 Trace
trace("SaveCache", m_Desc
.c_str());
82 std::ofstream
ofs(m_CacheFilename
.c_str());
86 cache_type::const_iterator i
= m_Cache
.begin();
87 for( ; i
!= m_Cache
.end(); ++i
) {
88 ofs
<< i
->first
<< std::endl
;
90 return !ofs
.bad() && !ofs
.fail();
93 bool DatabaseSyncState::LoadMap()
95 return m_IdMap
.Load(m_MapFilename
.c_str());
98 bool DatabaseSyncState::SaveMap()
100 return m_IdMap
.Save(m_MapFilename
.c_str());
103 // cycle through the map and search the state table for each rid,
104 // and remove any that do not exist
105 void DatabaseSyncState::CleanupMap()
107 idmap::iterator i
= m_IdMap
.begin();
108 for( ; i
!= m_IdMap
.end(); ++i
) {
109 if( !m_Table
.GetIndex(i
->second
) ) {
110 // Record Id does not exist in state table, so it is
111 // not needed anymore in the ID map
120 /// Searches for the given record ID, and returns the mapped UID. If not
121 /// found, it creates a new UID and returns it without mapping it.
123 std::string
DatabaseSyncState::Map2Uid(uint32_t recordId
) const
125 // search the idmap for the UID
127 idmap::const_iterator mapped_id
;
128 if( m_IdMap
.RidExists(recordId
, &mapped_id
) ) {
129 uid
= mapped_id
->first
;
132 // not mapped, map it ourselves
133 char *puid
= g_strdup_printf("%s-%u", m_Desc
.c_str(), recordId
);
140 unsigned long DatabaseSyncState::GetMappedRecordId(const std::string
&uid
)
142 Trace
trace("DatabaseSyncState::GetMappedRecordId()", m_Desc
.c_str());
144 // if already in map, use the matching rid
145 idmap::const_iterator it
;
146 if( m_IdMap
.UidExists(uid
, &it
) ) {
147 trace
.logf(_("found existing uid in map: %lu"), it
->second
);
151 // nothing in the map, so try to convert the string to a number
152 unsigned long RecordId
;
153 if( sscanf(uid
.c_str(), "%lu", &RecordId
) != 0 ) {
154 trace
.logf("parsed uid as: %lu", RecordId
);
155 if( m_IdMap
.Map(uid
, RecordId
) != m_IdMap
.end() )
158 trace
.logf(_("parsed uid already exists in map, skipping"));
161 // create one of our own, if we get here...
162 // do this in a loop to keep going until we find an ID that's unique
164 RecordId
= m_Table
.MakeNewRecordId();
165 } while( m_IdMap
.Map(uid
, RecordId
) == m_IdMap
.end() );
167 trace
.logf(_("made new record id: %lu"), RecordId
);
173 //////////////////////////////////////////////////////////////////////////////
174 // BarryEnvironment Public API
176 BarryEnvironment::BarryEnvironment(OSyncMember
*pm
)
180 m_CalendarSync(pm
, "calendar"),
181 m_ContactsSync(pm
, "contacts")
185 BarryEnvironment::~BarryEnvironment()
189 void BarryEnvironment::DoConnect()
192 throw std::logic_error(_("Tried to use empty Connector"));
196 // Save the DBIDs and DBNames of the databases we will work with
197 if( m_CalendarSync
.m_Sync
) {
198 m_CalendarSync
.m_dbName
= Barry::Calendar::GetDBName();
199 m_CalendarSync
.m_dbId
= m_con
->GetDesktop().GetDBID(Barry::Calendar::GetDBName());
202 if( m_ContactsSync
.m_Sync
) {
203 m_ContactsSync
.m_dbId
= m_con
->GetDesktop().GetDBID(Barry::Contact::GetDBName());
204 m_ContactsSync
.m_dbName
= Barry::Contact::GetDBName();
208 void BarryEnvironment::SetPassword(const std::string
&password
)
210 m_password
= password
;
212 m_con
->SetPassword(password
.c_str());
215 void BarryEnvironment::Connect(const Barry::ProbeResult
&result
)
217 m_con
.reset(new DesktopConnector(m_password
.c_str(), "UTF-8", result
));
221 void BarryEnvironment::Reconnect()
226 void BarryEnvironment::Disconnect()
231 void BarryEnvironment::ClearDirtyFlags(Barry::RecordStateTable
&table
,
232 const std::string
&dbname
)
234 Trace
trace("ClearDirtyFlags");
236 unsigned int dbId
= m_con
->GetDesktop().GetDBID(dbname
);
238 Barry::RecordStateTable::StateMapType::const_iterator i
= table
.StateMap
.begin();
239 for( ; i
!= table
.StateMap
.end(); ++i
) {
240 if( i
->second
.Dirty
) {
241 trace
.logf(_("Clearing dirty flag for db %u, index %u"),
243 m_con
->GetDesktop().ClearDirty(dbId
, i
->first
);
248 void BarryEnvironment::ClearCalendarDirtyFlags()
250 Trace
trace("ClearCalendarDirtyFlags");
251 ClearDirtyFlags(m_CalendarSync
.m_Table
, Barry::Calendar::GetDBName());
254 void BarryEnvironment::ClearContactsDirtyFlags()
256 Trace
trace("ClearContactsDirtyFlags");
257 ClearDirtyFlags(m_ContactsSync
.m_Table
, Barry::Contact::GetDBName());
260 DatabaseSyncState
* BarryEnvironment::GetSyncObject(OSyncChange
*change
)
262 Trace
trace("BarryEnvironment::GetSyncObject()");
264 OSyncObjType
*type
= osync_change_get_objtype(change
);
265 const char *name
= osync_objtype_get_name(type
);
266 if( strcmp(name
, "event") == 0 ) {
267 return &m_CalendarSync
;
269 else if( strcmp(name
, "contact") == 0 ) {
270 return &m_ContactsSync
;
277 void BarryEnvironment::ParseConfig(const char *data
, int size
)
279 Trace
trace("ParseConfig");
281 m_ConfigData
.assign(data
, size
);
283 // The config data should contain:
284 // - Keyword: DebugMode
285 // - if the single word "DebugMode" is found, enable Debug
287 // - Keyword: Device <pin> ...
288 // - PIN of device to sync with
289 // - or a flag that says "autoconfig with first device found"
290 // which will autodetect, and update the config
291 // automatically with the found PIN... all future syncs
292 // will then have a PIN
293 // - checkboxes for (both can be on):
294 // - sync calendar items
297 std::istringstream
iss(m_ConfigData
);
299 while( std::getline(iss
, line
) ) {
304 std::istringstream
ils(line
);
305 int cal
= 0, con
= 0;
310 if( key
== "DebugMode" ) {
313 else if( key
== "Device" ) {
314 ils
>> std::hex
>> m_pin
>> cal
>> con
;
316 std::ostringstream oss
;
317 oss
<< std::hex
<< m_pin
;
318 trace
.log(oss
.str().c_str());
321 m_CalendarSync
.m_Sync
= true;
322 trace
.log(_("calendar syncing enabled"));
326 m_ContactsSync
.m_Sync
= true;
327 trace
.log(_("contacts syncing enabled"));
330 else if ( key
== "Password" ) {
332 trace
.log(_("using password from config file"));
337 //void BarryEnvironment::BuildConfig()
339 // FIXME - build back into one long string