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

Side by Side Diff: chrome/browser/sync/syncable/syncable.cc

Issue 2830027: Remove extended attributes. The lame broken codepath in the DBS was causing (Closed)
Patch Set: Synced with TOT, resolved conflicts. Created 10 years, 5 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
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 "chrome/browser/sync/syncable/syncable.h" 5 #include "chrome/browser/sync/syncable/syncable.h"
6 6
7 #include "build/build_config.h" 7 #include "build/build_config.h"
8 8
9 #include <sys/stat.h> 9 #include <sys/stat.h>
10 #if defined(OS_POSIX) 10 #if defined(OS_POSIX)
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 Directory::Kernel::Kernel(const FilePath& db_path, 160 Directory::Kernel::Kernel(const FilePath& db_path,
161 const string& name, 161 const string& name,
162 const KernelLoadInfo& info) 162 const KernelLoadInfo& info)
163 : db_path(db_path), 163 : db_path(db_path),
164 refcount(1), 164 refcount(1),
165 name(name), 165 name(name),
166 metahandles_index(new Directory::MetahandlesIndex), 166 metahandles_index(new Directory::MetahandlesIndex),
167 ids_index(new Directory::IdsIndex), 167 ids_index(new Directory::IdsIndex),
168 parent_id_child_index(new Directory::ParentIdChildIndex), 168 parent_id_child_index(new Directory::ParentIdChildIndex),
169 client_tag_index(new Directory::ClientTagIndex), 169 client_tag_index(new Directory::ClientTagIndex),
170 extended_attributes(new ExtendedAttributes),
171 unapplied_update_metahandles(new MetahandleSet), 170 unapplied_update_metahandles(new MetahandleSet),
172 unsynced_metahandles(new MetahandleSet), 171 unsynced_metahandles(new MetahandleSet),
173 dirty_metahandles(new MetahandleSet), 172 dirty_metahandles(new MetahandleSet),
174 channel(new Directory::Channel(syncable::DIRECTORY_DESTROYED)), 173 channel(new Directory::Channel(syncable::DIRECTORY_DESTROYED)),
175 info_status(Directory::KERNEL_SHARE_INFO_VALID), 174 info_status(Directory::KERNEL_SHARE_INFO_VALID),
176 persisted_info(info.kernel_info), 175 persisted_info(info.kernel_info),
177 cache_guid(info.cache_guid), 176 cache_guid(info.cache_guid),
178 next_metahandle(info.max_metahandle + 1) { 177 next_metahandle(info.max_metahandle + 1) {
179 } 178 }
180 179
(...skipping 10 matching lines...) Expand all
191 delete this; 190 delete this;
192 } 191 }
193 192
194 Directory::Kernel::~Kernel() { 193 Directory::Kernel::~Kernel() {
195 CHECK(0 == refcount); 194 CHECK(0 == refcount);
196 delete channel; 195 delete channel;
197 changes_channel.Notify(kShutdownChangesEvent); 196 changes_channel.Notify(kShutdownChangesEvent);
198 delete unsynced_metahandles; 197 delete unsynced_metahandles;
199 delete unapplied_update_metahandles; 198 delete unapplied_update_metahandles;
200 delete dirty_metahandles; 199 delete dirty_metahandles;
201 delete extended_attributes;
202 delete parent_id_child_index; 200 delete parent_id_child_index;
203 delete client_tag_index; 201 delete client_tag_index;
204 delete ids_index; 202 delete ids_index;
205 for_each(metahandles_index->begin(), metahandles_index->end(), DeleteEntry); 203 for_each(metahandles_index->begin(), metahandles_index->end(), DeleteEntry);
206 delete metahandles_index; 204 delete metahandles_index;
207 } 205 }
208 206
209 Directory::Directory() : kernel_(NULL), store_(NULL) { 207 Directory::Directory() : kernel_(NULL), store_(NULL) {
210 } 208 }
211 209
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 const string& name) { 245 const string& name) {
248 DCHECK_EQ(static_cast<DirectoryBackingStore*>(NULL), store_); 246 DCHECK_EQ(static_cast<DirectoryBackingStore*>(NULL), store_);
249 FilePath db_path(file_path); 247 FilePath db_path(file_path);
250 file_util::AbsolutePath(&db_path); 248 file_util::AbsolutePath(&db_path);
251 store_ = CreateBackingStore(name, db_path); 249 store_ = CreateBackingStore(name, db_path);
252 250
253 KernelLoadInfo info; 251 KernelLoadInfo info;
254 // Temporary indices before kernel_ initialized in case Load fails. We 0(1) 252 // Temporary indices before kernel_ initialized in case Load fails. We 0(1)
255 // swap these later. 253 // swap these later.
256 MetahandlesIndex metas_bucket; 254 MetahandlesIndex metas_bucket;
257 ExtendedAttributes xattrs_bucket; 255 DirOpenResult result = store_->Load(&metas_bucket, &info);
258 DirOpenResult result = store_->Load(&metas_bucket, &xattrs_bucket, &info);
259 if (OPENED != result) 256 if (OPENED != result)
260 return result; 257 return result;
261 258
262 kernel_ = new Kernel(db_path, name, info); 259 kernel_ = new Kernel(db_path, name, info);
263 kernel_->metahandles_index->swap(metas_bucket); 260 kernel_->metahandles_index->swap(metas_bucket);
264 kernel_->extended_attributes->swap(xattrs_bucket);
265 InitializeIndices(); 261 InitializeIndices();
266 return OPENED; 262 return OPENED;
267 } 263 }
268 264
269 void Directory::Close() { 265 void Directory::Close() {
270 if (store_) 266 if (store_)
271 delete store_; 267 delete store_;
272 store_ = NULL; 268 store_ = NULL;
273 if (kernel_) { 269 if (kernel_) {
274 bool del = !base::subtle::NoBarrier_AtomicIncrement(&kernel_->refcount, -1); 270 bool del = !base::subtle::NoBarrier_AtomicIncrement(&kernel_->refcount, -1);
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
519 if (!entry->is_dirty()) 515 if (!entry->is_dirty())
520 continue; 516 continue;
521 snapshot->dirty_metas.insert(snapshot->dirty_metas.end(), *entry); 517 snapshot->dirty_metas.insert(snapshot->dirty_metas.end(), *entry);
522 DCHECK_EQ(1U, kernel_->dirty_metahandles->count(*i)); 518 DCHECK_EQ(1U, kernel_->dirty_metahandles->count(*i));
523 // We don't bother removing from the index here as we blow the entire thing 519 // We don't bother removing from the index here as we blow the entire thing
524 // in a moment, and it unnecessarily complicates iteration. 520 // in a moment, and it unnecessarily complicates iteration.
525 entry->clear_dirty(NULL); 521 entry->clear_dirty(NULL);
526 } 522 }
527 ClearDirtyMetahandles(); 523 ClearDirtyMetahandles();
528 524
529 // Do the same for extended attributes.
530 for (ExtendedAttributes::iterator i = kernel_->extended_attributes->begin();
531 i != kernel_->extended_attributes->end(); ++i) {
532 if (!i->second.dirty)
533 continue;
534 snapshot->dirty_xattrs[i->first] = i->second;
535 i->second.dirty = false;
536 }
537
538 // Fill kernel_info_status and kernel_info. 525 // Fill kernel_info_status and kernel_info.
539 snapshot->kernel_info = kernel_->persisted_info; 526 snapshot->kernel_info = kernel_->persisted_info;
540 // To avoid duplicates when the process crashes, we record the next_id to be 527 // To avoid duplicates when the process crashes, we record the next_id to be
541 // greater magnitude than could possibly be reached before the next save 528 // greater magnitude than could possibly be reached before the next save
542 // changes. In other words, it's effectively impossible for the user to 529 // changes. In other words, it's effectively impossible for the user to
543 // generate 65536 new bookmarks in 3 seconds. 530 // generate 65536 new bookmarks in 3 seconds.
544 snapshot->kernel_info.next_id -= 65536; 531 snapshot->kernel_info.next_id -= 65536;
545 snapshot->kernel_info_status = kernel_->info_status; 532 snapshot->kernel_info_status = kernel_->info_status;
546 // This one we reset on failure. 533 // This one we reset on failure.
547 kernel_->info_status = KERNEL_SHARE_INFO_VALID; 534 kernel_->info_status = KERNEL_SHARE_INFO_VALID;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
588 DCHECK_EQ(1u, num_erased); 575 DCHECK_EQ(1u, num_erased);
589 num_erased = kernel_->metahandles_index->erase(entry); 576 num_erased = kernel_->metahandles_index->erase(entry);
590 DCHECK_EQ(1u, num_erased); 577 DCHECK_EQ(1u, num_erased);
591 578
592 // Might not be in it 579 // Might not be in it
593 num_erased = kernel_->client_tag_index->erase(entry); 580 num_erased = kernel_->client_tag_index->erase(entry);
594 DCHECK_EQ(entry->ref(UNIQUE_CLIENT_TAG).empty(), !num_erased); 581 DCHECK_EQ(entry->ref(UNIQUE_CLIENT_TAG).empty(), !num_erased);
595 delete entry; 582 delete entry;
596 } 583 }
597 } 584 }
598
599 ExtendedAttributes::const_iterator i = snapshot.dirty_xattrs.begin();
600 while (i != snapshot.dirty_xattrs.end()) {
601 ExtendedAttributeKey key(i->first.metahandle, i->first.key);
602 ExtendedAttributes::iterator found =
603 kernel_->extended_attributes->find(key);
604 if (found == kernel_->extended_attributes->end() ||
605 found->second.dirty || !i->second.is_deleted) {
606 ++i;
607 } else {
608 kernel_->extended_attributes->erase(found);
609 }
610 }
611 } 585 }
612 586
613 void Directory::PurgeEntriesWithTypeIn(const std::set<ModelType>& types) { 587 void Directory::PurgeEntriesWithTypeIn(const std::set<ModelType>& types) {
614 if (types.count(UNSPECIFIED) != 0U || types.count(TOP_LEVEL_FOLDER) != 0U) { 588 if (types.count(UNSPECIFIED) != 0U || types.count(TOP_LEVEL_FOLDER) != 0U) {
615 NOTREACHED() << "Don't support purging unspecified or top level entries."; 589 NOTREACHED() << "Don't support purging unspecified or top level entries.";
616 return; 590 return;
617 } 591 }
618 592
619 if (types.empty()) 593 if (types.empty())
620 return; 594 return;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
659 // that SaveChanges will at least try again later. 633 // that SaveChanges will at least try again later.
660 for (OriginalEntries::const_iterator i = snapshot.dirty_metas.begin(); 634 for (OriginalEntries::const_iterator i = snapshot.dirty_metas.begin();
661 i != snapshot.dirty_metas.end(); ++i) { 635 i != snapshot.dirty_metas.end(); ++i) {
662 kernel_->needle.put(META_HANDLE, i->ref(META_HANDLE)); 636 kernel_->needle.put(META_HANDLE, i->ref(META_HANDLE));
663 MetahandlesIndex::iterator found = 637 MetahandlesIndex::iterator found =
664 kernel_->metahandles_index->find(&kernel_->needle); 638 kernel_->metahandles_index->find(&kernel_->needle);
665 if (found != kernel_->metahandles_index->end()) { 639 if (found != kernel_->metahandles_index->end()) {
666 (*found)->mark_dirty(kernel_->dirty_metahandles); 640 (*found)->mark_dirty(kernel_->dirty_metahandles);
667 } 641 }
668 } 642 }
669
670 for (ExtendedAttributes::const_iterator i = snapshot.dirty_xattrs.begin();
671 i != snapshot.dirty_xattrs.end(); ++i) {
672 ExtendedAttributeKey key(i->first.metahandle, i->first.key);
673 ExtendedAttributes::iterator found =
674 kernel_->extended_attributes->find(key);
675 if (found != kernel_->extended_attributes->end())
676 found->second.dirty = true;
677 }
678 } 643 }
679 644
680 int64 Directory::last_download_timestamp(ModelType model_type) const { 645 int64 Directory::last_download_timestamp(ModelType model_type) const {
681 ScopedKernelLock lock(this); 646 ScopedKernelLock lock(this);
682 return kernel_->persisted_info.last_download_timestamp[model_type]; 647 return kernel_->persisted_info.last_download_timestamp[model_type];
683 } 648 }
684 649
685 void Directory::set_last_download_timestamp(ModelType model_type, 650 void Directory::set_last_download_timestamp(ModelType model_type,
686 int64 timestamp) { 651 int64 timestamp) {
687 ScopedKernelLock lock(this); 652 ScopedKernelLock lock(this);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
745 } 710 }
746 711
747 void Directory::GetUnsyncedMetaHandles(BaseTransaction* trans, 712 void Directory::GetUnsyncedMetaHandles(BaseTransaction* trans,
748 UnsyncedMetaHandles* result) { 713 UnsyncedMetaHandles* result) {
749 result->clear(); 714 result->clear();
750 ScopedKernelLock lock(this); 715 ScopedKernelLock lock(this);
751 copy(kernel_->unsynced_metahandles->begin(), 716 copy(kernel_->unsynced_metahandles->begin(),
752 kernel_->unsynced_metahandles->end(), back_inserter(*result)); 717 kernel_->unsynced_metahandles->end(), back_inserter(*result));
753 } 718 }
754 719
755 void Directory::GetAllExtendedAttributes(BaseTransaction* trans,
756 int64 metahandle,
757 std::set<ExtendedAttribute>* result) {
758 AttributeKeySet keys;
759 GetExtendedAttributesList(trans, metahandle, &keys);
760 AttributeKeySet::iterator iter;
761 for (iter = keys.begin(); iter != keys.end(); ++iter) {
762 ExtendedAttributeKey key(metahandle, *iter);
763 ExtendedAttribute extended_attribute(trans, GET_BY_HANDLE, key);
764 CHECK(extended_attribute.good());
765 result->insert(extended_attribute);
766 }
767 }
768
769 void Directory::GetExtendedAttributesList(BaseTransaction* trans,
770 int64 metahandle, AttributeKeySet* result) {
771 ExtendedAttributes::iterator iter;
772 for (iter = kernel_->extended_attributes->begin();
773 iter != kernel_->extended_attributes->end(); ++iter) {
774 if (iter->first.metahandle == metahandle) {
775 if (!iter->second.is_deleted)
776 result->insert(iter->first.key);
777 }
778 }
779 }
780
781 void Directory::DeleteAllExtendedAttributes(WriteTransaction* trans,
782 int64 metahandle) {
783 AttributeKeySet keys;
784 GetExtendedAttributesList(trans, metahandle, &keys);
785 AttributeKeySet::iterator iter;
786 for (iter = keys.begin(); iter != keys.end(); ++iter) {
787 ExtendedAttributeKey key(metahandle, *iter);
788 MutableExtendedAttribute attribute(trans, GET_BY_HANDLE, key);
789 // This flags the attribute for deletion during SaveChanges. At that time
790 // any deleted attributes are purged from disk and memory.
791 attribute.delete_attribute();
792 }
793 }
794
795 int64 Directory::unsynced_entity_count() const { 720 int64 Directory::unsynced_entity_count() const {
796 ScopedKernelLock lock(this); 721 ScopedKernelLock lock(this);
797 return kernel_->unsynced_metahandles->size(); 722 return kernel_->unsynced_metahandles->size();
798 } 723 }
799 724
800 void Directory::GetUnappliedUpdateMetaHandles(BaseTransaction* trans, 725 void Directory::GetUnappliedUpdateMetaHandles(BaseTransaction* trans,
801 UnappliedUpdateMetaHandles* result) { 726 UnappliedUpdateMetaHandles* result) {
802 result->clear(); 727 result->clear();
803 ScopedKernelLock lock(this); 728 ScopedKernelLock lock(this);
804 copy(kernel_->unapplied_update_metahandles->begin(), 729 copy(kernel_->unapplied_update_metahandles->begin(),
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
1089 1014
1090 Directory* Entry::dir() const { 1015 Directory* Entry::dir() const {
1091 return basetrans_->directory(); 1016 return basetrans_->directory();
1092 } 1017 }
1093 1018
1094 const string& Entry::Get(StringField field) const { 1019 const string& Entry::Get(StringField field) const {
1095 DCHECK(kernel_); 1020 DCHECK(kernel_);
1096 return kernel_->ref(field); 1021 return kernel_->ref(field);
1097 } 1022 }
1098 1023
1099 void Entry::GetAllExtendedAttributes(BaseTransaction* trans,
1100 std::set<ExtendedAttribute> *result) {
1101 dir()->GetAllExtendedAttributes(trans, kernel_->ref(META_HANDLE), result);
1102 }
1103
1104 void Entry::GetExtendedAttributesList(BaseTransaction* trans,
1105 AttributeKeySet* result) {
1106 dir()->GetExtendedAttributesList(trans, kernel_->ref(META_HANDLE), result);
1107 }
1108
1109 void Entry::DeleteAllExtendedAttributes(WriteTransaction *trans) {
1110 dir()->DeleteAllExtendedAttributes(trans, kernel_->ref(META_HANDLE));
1111 }
1112
1113 syncable::ModelType Entry::GetServerModelType() const { 1024 syncable::ModelType Entry::GetServerModelType() const {
1114 ModelType specifics_type = GetModelTypeFromSpecifics(Get(SERVER_SPECIFICS)); 1025 ModelType specifics_type = GetModelTypeFromSpecifics(Get(SERVER_SPECIFICS));
1115 if (specifics_type != UNSPECIFIED) 1026 if (specifics_type != UNSPECIFIED)
1116 return specifics_type; 1027 return specifics_type;
1117 if (IsRoot()) 1028 if (IsRoot())
1118 return TOP_LEVEL_FOLDER; 1029 return TOP_LEVEL_FOLDER;
1119 // Loose check for server-created top-level folders that aren't 1030 // Loose check for server-created top-level folders that aren't
1120 // bound to a particular model type. 1031 // bound to a particular model type.
1121 if (!Get(UNIQUE_SERVER_TAG).empty() && Get(SERVER_IS_DIR)) 1032 if (!Get(UNIQUE_SERVER_TAG).empty() && Get(SERVER_IS_DIR))
1122 return TOP_LEVEL_FOLDER; 1033 return TOP_LEVEL_FOLDER;
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after
1485 Id Directory::GetFirstChildId(BaseTransaction* trans, 1396 Id Directory::GetFirstChildId(BaseTransaction* trans,
1486 const Id& parent_id) { 1397 const Id& parent_id) {
1487 return GetChildWithNullIdField(PREV_ID, trans, parent_id); 1398 return GetChildWithNullIdField(PREV_ID, trans, parent_id);
1488 } 1399 }
1489 1400
1490 Id Directory::GetLastChildId(BaseTransaction* trans, 1401 Id Directory::GetLastChildId(BaseTransaction* trans,
1491 const Id& parent_id) { 1402 const Id& parent_id) {
1492 return GetChildWithNullIdField(NEXT_ID, trans, parent_id); 1403 return GetChildWithNullIdField(NEXT_ID, trans, parent_id);
1493 } 1404 }
1494 1405
1495 ExtendedAttribute::ExtendedAttribute(BaseTransaction* trans, GetByHandle,
1496 const ExtendedAttributeKey& key) {
1497 Directory::Kernel* const kernel = trans->directory()->kernel_;
1498 ScopedKernelLock lock(trans->directory());
1499 Init(trans, kernel, &lock, key);
1500 }
1501
1502 bool ExtendedAttribute::Init(BaseTransaction* trans,
1503 Directory::Kernel* const kernel,
1504 ScopedKernelLock* lock,
1505 const ExtendedAttributeKey& key) {
1506 i_ = kernel->extended_attributes->find(key);
1507 good_ = kernel->extended_attributes->end() != i_;
1508 return good_;
1509 }
1510
1511 MutableExtendedAttribute::MutableExtendedAttribute(
1512 WriteTransaction* trans, GetByHandle,
1513 const ExtendedAttributeKey& key) :
1514 ExtendedAttribute(trans, GET_BY_HANDLE, key) {
1515 }
1516
1517 MutableExtendedAttribute::MutableExtendedAttribute(
1518 WriteTransaction* trans, Create, const ExtendedAttributeKey& key) {
1519 Directory::Kernel* const kernel = trans->directory()->kernel_;
1520 ScopedKernelLock lock(trans->directory());
1521 if (!Init(trans, kernel, &lock, key)) {
1522 ExtendedAttributeValue val;
1523 val.is_deleted = false;
1524 val.dirty = true;
1525 i_ = kernel->extended_attributes->insert(std::make_pair(key, val)).first;
1526 good_ = true;
1527 }
1528 }
1529
1530 bool IsLegalNewParent(BaseTransaction* trans, const Id& entry_id, 1406 bool IsLegalNewParent(BaseTransaction* trans, const Id& entry_id,
1531 const Id& new_parent_id) { 1407 const Id& new_parent_id) {
1532 if (entry_id.IsRoot()) 1408 if (entry_id.IsRoot())
1533 return false; 1409 return false;
1534 // we have to ensure that the entry is not an ancestor of the new parent. 1410 // we have to ensure that the entry is not an ancestor of the new parent.
1535 Id ancestor_id = new_parent_id; 1411 Id ancestor_id = new_parent_id;
1536 while (!ancestor_id.IsRoot()) { 1412 while (!ancestor_id.IsRoot()) {
1537 if (entry_id == ancestor_id) 1413 if (entry_id == ancestor_id)
1538 return false; 1414 return false;
1539 Entry new_parent(trans, GET_BY_ID, ancestor_id); 1415 Entry new_parent(trans, GET_BY_ID, ancestor_id);
1540 CHECK(new_parent.good()); 1416 CHECK(new_parent.good());
1541 ancestor_id = new_parent.Get(PARENT_ID); 1417 ancestor_id = new_parent.Get(PARENT_ID);
1542 } 1418 }
1543 return true; 1419 return true;
1544 } 1420 }
1545 1421
1546 const Blob* GetExtendedAttributeValue(const Entry& e,
1547 const string& attribute_name) {
1548 ExtendedAttributeKey key(e.Get(META_HANDLE), attribute_name);
1549 ExtendedAttribute extended_attribute(e.trans(), GET_BY_HANDLE, key);
1550 if (extended_attribute.good() && !extended_attribute.is_deleted())
1551 return &extended_attribute.value();
1552 return NULL;
1553 }
1554
1555 // This function sets only the flags needed to get this entry to sync. 1422 // This function sets only the flags needed to get this entry to sync.
1556 void MarkForSyncing(syncable::MutableEntry* e) { 1423 void MarkForSyncing(syncable::MutableEntry* e) {
1557 DCHECK_NE(static_cast<MutableEntry*>(NULL), e); 1424 DCHECK_NE(static_cast<MutableEntry*>(NULL), e);
1558 DCHECK(!e->IsRoot()) << "We shouldn't mark a permanent object for syncing."; 1425 DCHECK(!e->IsRoot()) << "We shouldn't mark a permanent object for syncing.";
1559 e->Put(IS_UNSYNCED, true); 1426 e->Put(IS_UNSYNCED, true);
1560 e->Put(SYNCING, false); 1427 e->Put(SYNCING, false);
1561 } 1428 }
1562 1429
1563 } // namespace syncable 1430 } // namespace syncable
1564 1431
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1640 return s << std::dec; 1507 return s << std::dec;
1641 } 1508 }
1642 1509
1643 FastDump& operator<<(FastDump& dump, const syncable::Blob& blob) { 1510 FastDump& operator<<(FastDump& dump, const syncable::Blob& blob) {
1644 if (blob.empty()) 1511 if (blob.empty())
1645 return dump; 1512 return dump;
1646 string buffer(HexEncode(&blob[0], blob.size())); 1513 string buffer(HexEncode(&blob[0], blob.size()));
1647 dump.out_->sputn(buffer.c_str(), buffer.size()); 1514 dump.out_->sputn(buffer.c_str(), buffer.size());
1648 return dump; 1515 return dump;
1649 } 1516 }
OLDNEW
« no previous file with comments | « chrome/browser/sync/syncable/syncable.h ('k') | chrome/browser/sync/syncable/syncable_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698