Show
Ignore:
Timestamp:
10/28/07 23:41:34 (1 year ago)
Author:
daboo
Message:

Calendar ctag handling. Don't list the calendars/address books when first starting up if
we have a fresh cache.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • Mulberry/branches/v4.1d1/Sources_Common/Calendar_Store/Protocols/CCalendarProtocol.cpp

    r86 r113  
    3232#include "CConnectionManager.h" 
    3333#include "CLocalCalendarClient.h" 
     34#include "CPasswordManager.h" 
    3435#include "CPreferences.h" 
    3536#include "CWebDAVCalendarClient.h" 
     
    3839 
    3940#include "CICalendarSync.h" 
     41#include "CICalendarDateTime.h" 
     42#include "CICalendarDuration.h" 
    4043 
    4144#include "XMLDocument.h" 
     
    6063        mCacheIsPrimary = false; 
    6164        mSyncingList = false; 
     65        mListedFromCache = false; 
    6266 
    6367        // Only WebDAV servers can disconnect 
     
    482486                        // Only bother if it contains something 
    483487                        if (!auth->GetPswd().empty()) 
     488                        { 
    484489                                CCalendarProtocol::SetCachedPswd(auth->GetUID(), auth->GetPswd()); 
     490                                CPasswordManager::GetManager()->AddPassword(GetAccount(), auth->GetPswd()); 
     491                        } 
    485492                } 
    486493 
     
    569576        else 
    570577        { 
    571                 // Now get new list 
    572                 mClient->_ListCalendars(&mStoreRoot); 
    573  
    574                 // Always keep disconnected cache list in sync with server 
    575                 if (mCacheClient != NULL) 
    576                 { 
    577                         DumpCalendars(); 
    578                 } 
     578                // First try the disconnected cache - but only use if current 
     579                if (mListedFromCache || ((mCacheClient == NULL) || !ReadCalendars(true))) 
     580                { 
     581                        // Now get new list 
     582                        mClient->_ListCalendars(&mStoreRoot); 
     583 
     584                        // Always keep disconnected cache list in sync with server 
     585                        if (mCacheClient != NULL) 
     586                        { 
     587                                DumpCalendars(); 
     588                        } 
     589                } 
     590                else 
     591                        mListedFromCache = true; 
    579592        } 
    580593 
     
    10061019                //  2.1 Add new components to server and cache info 
    10071020                //  2.2 Remove deleted components from server and cached server info if still present on server 
    1008                 //  2.3 Cache info for changed items for later sync 
     1021                //  2.3 Cache info for changed items for later sync (or change them immediately if the server has not changed 
    10091022                // 
    10101023                // 3. Scan list of local components 
     
    10201033                // 4. Copy remaining items in server set to local cache - they are new items 
    10211034                // 
     1035                // We only need to do steps 3 & 4 if the data on the server is known to have changed. 
     1036                // 
    10221037                 
    10231038                // Now do it... 
     
    10251040                // Step 1 
    10261041                cdstrmap comps; 
    1027                 mClient->_GetComponentInfo(node, cal, comps); 
     1042                bool server_changed = mClient->_CalendarChanged(node, cal); 
     1043                if (server_changed) 
     1044                        mClient->_GetComponentInfo(node, cal, comps); 
     1045                else 
     1046                { 
     1047                        mCacheClient->_ReadFullCalendar(node, cal); 
     1048                } 
    10281049                 
    10291050                // Step 2 
     
    10631084                        // Step 2.3 
    10641085                        else if ((*iter).second.GetAction() == iCal::CICalendarComponentRecord::eChanged) 
    1065                                 cache_changed.insert(cdstrmap::value_type((*iter).second.GetRURL(), (*iter).second.GetETag())); 
     1086                        { 
     1087                                if (server_changed) 
     1088                                        cache_changed.insert(cdstrmap::value_type((*iter).second.GetRURL(), (*iter).second.GetETag())); 
     1089                                else 
     1090                                { 
     1091                                        // Change it on the server 
     1092                                        const iCal::CICalendarComponent* comp = cal.GetComponentByKey((*iter).first); 
     1093                                        mClient->_ChangeComponent(node, cal, *comp); 
     1094                                        cache_changed.insert(cdstrmap::value_type((*iter).second.GetRURL(), (*iter).second.GetETag())); 
     1095                                } 
     1096                        } 
    10661097                } 
    10671098                 
    10681099                 
    10691100                // Now do sync 
    1070                  
    1071                 // Get component info from cache 
    1072                 iCal::CICalendarComponentDBList dbs; 
    1073                 cal.GetAllDBs(dbs); 
    1074                 cdstrvect component_keys; 
    1075                 for(iCal::CICalendarComponentDBList::const_iterator iter1 = dbs.begin(); iter1 != dbs.end(); iter1++) 
    1076                 { 
    1077                         for(iCal::CICalendarComponentDB::const_iterator iter2 = (*iter1)->begin(); iter2 != (*iter1)->end(); iter2++) 
     1101                if (server_changed) 
     1102                { 
     1103                        // Get component info from cache 
     1104                        iCal::CICalendarComponentDBList dbs; 
     1105                        cal.GetAllDBs(dbs); 
     1106                        cdstrvect component_keys; 
     1107                        for(iCal::CICalendarComponentDBList::const_iterator iter1 = dbs.begin(); iter1 != dbs.end(); iter1++) 
    10781108                        { 
    1079                                 component_keys.push_back((*iter2).second->GetMapKey()); 
     1109                                for(iCal::CICalendarComponentDB::const_iterator iter2 = (*iter1)->begin(); iter2 != (*iter1)->end(); iter2++) 
     1110                                { 
     1111                                        component_keys.push_back((*iter2).second->GetMapKey()); 
     1112                                } 
    10801113                        } 
    1081                 } 
    1082                  
    1083                 // Step 3 
    1084                 cdstrset matching_components; 
    1085                 for(cdstrvect::const_iterator iter = component_keys.begin(); iter != component_keys.end(); iter++) 
    1086                 { 
    1087                         iCal::CICalendarComponent* cache_comp = cal.GetComponentByKey(*iter); 
    1088                         if (cache_comp == NULL) 
    1089                                 continue; 
    1090  
    1091                         // Get this components RURL 
    1092                         cdstring cache_rurl = cache_comp->GetRURL(); 
    1093                         cdstring cache_etag = cache_comp->GetETag(); 
    10941114                         
    1095                         // Get the server info 
    1096                         cdstring server_rurl; 
    1097                         cdstring server_etag; 
    1098                         cdstrmap::const_iterator found = comps.find(cache_rurl); 
    1099                         if (found != comps.end()) 
     1115                        // Step 3 
     1116                        cdstrset matching_components; 
     1117                        for(cdstrvect::const_iterator iter = component_keys.begin(); iter != component_keys.end(); iter++) 
    11001118                        { 
    1101                                 server_rurl = (*found).first; 
    1102                                 server_etag = (*found).second; 
    1103                         } 
    1104  
    1105                         // Step 3.1 
    1106                         if (cache_added.count(cache_rurl) != 0) 
    1107                                 continue; 
    1108                          
    1109                         // Step 3.2 
    1110                         else if (cache_changed.count(cache_rurl) != 0) 
    1111                         { 
    1112                                 // Step 3.2.1 
    1113                                 if (cache_etag == server_etag) 
     1119                                iCal::CICalendarComponent* cache_comp = cal.GetComponentByKey(*iter); 
     1120                                if (cache_comp == NULL) 
     1121                                        continue; 
     1122 
     1123                                // Get this components RURL 
     1124                                cdstring cache_rurl = cache_comp->GetRURL(); 
     1125                                cdstring cache_etag = cache_comp->GetETag(); 
     1126                                 
     1127                                // Get the server info 
     1128                                cdstring server_rurl; 
     1129                                cdstring server_etag; 
     1130                                cdstrmap::const_iterator found = comps.find(cache_rurl); 
     1131                                if (found != comps.end()) 
    11141132                                { 
    1115                                         // Write changed cache component to server 
    1116                                         mClient->_ChangeComponent(node, cal, *cache_comp); 
     1133                                        server_rurl = (*found).first; 
     1134                                        server_etag = (*found).second; 
    11171135                                } 
     1136 
     1137                                // Step 3.1 
     1138                                if (cache_added.count(cache_rurl) != 0) 
     1139                                        continue; 
    11181140                                 
    1119                                 // Step 3.2.2 
    1120                                 else 
     1141                                // Step 3.2 
     1142                                else if (cache_changed.count(cache_rurl) != 0) 
    11211143                                { 
    1122                                         // Do iCal SEQ etc comparison 
     1144                                        // Step 3.2.1 
     1145                                        if (cache_etag == server_etag) 
     1146                                        { 
     1147                                                // Write changed cache component to server 
     1148                                                mClient->_ChangeComponent(node, cal, *cache_comp); 
     1149                                        } 
    11231150                                         
    1124                                         // First read in component from server into temp calendar 
    1125                                         iCal::CICalendar tempcal; 
    1126                                         iCal::CICalendarComponent* server_comp = mClient->_ReadComponent(node, tempcal, server_rurl); 
    1127                                         if (server_comp != NULL) 
     1151                                        // Step 3.2.2 
     1152                                        else 
    11281153                                        { 
    1129                                                 int result = iCal::CICalendarSync::CompareComponentVersions(server_comp, cache_comp); 
     1154                                                // Do iCal SEQ etc comparison 
    11301155                                                 
    1131                                                 if (result == 1) 
     1156                                                // First read in component from server into temp calendar 
     1157                                                iCal::CICalendar tempcal; 
     1158                                                iCal::CICalendarComponent* server_comp = mClient->_ReadComponent(node, tempcal, server_rurl); 
     1159                                                if (server_comp != NULL) 
    11321160                                                { 
    1133                                                         // Cache is newer than server - cache overwrites to server 
    1134                                                         mClient->_ChangeComponent(node, cal, *cache_comp); 
    1135                                                 } 
    1136                                                 else if (result == -1) 
    1137                                                 { 
    1138                                                         // Cache is older than server - server overwrites cache 
    1139  
    1140                                                         // Remove the cached component first 
    1141                                                         cal.RemoveComponentByKey(cache_comp->GetMapKey()); 
    1142                                                         cache_comp = NULL; 
     1161                                                        int result = iCal::CICalendarSync::CompareComponentVersions(server_comp, cache_comp); 
    11431162                                                         
    1144                                                         // Copy component from server into local cache effectively replacing old one 
    1145                                                         iCal::CICalendarComponent* new_comp = server_comp->clone(); 
    1146                                                         new_comp->SetCalendar(cal.GetRef()); 
    1147                                                         cal.AddComponent(new_comp); 
     1163                                                        if (result == 1) 
     1164                                                        { 
     1165                                                                // Cache is newer than server - cache overwrites to server 
     1166                                                                mClient->_ChangeComponent(node, cal, *cache_comp); 
     1167                                                        } 
     1168                                                        else if (result == -1) 
     1169                                                        { 
     1170                                                                // Cache is older than server - server overwrites cache 
     1171 
     1172                                                                // Remove the cached component first 
     1173                                                                cal.RemoveComponentByKey(cache_comp->GetMapKey()); 
     1174                                                                cache_comp = NULL; 
     1175                                                                 
     1176                                                                // Copy component from server into local cache effectively replacing old one 
     1177                                                                iCal::CICalendarComponent* new_comp = server_comp->clone(); 
     1178                                                                new_comp->SetCalendar(cal.GetRef()); 
     1179                                                                cal.AddComponent(new_comp); 
     1180                                                        } 
    11481181                                                } 
    11491182                                        } 
    11501183                                } 
     1184                                 
     1185                                // Step 3.3 
     1186                                else if (!server_rurl.empty()) 
     1187                                { 
     1188                                        // Step 3.3.1 
     1189                                        if (cache_etag != server_etag) 
     1190                                        { 
     1191                                                // Copy from server to cache overwriting cache value 
     1192                                                 
     1193                                                // Remove the cached component first 
     1194                                                cal.RemoveComponentByKey(cache_comp->GetMapKey()); 
     1195                                                cache_comp = NULL; 
     1196                                                 
     1197                                                // Read component from server into local cache effectively replacing old one 
     1198                                                mClient->_ReadComponent(node, cal, server_rurl); 
     1199                                        } 
     1200                                } 
     1201                                 
     1202                                // Step 3.4 
     1203                                else 
     1204                                { 
     1205                                        // comp is deleted in this call 
     1206                                        cal.RemoveComponentByKey(cache_comp->GetMapKey()); 
     1207                                        cache_comp = NULL; 
     1208                                } 
     1209                                 
     1210                                // Step 3.5 
     1211                                if (!server_rurl.empty()) 
     1212                                        matching_components.insert(server_rurl); 
    11511213                        } 
    11521214                         
    1153                         // Step 3.3 
    1154                         else if (!server_rurl.empty()) 
     1215                        // Step 4 
     1216                        cdstrvect rurls; 
     1217                        for(cdstrmap::const_iterator iter = comps.begin(); iter != comps.end(); iter++) 
    11551218                        { 
    1156                                 // Step 3.3.1 
    1157                                 if (cache_etag != server_etag) 
    1158                                 { 
    1159                                         // Copy from server to cache overwriting cache value 
    1160                                          
    1161                                         // Remove the cached component first 
    1162                                         cal.RemoveComponentByKey(cache_comp->GetMapKey()); 
    1163                                         cache_comp = NULL; 
    1164                                          
    1165                                         // Read component from server into local cache effectively replacing old one 
    1166                                         mClient->_ReadComponent(node, cal, server_rurl); 
    1167                                 } 
     1219                                cdstrset::const_iterator found = matching_components.find((*iter).first); 
     1220                                if (found == matching_components.end()) 
     1221                                        rurls.push_back((*iter).first); 
    11681222                        } 
    1169                          
    1170                         // Step 3.4 
    1171                         else 
    1172                         { 
    1173                                 // comp is deleted in this call 
    1174                                 cal.RemoveComponentByKey(cache_comp->GetMapKey()); 
    1175                                 cache_comp = NULL; 
    1176                         } 
    1177                          
    1178                         // Step 3.5 
    1179                         if (!server_rurl.empty()) 
    1180                                 matching_components.insert(server_rurl); 
    1181                 } 
    1182                  
    1183                 // Step 4 
    1184                 cdstrvect rurls; 
    1185                 for(cdstrmap::const_iterator iter = comps.begin(); iter != comps.end(); iter++) 
    1186                 { 
    1187                         cdstrset::const_iterator found = matching_components.find((*iter).first); 
    1188                         if (found == matching_components.end()) 
    1189                                 rurls.push_back((*iter).first); 
    1190                 } 
    1191  
    1192                 // Read components from server into local cache as its a new one on the server 
    1193                 if (rurls.size() != 0) 
    1194                         mClient->_ReadComponents(node, cal, rurls); 
     1223 
     1224                        // Read components from server into local cache as its a new one on the server 
     1225                        if (rurls.size() != 0) 
     1226                                mClient->_ReadComponents(node, cal, rurls); 
     1227                } 
    11951228 
    11961229                // Clear out cache recording 
    11971230                cal.ClearRecording(); 
    11981231                 
     1232                // Get the current server sync token 
     1233                mClient->_UpdateSyncToken(node, cal); 
     1234 
    11991235                // Now write back cache 
    1200                 if (mCacheClient->_TouchCalendar(node)) 
     1236                if (!mCacheClient->_TouchCalendar(node)) 
    12011237                        DumpCalendars(); 
    12021238                mCacheClient->_WriteFullCalendar(node, cal); 
     
    17421778        xmllib::XMLObject::WriteAttribute(doc->GetRoot(), cXMLAttribute_version, (uint32_t)1); 
    17431779         
     1780        // Store the current date 
     1781        iCal::CICalendarDateTime dt = iCal::CICalendarDateTime::GetNowUTC(); 
     1782        dt.SetDateOnly(true); 
     1783        xmllib::XMLObject::WriteAttribute(doc->GetRoot(), cXMLAttribute_datestamp, dt.GetText()); 
     1784         
    17441785        // Now add each node (and child nodes) to XML doc 
    17451786        mStoreRoot.WriteXML(doc.get(), doc->GetRoot(), true); 
     
    17501791} 
    17511792 
    1752 void CCalendarProtocol::ReadCalendars() 
    1753 { 
     1793bool CCalendarProtocol::ReadCalendars(bool only_if_current) 
     1794{ 
     1795        bool is_current = false; 
    17541796        cdstring list_name = mOfflineCWD + cCalendarListName; 
    17551797         
     
    17641806                xmllib::XMLNode* root = parser.Document()->GetRoot(); 
    17651807                if (!root->CompareFullName(cXMLElement_calendarlist)) 
    1766                         return; 
     1808                        return is_current; 
    17671809                 
    1768                 // Now have store root read in all children 
    1769                 mStoreRoot.ReadXML(root, true); 
    1770  
    1771                 // Always cache the disconnected state 
    1772                 mStoreRoot.TestDisconnectCache(); 
    1773         } 
    1774 } 
     1810                // Get the datestamp 
     1811                cdstring dtstamp; 
     1812                if (xmllib::XMLObject::ReadAttribute(root, cXMLAttribute_datestamp, dtstamp)) 
     1813                { 
     1814                        iCal::CICalendarDateTime dtnow = iCal::CICalendarDateTime::GetNowUTC(); 
     1815                        dtnow.SetDateOnly(true); 
     1816 
     1817                        iCal::CICalendarDateTime dt; 
     1818                        dt.Parse(dtstamp); 
     1819                         
     1820                        iCal::CICalendarDuration diff = dtnow - dt; 
     1821                        is_current = (diff.GetTotalSeconds() <= 48 * 60 * 60); 
     1822                } 
     1823 
     1824                if (!only_if_current || is_current) 
     1825                { 
     1826                        // Now have store root read in all children 
     1827                        mStoreRoot.ReadXML(root, true); 
     1828 
     1829                        // Always cache the disconnected state 
     1830                        if (IsDisconnected() || mCacheIsPrimary) 
     1831                                mStoreRoot.TestDisconnectCache(); 
     1832                } 
     1833        } 
     1834         
     1835        return is_current; 
     1836}