| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "sync/engine/model_type_sync_proxy_impl.h" | 5 #include "sync/engine/model_type_sync_proxy_impl.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/location.h" | 8 #include "base/location.h" |
| 9 #include "sync/engine/model_type_entity.h" | 9 #include "sync/engine/model_type_entity.h" |
| 10 #include "sync/engine/model_type_sync_worker.h" | 10 #include "sync/engine/model_type_sync_worker.h" |
| 11 #include "sync/internal_api/public/sync_context_proxy.h" | 11 #include "sync/internal_api/public/sync_context_proxy.h" |
| 12 #include "sync/syncable/syncable_util.h" | 12 #include "sync/syncable/syncable_util.h" |
| 13 | 13 |
| 14 namespace syncer { | 14 namespace syncer { |
| 15 | 15 |
| 16 ModelTypeSyncProxyImpl::ModelTypeSyncProxyImpl(ModelType type) | 16 ModelTypeSyncProxyImpl::ModelTypeSyncProxyImpl(ModelType type) |
| 17 : type_(type), | 17 : type_(type), |
| 18 is_preferred_(false), | 18 is_preferred_(false), |
| 19 is_connected_(false), | 19 is_connected_(false), |
| 20 entities_deleter_(&entities_), | |
| 21 pending_updates_map_deleter_(&pending_updates_map_), | |
| 22 weak_ptr_factory_for_ui_(this), | 20 weak_ptr_factory_for_ui_(this), |
| 23 weak_ptr_factory_for_sync_(this) { | 21 weak_ptr_factory_for_sync_(this) { |
| 24 } | 22 } |
| 25 | 23 |
| 26 ModelTypeSyncProxyImpl::~ModelTypeSyncProxyImpl() { | 24 ModelTypeSyncProxyImpl::~ModelTypeSyncProxyImpl() { |
| 27 } | 25 } |
| 28 | 26 |
| 29 bool ModelTypeSyncProxyImpl::IsPreferred() const { | 27 bool ModelTypeSyncProxyImpl::IsPreferred() const { |
| 30 DCHECK(CalledOnValidThread()); | 28 DCHECK(CalledOnValidThread()); |
| 31 return is_preferred_; | 29 return is_preferred_; |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 100 FlushPendingCommitRequests(); | 98 FlushPendingCommitRequests(); |
| 101 } | 99 } |
| 102 | 100 |
| 103 void ModelTypeSyncProxyImpl::Put(const std::string& client_tag, | 101 void ModelTypeSyncProxyImpl::Put(const std::string& client_tag, |
| 104 const sync_pb::EntitySpecifics& specifics) { | 102 const sync_pb::EntitySpecifics& specifics) { |
| 105 DCHECK_EQ(type_, GetModelTypeFromSpecifics(specifics)); | 103 DCHECK_EQ(type_, GetModelTypeFromSpecifics(specifics)); |
| 106 | 104 |
| 107 const std::string client_tag_hash( | 105 const std::string client_tag_hash( |
| 108 syncable::GenerateSyncableHash(type_, client_tag)); | 106 syncable::GenerateSyncableHash(type_, client_tag)); |
| 109 | 107 |
| 110 EntityMap::iterator it = entities_.find(client_tag_hash); | 108 EntityMap::const_iterator it = entities_.find(client_tag_hash); |
| 111 if (it == entities_.end()) { | 109 if (it == entities_.end()) { |
| 112 scoped_ptr<ModelTypeEntity> entity(ModelTypeEntity::NewLocalItem( | 110 scoped_ptr<ModelTypeEntity> entity(ModelTypeEntity::NewLocalItem( |
| 113 client_tag, specifics, base::Time::Now())); | 111 client_tag, specifics, base::Time::Now())); |
| 114 entities_.insert(std::make_pair(client_tag_hash, entity.release())); | 112 entities_.insert(client_tag_hash, entity.Pass()); |
| 115 } else { | 113 } else { |
| 116 ModelTypeEntity* entity = it->second; | 114 ModelTypeEntity* entity = it->second; |
| 117 entity->MakeLocalChange(specifics); | 115 entity->MakeLocalChange(specifics); |
| 118 } | 116 } |
| 119 | 117 |
| 120 FlushPendingCommitRequests(); | 118 FlushPendingCommitRequests(); |
| 121 } | 119 } |
| 122 | 120 |
| 123 void ModelTypeSyncProxyImpl::Delete(const std::string& client_tag) { | 121 void ModelTypeSyncProxyImpl::Delete(const std::string& client_tag) { |
| 124 const std::string client_tag_hash( | 122 const std::string client_tag_hash( |
| 125 syncable::GenerateSyncableHash(type_, client_tag)); | 123 syncable::GenerateSyncableHash(type_, client_tag)); |
| 126 | 124 |
| 127 EntityMap::iterator it = entities_.find(client_tag_hash); | 125 EntityMap::const_iterator it = entities_.find(client_tag_hash); |
| 128 if (it == entities_.end()) { | 126 if (it == entities_.end()) { |
| 129 // That's unusual, but not necessarily a bad thing. | 127 // That's unusual, but not necessarily a bad thing. |
| 130 // Missing is as good as deleted as far as the model is concerned. | 128 // Missing is as good as deleted as far as the model is concerned. |
| 131 DLOG(WARNING) << "Attempted to delete missing item." | 129 DLOG(WARNING) << "Attempted to delete missing item." |
| 132 << " client tag: " << client_tag; | 130 << " client tag: " << client_tag; |
| 133 } else { | 131 } else { |
| 134 ModelTypeEntity* entity = it->second; | 132 ModelTypeEntity* entity = it->second; |
| 135 entity->Delete(); | 133 entity->Delete(); |
| 136 } | 134 } |
| 137 | 135 |
| 138 FlushPendingCommitRequests(); | 136 FlushPendingCommitRequests(); |
| 139 } | 137 } |
| 140 | 138 |
| 141 void ModelTypeSyncProxyImpl::FlushPendingCommitRequests() { | 139 void ModelTypeSyncProxyImpl::FlushPendingCommitRequests() { |
| 142 CommitRequestDataList commit_requests; | 140 CommitRequestDataList commit_requests; |
| 143 | 141 |
| 144 // Don't bother sending anything if there's no one to send to. | 142 // Don't bother sending anything if there's no one to send to. |
| 145 if (!IsConnected()) | 143 if (!IsConnected()) |
| 146 return; | 144 return; |
| 147 | 145 |
| 148 // Don't send anything if the type is not ready to handle commits. | 146 // Don't send anything if the type is not ready to handle commits. |
| 149 if (!data_type_state_.initial_sync_done) | 147 if (!data_type_state_.initial_sync_done) |
| 150 return; | 148 return; |
| 151 | 149 |
| 152 // TODO(rlarocque): Do something smarter than iterate here. | 150 // TODO(rlarocque): Do something smarter than iterate here. |
| 153 for (EntityMap::iterator it = entities_.begin(); it != entities_.end(); | 151 for (EntityMap::const_iterator it = entities_.begin(); it != entities_.end(); |
| 154 ++it) { | 152 ++it) { |
| 155 if (it->second->RequiresCommitRequest()) { | 153 if (it->second->RequiresCommitRequest()) { |
| 156 CommitRequestData request; | 154 CommitRequestData request; |
| 157 it->second->InitializeCommitRequestData(&request); | 155 it->second->InitializeCommitRequestData(&request); |
| 158 commit_requests.push_back(request); | 156 commit_requests.push_back(request); |
| 159 it->second->SetCommitRequestInProgress(); | 157 it->second->SetCommitRequestInProgress(); |
| 160 } | 158 } |
| 161 } | 159 } |
| 162 | 160 |
| 163 if (!commit_requests.empty()) | 161 if (!commit_requests.empty()) |
| 164 worker_->EnqueueForCommit(commit_requests); | 162 worker_->EnqueueForCommit(commit_requests); |
| 165 } | 163 } |
| 166 | 164 |
| 167 void ModelTypeSyncProxyImpl::OnCommitCompleted( | 165 void ModelTypeSyncProxyImpl::OnCommitCompleted( |
| 168 const DataTypeState& type_state, | 166 const DataTypeState& type_state, |
| 169 const CommitResponseDataList& response_list) { | 167 const CommitResponseDataList& response_list) { |
| 170 data_type_state_ = type_state; | 168 data_type_state_ = type_state; |
| 171 | 169 |
| 172 for (CommitResponseDataList::const_iterator list_it = response_list.begin(); | 170 for (CommitResponseDataList::const_iterator list_it = response_list.begin(); |
| 173 list_it != response_list.end(); | 171 list_it != response_list.end(); |
| 174 ++list_it) { | 172 ++list_it) { |
| 175 const CommitResponseData& response_data = *list_it; | 173 const CommitResponseData& response_data = *list_it; |
| 176 const std::string& client_tag_hash = response_data.client_tag_hash; | 174 const std::string& client_tag_hash = response_data.client_tag_hash; |
| 177 | 175 |
| 178 EntityMap::iterator it = entities_.find(client_tag_hash); | 176 EntityMap::const_iterator it = entities_.find(client_tag_hash); |
| 179 if (it == entities_.end()) { | 177 if (it == entities_.end()) { |
| 180 NOTREACHED() << "Received commit response for missing item." | 178 NOTREACHED() << "Received commit response for missing item." |
| 181 << " type: " << type_ << " client_tag: " << client_tag_hash; | 179 << " type: " << type_ << " client_tag: " << client_tag_hash; |
| 182 return; | 180 return; |
| 183 } else { | 181 } else { |
| 184 it->second->ReceiveCommitResponse(response_data.id, | 182 it->second->ReceiveCommitResponse(response_data.id, |
| 185 response_data.sequence_number, | 183 response_data.sequence_number, |
| 186 response_data.response_version, | 184 response_data.response_version, |
| 187 data_type_state_.encryption_key_name); | 185 data_type_state_.encryption_key_name); |
| 188 } | 186 } |
| 189 } | 187 } |
| 190 } | 188 } |
| 191 | 189 |
| 192 void ModelTypeSyncProxyImpl::OnUpdateReceived( | 190 void ModelTypeSyncProxyImpl::OnUpdateReceived( |
| 193 const DataTypeState& data_type_state, | 191 const DataTypeState& data_type_state, |
| 194 const UpdateResponseDataList& response_list, | 192 const UpdateResponseDataList& response_list, |
| 195 const UpdateResponseDataList& pending_updates) { | 193 const UpdateResponseDataList& pending_updates) { |
| 196 bool got_new_encryption_requirements = data_type_state_.encryption_key_name != | 194 bool got_new_encryption_requirements = data_type_state_.encryption_key_name != |
| 197 data_type_state.encryption_key_name; | 195 data_type_state.encryption_key_name; |
| 198 | 196 |
| 199 data_type_state_ = data_type_state; | 197 data_type_state_ = data_type_state; |
| 200 | 198 |
| 201 for (UpdateResponseDataList::const_iterator list_it = response_list.begin(); | 199 for (UpdateResponseDataList::const_iterator list_it = response_list.begin(); |
| 202 list_it != response_list.end(); | 200 list_it != response_list.end(); |
| 203 ++list_it) { | 201 ++list_it) { |
| 204 const UpdateResponseData& response_data = *list_it; | 202 const UpdateResponseData& response_data = *list_it; |
| 205 const std::string& client_tag_hash = response_data.client_tag_hash; | 203 const std::string& client_tag_hash = response_data.client_tag_hash; |
| 206 | 204 |
| 207 UpdateMap::iterator old_it = pending_updates_map_.find(client_tag_hash); | 205 // If we're being asked to apply an update to this entity, this overrides |
| 208 if (old_it != pending_updates_map_.end()) { | 206 // the previous pending updates. |
| 209 // If we're being asked to apply an update to this entity, this overrides | 207 pending_updates_map_.erase(client_tag_hash); |
| 210 // the previous pending updates. | |
| 211 delete old_it->second; | |
| 212 pending_updates_map_.erase(old_it); | |
| 213 } | |
| 214 | 208 |
| 215 EntityMap::iterator it = entities_.find(client_tag_hash); | 209 EntityMap::const_iterator it = entities_.find(client_tag_hash); |
| 216 if (it == entities_.end()) { | 210 if (it == entities_.end()) { |
| 217 scoped_ptr<ModelTypeEntity> entity = | 211 scoped_ptr<ModelTypeEntity> entity = |
| 218 ModelTypeEntity::FromServerUpdate(response_data.id, | 212 ModelTypeEntity::FromServerUpdate(response_data.id, |
| 219 response_data.client_tag_hash, | 213 response_data.client_tag_hash, |
| 220 response_data.non_unique_name, | 214 response_data.non_unique_name, |
| 221 response_data.response_version, | 215 response_data.response_version, |
| 222 response_data.specifics, | 216 response_data.specifics, |
| 223 response_data.deleted, | 217 response_data.deleted, |
| 224 response_data.ctime, | 218 response_data.ctime, |
| 225 response_data.mtime, | 219 response_data.mtime, |
| 226 response_data.encryption_key_name); | 220 response_data.encryption_key_name); |
| 227 entities_.insert(std::make_pair(client_tag_hash, entity.release())); | 221 entities_.insert(client_tag_hash, entity.Pass()); |
| 228 } else { | 222 } else { |
| 229 ModelTypeEntity* entity = it->second; | 223 ModelTypeEntity* entity = it->second; |
| 230 entity->ApplyUpdateFromServer(response_data.response_version, | 224 entity->ApplyUpdateFromServer(response_data.response_version, |
| 231 response_data.deleted, | 225 response_data.deleted, |
| 232 response_data.specifics, | 226 response_data.specifics, |
| 233 response_data.mtime, | 227 response_data.mtime, |
| 234 response_data.encryption_key_name); | 228 response_data.encryption_key_name); |
| 235 | 229 |
| 236 // TODO: Do something special when conflicts are detected. | 230 // TODO: Do something special when conflicts are detected. |
| 237 } | 231 } |
| 238 | 232 |
| 239 // If the received entity has out of date encryption, we schedule another | 233 // If the received entity has out of date encryption, we schedule another |
| 240 // commit to fix it. | 234 // commit to fix it. |
| 241 if (data_type_state_.encryption_key_name != | 235 if (data_type_state_.encryption_key_name != |
| 242 response_data.encryption_key_name) { | 236 response_data.encryption_key_name) { |
| 243 DVLOG(2) << ModelTypeToString(type_) << ": Requesting re-encrypt commit " | 237 DVLOG(2) << ModelTypeToString(type_) << ": Requesting re-encrypt commit " |
| 244 << response_data.encryption_key_name << " -> " | 238 << response_data.encryption_key_name << " -> " |
| 245 << data_type_state_.encryption_key_name; | 239 << data_type_state_.encryption_key_name; |
| 246 EntityMap::iterator it2 = entities_.find(client_tag_hash); | 240 EntityMap::const_iterator it2 = entities_.find(client_tag_hash); |
| 247 it2->second->UpdateDesiredEncryptionKey( | 241 it2->second->UpdateDesiredEncryptionKey( |
| 248 data_type_state_.encryption_key_name); | 242 data_type_state_.encryption_key_name); |
| 249 } | 243 } |
| 250 } | 244 } |
| 251 | 245 |
| 252 // Save pending updates in the appropriate data structure. | 246 // Save pending updates in the appropriate data structure. |
| 253 for (UpdateResponseDataList::const_iterator list_it = pending_updates.begin(); | 247 for (UpdateResponseDataList::const_iterator list_it = pending_updates.begin(); |
| 254 list_it != pending_updates.end(); | 248 list_it != pending_updates.end(); |
| 255 ++list_it) { | 249 ++list_it) { |
| 256 const UpdateResponseData& update = *list_it; | 250 const UpdateResponseData& update = *list_it; |
| 257 const std::string& client_tag_hash = update.client_tag_hash; | 251 const std::string& client_tag_hash = update.client_tag_hash; |
| 258 | 252 |
| 259 UpdateMap::iterator lookup_it = pending_updates_map_.find(client_tag_hash); | 253 UpdateMap::const_iterator lookup_it = |
| 254 pending_updates_map_.find(client_tag_hash); |
| 260 if (lookup_it == pending_updates_map_.end()) { | 255 if (lookup_it == pending_updates_map_.end()) { |
| 261 pending_updates_map_.insert( | 256 pending_updates_map_.insert( |
| 262 std::make_pair(client_tag_hash, new UpdateResponseData(update))); | 257 client_tag_hash, make_scoped_ptr(new UpdateResponseData(update))); |
| 263 } else if (lookup_it->second->response_version <= update.response_version) { | 258 } else if (lookup_it->second->response_version <= update.response_version) { |
| 264 delete lookup_it->second; | |
| 265 pending_updates_map_.erase(lookup_it); | 259 pending_updates_map_.erase(lookup_it); |
| 266 pending_updates_map_.insert( | 260 pending_updates_map_.insert( |
| 267 std::make_pair(client_tag_hash, new UpdateResponseData(update))); | 261 client_tag_hash, make_scoped_ptr(new UpdateResponseData(update))); |
| 268 } else { | 262 } else { |
| 269 // Received update is stale, do not overwrite existing. | 263 // Received update is stale, do not overwrite existing. |
| 270 } | 264 } |
| 271 } | 265 } |
| 272 | 266 |
| 273 if (got_new_encryption_requirements) { | 267 if (got_new_encryption_requirements) { |
| 274 for (EntityMap::iterator it = entities_.begin(); it != entities_.end(); | 268 for (EntityMap::const_iterator it = entities_.begin(); |
| 275 ++it) { | 269 it != entities_.end(); ++it) { |
| 276 it->second->UpdateDesiredEncryptionKey( | 270 it->second->UpdateDesiredEncryptionKey( |
| 277 data_type_state_.encryption_key_name); | 271 data_type_state_.encryption_key_name); |
| 278 } | 272 } |
| 279 } | 273 } |
| 280 | 274 |
| 281 // We may have new reasons to commit by the time this function is done. | 275 // We may have new reasons to commit by the time this function is done. |
| 282 FlushPendingCommitRequests(); | 276 FlushPendingCommitRequests(); |
| 283 | 277 |
| 284 // TODO: Inform the model of the new or updated data. | 278 // TODO: Inform the model of the new or updated data. |
| 285 // TODO: Persist the new data on disk. | 279 // TODO: Persist the new data on disk. |
| 286 } | 280 } |
| 287 | 281 |
| 288 UpdateResponseDataList ModelTypeSyncProxyImpl::GetPendingUpdates() { | 282 UpdateResponseDataList ModelTypeSyncProxyImpl::GetPendingUpdates() { |
| 289 UpdateResponseDataList pending_updates_list; | 283 UpdateResponseDataList pending_updates_list; |
| 290 for (UpdateMap::const_iterator it = pending_updates_map_.begin(); | 284 for (UpdateMap::const_iterator it = pending_updates_map_.begin(); |
| 291 it != pending_updates_map_.end(); | 285 it != pending_updates_map_.end(); |
| 292 ++it) { | 286 ++it) { |
| 293 pending_updates_list.push_back(*it->second); | 287 pending_updates_list.push_back(*it->second); |
| 294 } | 288 } |
| 295 return pending_updates_list; | 289 return pending_updates_list; |
| 296 } | 290 } |
| 297 | 291 |
| 298 void ModelTypeSyncProxyImpl::ClearTransientSyncState() { | 292 void ModelTypeSyncProxyImpl::ClearTransientSyncState() { |
| 299 for (EntityMap::iterator it = entities_.begin(); it != entities_.end(); | 293 for (EntityMap::const_iterator it = entities_.begin(); it != entities_.end(); |
| 300 ++it) { | 294 ++it) { |
| 301 it->second->ClearTransientSyncState(); | 295 it->second->ClearTransientSyncState(); |
| 302 } | 296 } |
| 303 } | 297 } |
| 304 | 298 |
| 305 void ModelTypeSyncProxyImpl::ClearSyncState() { | 299 void ModelTypeSyncProxyImpl::ClearSyncState() { |
| 306 for (EntityMap::iterator it = entities_.begin(); it != entities_.end(); | 300 for (EntityMap::const_iterator it = entities_.begin(); it != entities_.end(); |
| 307 ++it) { | 301 ++it) { |
| 308 it->second->ClearSyncState(); | 302 it->second->ClearSyncState(); |
| 309 } | 303 } |
| 310 STLDeleteValues(&pending_updates_map_); | 304 pending_updates_map_.clear(); |
| 311 data_type_state_ = DataTypeState(); | 305 data_type_state_ = DataTypeState(); |
| 312 } | 306 } |
| 313 | 307 |
| 314 } // namespace syncer | 308 } // namespace syncer |
| OLD | NEW |