2 // \file environment.cc
3 // Container / environment class for the sync module.
7 Copyright (C) 2006-2012, 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"
32 using namespace Barry
;
34 //////////////////////////////////////////////////////////////////////////////
37 DatabaseSyncState::DatabaseSyncState(OSyncMember
*pm
, const char *description
)
42 m_CacheFilename
= m_MapFilename
=
43 osync_member_get_configdir(pm
);
44 m_CacheFilename
+= "/barry_" + m_Desc
+ "_cache.txt";
45 m_MapFilename
+= "/barry_" + m_Desc
+ "_idmap.txt";
48 DatabaseSyncState::~DatabaseSyncState()
52 bool DatabaseSyncState::LoadCache()
54 Trace
trace("LoadCache", m_Desc
.c_str());
57 std::ifstream
ifs(m_CacheFilename
.c_str());
62 uint32_t recordId
= 0;
65 m_Cache
[recordId
] = false;
70 m_Cache
.clear(); // assume full sync
71 trace
.log("Load failed!");
77 bool DatabaseSyncState::SaveCache()
79 Trace
trace("SaveCache", m_Desc
.c_str());
81 std::ofstream
ofs(m_CacheFilename
.c_str());
85 cache_type::const_iterator i
= m_Cache
.begin();
86 for( ; i
!= m_Cache
.end(); ++i
) {
87 ofs
<< i
->first
<< std::endl
;
89 return !ofs
.bad() && !ofs
.fail();
92 bool DatabaseSyncState::LoadMap()
94 return m_IdMap
.Load(m_MapFilename
.c_str());
97 bool DatabaseSyncState::SaveMap()
99 return m_IdMap
.Save(m_MapFilename
.c_str());
102 // cycle through the map and search the state table for each rid,
103 // and remove any that do not exist
104 void DatabaseSyncState::CleanupMap()
106 idmap::iterator i
= m_IdMap
.begin();
107 for( ; i
!= m_IdMap
.end(); ++i
) {
108 if( !m_Table
.GetIndex(i
->second
) ) {
109 // Record Id does not exist in state table, so it is
110 // not needed anymore in the ID map
119 /// Searches for the given record ID, and returns the mapped UID. If not
120 /// found, it creates a new UID and returns it without mapping it.
122 std::string
DatabaseSyncState::Map2Uid(uint32_t recordId
) const
124 // search the idmap for the UID
126 idmap::const_iterator mapped_id
;
127 if( m_IdMap
.RidExists(recordId
, &mapped_id
) ) {
128 uid
= mapped_id
->first
;
131 // not mapped, map it ourselves
132 char *puid
= g_strdup_printf("%s-%u", m_Desc
.c_str(), recordId
);
139 unsigned long DatabaseSyncState::GetMappedRecordId(const std::string
&uid
)
141 Trace
trace("DatabaseSyncState::GetMappedRecordId()", m_Desc
.c_str());
143 // if already in map, use the matching rid
144 idmap::const_iterator it
;
145 if( m_IdMap
.UidExists(uid
, &it
) ) {
146 trace
.logf("found existing uid in map: %lu", it
->second
);
150 // nothing in the map, so try to convert the string to a number
151 unsigned long RecordId
;
152 if( sscanf(uid
.c_str(), "%lu", &RecordId
) != 0 ) {
153 trace
.logf("parsed uid as: %lu", RecordId
);
154 if( m_IdMap
.Map(uid
, RecordId
) != m_IdMap
.end() )
157 trace
.logf("parsed uid already exists in map, skipping");
160 // create one of our own, if we get here...
161 // do this in a loop to keep going until we find an ID that's unique
163 RecordId
= m_Table
.MakeNewRecordId();
164 } while( m_IdMap
.Map(uid
, RecordId
) == m_IdMap
.end() );
166 trace
.logf("made new record id: %lu", RecordId
);
172 //////////////////////////////////////////////////////////////////////////////
173 // BarryEnvironment Public API
175 BarryEnvironment::BarryEnvironment(OSyncMember
*pm
)
179 m_CalendarSync(pm
, "calendar"),
180 m_ContactsSync(pm
, "contacts")
184 BarryEnvironment::~BarryEnvironment()
188 void BarryEnvironment::DoConnect()
191 throw std::logic_error("Tried to use empty Connector");
195 // Save the DBIDs and DBNames of the databases we will work with
196 if( m_CalendarSync
.m_Sync
) {
197 m_CalendarSync
.m_dbName
= Barry::Calendar::GetDBName();
198 m_CalendarSync
.m_dbId
= m_con
->GetDesktop().GetDBID(Barry::Calendar::GetDBName());
201 if( m_ContactsSync
.m_Sync
) {
202 m_ContactsSync
.m_dbId
= m_con
->GetDesktop().GetDBID(Barry::Contact::GetDBName());
203 m_ContactsSync
.m_dbName
= Barry::Contact::GetDBName();
207 void BarryEnvironment::SetPassword(const std::string
&password
)
209 m_password
= password
;
211 m_con
->SetPassword(password
.c_str());
214 void BarryEnvironment::Connect(const Barry::ProbeResult
&result
)
216 m_con
.reset(new DesktopConnector(m_password
.c_str(), "UTF-8", result
));
220 void BarryEnvironment::Reconnect()
225 void BarryEnvironment::Disconnect()
230 void BarryEnvironment::ClearDirtyFlags(Barry::RecordStateTable
&table
,
231 const std::string
&dbname
)
233 Trace
trace("ClearDirtyFlags");
235 unsigned int dbId
= m_con
->GetDesktop().GetDBID(dbname
);
237 Barry::RecordStateTable::StateMapType::const_iterator i
= table
.StateMap
.begin();
238 for( ; i
!= table
.StateMap
.end(); ++i
) {
239 if( i
->second
.Dirty
) {
240 trace
.logf("Clearing dirty flag for db %u, index %u",
242 m_con
->GetDesktop().ClearDirty(dbId
, i
->first
);
247 void BarryEnvironment::ClearCalendarDirtyFlags()
249 Trace
trace("ClearCalendarDirtyFlags");
250 ClearDirtyFlags(m_CalendarSync
.m_Table
, Barry::Calendar::GetDBName());
253 void BarryEnvironment::ClearContactsDirtyFlags()
255 Trace
trace("ClearContactsDirtyFlags");
256 ClearDirtyFlags(m_ContactsSync
.m_Table
, Barry::Contact::GetDBName());
259 DatabaseSyncState
* BarryEnvironment::GetSyncObject(OSyncChange
*change
)
261 Trace
trace("BarryEnvironment::GetSyncObject()");
263 OSyncObjType
*type
= osync_change_get_objtype(change
);
264 const char *name
= osync_objtype_get_name(type
);
265 if( strcmp(name
, "event") == 0 ) {
266 return &m_CalendarSync
;
268 else if( strcmp(name
, "contact") == 0 ) {
269 return &m_ContactsSync
;
276 void BarryEnvironment::ParseConfig(const char *data
, int size
)
278 Trace
trace("ParseConfig");
280 m_ConfigData
.assign(data
, size
);
282 // The config data should contain:
283 // - Keyword: DebugMode
284 // - if the single word "DebugMode" is found, enable Debug
286 // - Keyword: Device <pin> ...
287 // - PIN of device to sync with
288 // - or a flag that says "autoconfig with first device found"
289 // which will autodetect, and update the config
290 // automatically with the found PIN... all future syncs
291 // will then have a PIN
292 // - checkboxes for (both can be on):
293 // - sync calendar items
296 std::istringstream
iss(m_ConfigData
);
298 while( std::getline(iss
, line
) ) {
303 std::istringstream
ils(line
);
304 int cal
= 0, con
= 0;
309 if( key
== "DebugMode" ) {
312 else if( key
== "Device" ) {
313 ils
>> std::hex
>> m_pin
>> cal
>> con
;
315 std::ostringstream oss
;
316 oss
<< std::hex
<< m_pin
;
317 trace
.log(oss
.str().c_str());
320 m_CalendarSync
.m_Sync
= true;
321 trace
.log("calendar syncing enabled");
325 m_ContactsSync
.m_Sync
= true;
326 trace
.log("contacts syncing enabled");
329 else if ( key
== "Password" ) {
331 trace
.log("using password from config file");
336 //void BarryEnvironment::BuildConfig()
338 // FIXME - build back into one long string