Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(53)

Side by Side Diff: google_apis/gcm/engine/gcm_store_impl.cc

Issue 147193003: [GCM] Fix memory leaks (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix windows Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 "google_apis/gcm/engine/gcm_store_impl.h" 5 #include "google_apis/gcm/engine/gcm_store_impl.h"
6 6
7 #include "base/basictypes.h" 7 #include "base/basictypes.h"
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/callback.h" 9 #include "base/callback.h"
10 #include "base/file_util.h" 10 #include "base/file_util.h"
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 void RemoveUserSerialNumber(const std::string& username, 117 void RemoveUserSerialNumber(const std::string& username,
118 const UpdateCallback& callback); 118 const UpdateCallback& callback);
119 void SetNextSerialNumber(int64 serial_number, const UpdateCallback& callback); 119 void SetNextSerialNumber(int64 serial_number, const UpdateCallback& callback);
120 120
121 private: 121 private:
122 friend class base::RefCountedThreadSafe<Backend>; 122 friend class base::RefCountedThreadSafe<Backend>;
123 ~Backend(); 123 ~Backend();
124 124
125 bool LoadDeviceCredentials(uint64* android_id, uint64* security_token); 125 bool LoadDeviceCredentials(uint64* android_id, uint64* security_token);
126 bool LoadIncomingMessages(std::vector<std::string>* incoming_messages); 126 bool LoadIncomingMessages(std::vector<std::string>* incoming_messages);
127 bool LoadOutgoingMessages( 127 bool LoadOutgoingMessages(OutgoingMessageMap* outgoing_messages);
128 std::map<std::string, google::protobuf::MessageLite*>* outgoing_messages);
129 bool LoadNextSerialNumber(int64* next_serial_number); 128 bool LoadNextSerialNumber(int64* next_serial_number);
130 bool LoadUserSerialNumberMap( 129 bool LoadUserSerialNumberMap(
131 std::map<std::string, int64>* user_serial_number_map); 130 std::map<std::string, int64>* user_serial_number_map);
132 131
133 const base::FilePath path_; 132 const base::FilePath path_;
134 scoped_refptr<base::SequencedTaskRunner> foreground_task_runner_; 133 scoped_refptr<base::SequencedTaskRunner> foreground_task_runner_;
135 134
136 scoped_ptr<leveldb::DB> db_; 135 scoped_ptr<leveldb::DB> db_;
137 }; 136 };
138 137
139 GCMStoreImpl::Backend::Backend( 138 GCMStoreImpl::Backend::Backend(
140 const base::FilePath& path, 139 const base::FilePath& path,
141 scoped_refptr<base::SequencedTaskRunner> foreground_task_runner) 140 scoped_refptr<base::SequencedTaskRunner> foreground_task_runner)
142 : path_(path), foreground_task_runner_(foreground_task_runner) {} 141 : path_(path), foreground_task_runner_(foreground_task_runner) {}
143 142
144 GCMStoreImpl::Backend::~Backend() {} 143 GCMStoreImpl::Backend::~Backend() {}
145 144
146 void GCMStoreImpl::Backend::Load(const LoadCallback& callback) { 145 void GCMStoreImpl::Backend::Load(const LoadCallback& callback) {
147 LoadResult result; 146 scoped_ptr<LoadResult> result(new LoadResult());
148 if (db_.get()) { 147 if (db_.get()) {
149 LOG(ERROR) << "Attempting to reload open database."; 148 LOG(ERROR) << "Attempting to reload open database.";
150 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, result)); 149 foreground_task_runner_->PostTask(FROM_HERE,
150 base::Bind(callback,
151 base::Passed(&result)));
151 return; 152 return;
152 } 153 }
153 154
154 leveldb::Options options; 155 leveldb::Options options;
155 options.create_if_missing = true; 156 options.create_if_missing = true;
156 leveldb::DB* db; 157 leveldb::DB* db;
157 leveldb::Status status = 158 leveldb::Status status =
158 leveldb::DB::Open(options, path_.AsUTF8Unsafe(), &db); 159 leveldb::DB::Open(options, path_.AsUTF8Unsafe(), &db);
159 UMA_HISTOGRAM_BOOLEAN("GCM.LoadSucceeded", status.ok()); 160 UMA_HISTOGRAM_BOOLEAN("GCM.LoadSucceeded", status.ok());
160 if (!status.ok()) { 161 if (!status.ok()) {
161 LOG(ERROR) << "Failed to open database " << path_.value() << ": " 162 LOG(ERROR) << "Failed to open database " << path_.value() << ": "
162 << status.ToString(); 163 << status.ToString();
163 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, result)); 164 foreground_task_runner_->PostTask(FROM_HERE,
165 base::Bind(callback,
166 base::Passed(&result)));
164 return; 167 return;
165 } 168 }
166 db_.reset(db); 169 db_.reset(db);
167 170
168 if (!LoadDeviceCredentials(&result.device_android_id, 171 if (!LoadDeviceCredentials(&result->device_android_id,
169 &result.device_security_token) || 172 &result->device_security_token) ||
170 !LoadIncomingMessages(&result.incoming_messages) || 173 !LoadIncomingMessages(&result->incoming_messages) ||
171 !LoadOutgoingMessages(&result.outgoing_messages) || 174 !LoadOutgoingMessages(&result->outgoing_messages) ||
172 !LoadNextSerialNumber( 175 !LoadNextSerialNumber(
173 &result.serial_number_mappings.next_serial_number) || 176 &result->serial_number_mappings.next_serial_number) ||
174 !LoadUserSerialNumberMap( 177 !LoadUserSerialNumberMap(
175 &result.serial_number_mappings.user_serial_numbers)) { 178 &result->serial_number_mappings.user_serial_numbers)) {
176 result.device_android_id = 0; 179 result->device_android_id = 0;
177 result.device_security_token = 0; 180 result->device_security_token = 0;
178 result.incoming_messages.clear(); 181 result->incoming_messages.clear();
179 STLDeleteContainerPairSecondPointers(result.outgoing_messages.begin(), 182 result->outgoing_messages.clear();
180 result.outgoing_messages.end()); 183 foreground_task_runner_->PostTask(FROM_HERE,
181 result.outgoing_messages.clear(); 184 base::Bind(callback,
182 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, result)); 185 base::Passed(&result)));
183 return; 186 return;
184 } 187 }
185 188
186 // Only record histograms if GCM had already been set up for this device. 189 // Only record histograms if GCM had already been set up for this device.
187 if (result.device_android_id != 0 && result.device_security_token != 0) { 190 if (result->device_android_id != 0 && result->device_security_token != 0) {
188 int64 file_size = 0; 191 int64 file_size = 0;
189 if (base::GetFileSize(path_, &file_size)) { 192 if (base::GetFileSize(path_, &file_size)) {
190 UMA_HISTOGRAM_COUNTS("GCM.StoreSizeKB", 193 UMA_HISTOGRAM_COUNTS("GCM.StoreSizeKB",
191 static_cast<int>(file_size / 1024)); 194 static_cast<int>(file_size / 1024));
192 } 195 }
193 UMA_HISTOGRAM_COUNTS("GCM.RestoredOutgoingMessages", 196 UMA_HISTOGRAM_COUNTS("GCM.RestoredOutgoingMessages",
194 result.outgoing_messages.size()); 197 result->outgoing_messages.size());
195 UMA_HISTOGRAM_COUNTS("GCM.RestoredIncomingMessages", 198 UMA_HISTOGRAM_COUNTS("GCM.RestoredIncomingMessages",
196 result.incoming_messages.size()); 199 result->incoming_messages.size());
197 UMA_HISTOGRAM_COUNTS( 200 UMA_HISTOGRAM_COUNTS(
198 "GCM.NumUsers", 201 "GCM.NumUsers",
199 result.serial_number_mappings.user_serial_numbers.size()); 202 result->serial_number_mappings.user_serial_numbers.size());
200 } 203 }
201 204
202 DVLOG(1) << "Succeeded in loading " << result.incoming_messages.size() 205 DVLOG(1) << "Succeeded in loading " << result->incoming_messages.size()
203 << " unacknowledged incoming messages and " 206 << " unacknowledged incoming messages and "
204 << result.outgoing_messages.size() 207 << result->outgoing_messages.size()
205 << " unacknowledged outgoing messages."; 208 << " unacknowledged outgoing messages.";
206 result.success = true; 209 result->success = true;
207 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, result)); 210 foreground_task_runner_->PostTask(FROM_HERE,
211 base::Bind(callback,
212 base::Passed(&result)));
208 return; 213 return;
209 } 214 }
210 215
211 void GCMStoreImpl::Backend::Destroy(const UpdateCallback& callback) { 216 void GCMStoreImpl::Backend::Destroy(const UpdateCallback& callback) {
212 DVLOG(1) << "Destroying GCM store."; 217 DVLOG(1) << "Destroying GCM store.";
213 db_.reset(); 218 db_.reset();
214 const leveldb::Status s = 219 const leveldb::Status s =
215 leveldb::DestroyDB(path_.AsUTF8Unsafe(), leveldb::Options()); 220 leveldb::DestroyDB(path_.AsUTF8Unsafe(), leveldb::Options());
216 if (s.ok()) { 221 if (s.ok()) {
217 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); 222 foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true));
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
515 return false; 520 return false;
516 } 521 }
517 DVLOG(1) << "Found incoming message with id " << s.ToString(); 522 DVLOG(1) << "Found incoming message with id " << s.ToString();
518 incoming_messages->push_back(s.ToString()); 523 incoming_messages->push_back(s.ToString());
519 } 524 }
520 525
521 return true; 526 return true;
522 } 527 }
523 528
524 bool GCMStoreImpl::Backend::LoadOutgoingMessages( 529 bool GCMStoreImpl::Backend::LoadOutgoingMessages(
525 std::map<std::string, google::protobuf::MessageLite*>* outgoing_messages) { 530 OutgoingMessageMap* outgoing_messages) {
526 leveldb::ReadOptions read_options; 531 leveldb::ReadOptions read_options;
527 read_options.verify_checksums = true; 532 read_options.verify_checksums = true;
528 533
529 scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options)); 534 scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options));
530 for (iter->Seek(MakeSlice(kOutgoingMsgKeyStart)); 535 for (iter->Seek(MakeSlice(kOutgoingMsgKeyStart));
531 iter->Valid() && iter->key().ToString() < kOutgoingMsgKeyEnd; 536 iter->Valid() && iter->key().ToString() < kOutgoingMsgKeyEnd;
532 iter->Next()) { 537 iter->Next()) {
533 leveldb::Slice s = iter->value(); 538 leveldb::Slice s = iter->value();
534 if (s.size() <= 1) { 539 if (s.size() <= 1) {
535 LOG(ERROR) << "Error reading incoming message with key " << s.ToString(); 540 LOG(ERROR) << "Error reading incoming message with key " << s.ToString();
536 return false; 541 return false;
537 } 542 }
538 uint8 tag = iter->value().data()[0]; 543 uint8 tag = iter->value().data()[0];
539 std::string id = ParseOutgoingKey(iter->key().ToString()); 544 std::string id = ParseOutgoingKey(iter->key().ToString());
540 scoped_ptr<google::protobuf::MessageLite> message( 545 scoped_ptr<google::protobuf::MessageLite> message(
541 BuildProtobufFromTag(tag)); 546 BuildProtobufFromTag(tag));
542 if (!message.get() || 547 if (!message.get() ||
543 !message->ParseFromString(iter->value().ToString().substr(1))) { 548 !message->ParseFromString(iter->value().ToString().substr(1))) {
544 LOG(ERROR) << "Failed to parse outgoing message with id " << id 549 LOG(ERROR) << "Failed to parse outgoing message with id " << id
545 << " and tag " << tag; 550 << " and tag " << tag;
546 return false; 551 return false;
547 } 552 }
548 DVLOG(1) << "Found outgoing message with id " << id << " of type " 553 DVLOG(1) << "Found outgoing message with id " << id << " of type "
549 << base::IntToString(tag); 554 << base::IntToString(tag);
550 (*outgoing_messages)[id] = message.release(); 555 (*outgoing_messages)[id] = make_linked_ptr(message.release());
551 } 556 }
552 557
553 return true; 558 return true;
554 } 559 }
555 560
556 bool GCMStoreImpl::Backend::LoadNextSerialNumber(int64* next_serial_number) { 561 bool GCMStoreImpl::Backend::LoadNextSerialNumber(int64* next_serial_number) {
557 leveldb::ReadOptions read_options; 562 leveldb::ReadOptions read_options;
558 read_options.verify_checksums = true; 563 read_options.verify_checksums = true;
559 564
560 std::string result; 565 std::string result;
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
756 const UpdateCallback& callback) { 761 const UpdateCallback& callback) {
757 blocking_task_runner_->PostTask( 762 blocking_task_runner_->PostTask(
758 FROM_HERE, 763 FROM_HERE,
759 base::Bind(&GCMStoreImpl::Backend::RemoveUserSerialNumber, 764 base::Bind(&GCMStoreImpl::Backend::RemoveUserSerialNumber,
760 backend_, 765 backend_,
761 username, 766 username,
762 callback)); 767 callback));
763 } 768 }
764 769
765 void GCMStoreImpl::LoadContinuation(const LoadCallback& callback, 770 void GCMStoreImpl::LoadContinuation(const LoadCallback& callback,
766 const LoadResult& result) { 771 scoped_ptr<LoadResult> result) {
767 if (!result.success) { 772 if (!result->success) {
768 callback.Run(result); 773 callback.Run(result.Pass());
769 return; 774 return;
770 } 775 }
771 int num_throttled_apps = 0; 776 int num_throttled_apps = 0;
772 for (std::map<std::string, google::protobuf::MessageLite*>::const_iterator 777 for (OutgoingMessageMap::const_iterator
773 iter = result.outgoing_messages.begin(); 778 iter = result->outgoing_messages.begin();
774 iter != result.outgoing_messages.end(); ++iter) { 779 iter != result->outgoing_messages.end(); ++iter) {
775 const mcs_proto::DataMessageStanza* data_message = 780 const mcs_proto::DataMessageStanza* data_message =
776 reinterpret_cast<mcs_proto::DataMessageStanza*>(iter->second); 781 reinterpret_cast<mcs_proto::DataMessageStanza*>(iter->second.get());
777 DCHECK(!data_message->from().empty()); 782 DCHECK(!data_message->from().empty());
778 if (app_message_counts_.count(data_message->from()) == 0) 783 if (app_message_counts_.count(data_message->from()) == 0)
779 app_message_counts_[data_message->from()] = 1; 784 app_message_counts_[data_message->from()] = 1;
780 else 785 else
781 app_message_counts_[data_message->from()]++; 786 app_message_counts_[data_message->from()]++;
782 if (app_message_counts_[data_message->from()] == kMessagesPerAppLimit) 787 if (app_message_counts_[data_message->from()] == kMessagesPerAppLimit)
783 num_throttled_apps++; 788 num_throttled_apps++;
784 } 789 }
785 UMA_HISTOGRAM_COUNTS("GCM.NumThrottledApps", num_throttled_apps); 790 UMA_HISTOGRAM_COUNTS("GCM.NumThrottledApps", num_throttled_apps);
786 callback.Run(result); 791 callback.Run(result.Pass());
787 } 792 }
788 793
789 void GCMStoreImpl::AddOutgoingMessageContinuation( 794 void GCMStoreImpl::AddOutgoingMessageContinuation(
790 const UpdateCallback& callback, 795 const UpdateCallback& callback,
791 const std::string& app_id, 796 const std::string& app_id,
792 bool success) { 797 bool success) {
793 if (!success) { 798 if (!success) {
794 DCHECK(app_message_counts_[app_id] > 0); 799 DCHECK(app_message_counts_[app_id] > 0);
795 app_message_counts_[app_id]--; 800 app_message_counts_[app_id]--;
796 } 801 }
(...skipping 12 matching lines...) Expand all
809 removed_message_counts.begin(); 814 removed_message_counts.begin();
810 iter != removed_message_counts.end(); ++iter) { 815 iter != removed_message_counts.end(); ++iter) {
811 DCHECK_NE(app_message_counts_.count(iter->first), 0U); 816 DCHECK_NE(app_message_counts_.count(iter->first), 0U);
812 app_message_counts_[iter->first] -= iter->second; 817 app_message_counts_[iter->first] -= iter->second;
813 DCHECK_GE(app_message_counts_[iter->first], 0); 818 DCHECK_GE(app_message_counts_[iter->first], 0);
814 } 819 }
815 callback.Run(true); 820 callback.Run(true);
816 } 821 }
817 822
818 } // namespace gcm 823 } // namespace gcm
OLDNEW
« no previous file with comments | « google_apis/gcm/engine/gcm_store_impl.h ('k') | google_apis/gcm/engine/gcm_store_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698