OLD | NEW |
1 // Copyright 2015 The Crashpad Authors. All rights reserved. | 1 // Copyright 2015 The Crashpad Authors. All rights reserved. |
2 // | 2 // |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
6 // | 6 // |
7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
8 // | 8 // |
9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
96 | 96 |
97 enum class ReportState { | 97 enum class ReportState { |
98 //! \brief Created and filled out by caller, owned by database. | 98 //! \brief Created and filled out by caller, owned by database. |
99 kPending, | 99 kPending, |
100 //! \brief In the process of uploading, owned by caller. | 100 //! \brief In the process of uploading, owned by caller. |
101 kUploading, | 101 kUploading, |
102 //! \brief Upload completed or skipped, owned by database. | 102 //! \brief Upload completed or skipped, owned by database. |
103 kCompleted, | 103 kCompleted, |
104 }; | 104 }; |
105 | 105 |
| 106 enum { |
| 107 //! \brief Corresponds to uploaded bit of the report state. |
| 108 kAttributeUploaded = 1 << 0, |
| 109 |
| 110 //! \brief Corresponds to upload_explicity_requested bit of the report state. |
| 111 kAttributeUploadExplicitlyRequested = 1 << 1, |
| 112 }; |
| 113 |
106 struct MetadataFileReportRecord { | 114 struct MetadataFileReportRecord { |
107 // Note that this default constructor does no initialization. It is used only | 115 // Note that this default constructor does no initialization. It is used only |
108 // to create an array of records that are immediately initialized by reading | 116 // to create an array of records that are immediately initialized by reading |
109 // from disk in Metadata::Read(). | 117 // from disk in Metadata::Read(). |
110 MetadataFileReportRecord() {} | 118 MetadataFileReportRecord() {} |
111 | 119 |
112 // Constructs from a ReportDisk, adding to |string_table| and storing indices | 120 // Constructs from a ReportDisk, adding to |string_table| and storing indices |
113 // as strings into that table. | 121 // as strings into that table. |
114 MetadataFileReportRecord(const ReportDisk& report, std::string* string_table); | 122 MetadataFileReportRecord(const ReportDisk& report, std::string* string_table); |
115 | 123 |
116 UUID uuid; // UUID is a 16 byte, standard layout structure. | 124 UUID uuid; // UUID is a 16 byte, standard layout structure. |
117 uint32_t file_path_index; // Index into string table. File name is relative | 125 uint32_t file_path_index; // Index into string table. File name is relative |
118 // to the reports directory when on disk. | 126 // to the reports directory when on disk. |
119 uint32_t id_index; // Index into string table. | 127 uint32_t id_index; // Index into string table. |
120 int64_t creation_time; // Holds a time_t. | 128 int64_t creation_time; // Holds a time_t. |
121 int64_t last_upload_attempt_time; // Holds a time_t. | 129 int64_t last_upload_attempt_time; // Holds a time_t. |
122 int32_t upload_attempts; | 130 int32_t upload_attempts; |
123 int32_t state; // A ReportState. | 131 int32_t state; // A ReportState. |
124 uint8_t uploaded; // Boolean, 0 or 1. | 132 uint8_t attributes; // Bitfield of kAttribute*. |
125 uint8_t padding[7]; | 133 uint8_t padding[7]; |
126 }; | 134 }; |
127 | 135 |
128 //! \brief A private extension of the Report class that includes additional data | 136 //! \brief A private extension of the Report class that includes additional data |
129 //! that's stored on disk in the metadata file. | 137 //! that's stored on disk in the metadata file. |
130 struct ReportDisk : public CrashReportDatabase::Report { | 138 struct ReportDisk : public CrashReportDatabase::Report { |
131 ReportDisk(const MetadataFileReportRecord& record, | 139 ReportDisk(const MetadataFileReportRecord& record, |
132 const base::FilePath& report_dir, | 140 const base::FilePath& report_dir, |
133 const std::string& string_table); | 141 const std::string& string_table); |
134 | 142 |
135 ReportDisk(const UUID& uuid, | 143 ReportDisk(const UUID& uuid, |
136 const base::FilePath& path, | 144 const base::FilePath& path, |
137 time_t creation_tim, | 145 time_t creation_tim, |
138 ReportState state); | 146 ReportState state); |
139 | 147 |
140 //! \brief The current state of the report. | 148 //! \brief The current state of the report. |
141 ReportState state; | 149 ReportState state; |
142 }; | 150 }; |
143 | 151 |
144 MetadataFileReportRecord::MetadataFileReportRecord(const ReportDisk& report, | 152 MetadataFileReportRecord::MetadataFileReportRecord(const ReportDisk& report, |
145 std::string* string_table) | 153 std::string* string_table) |
146 : uuid(report.uuid), | 154 : uuid(report.uuid), |
147 file_path_index( | 155 file_path_index( |
148 AddStringToTable(string_table, report.file_path.BaseName().value())), | 156 AddStringToTable(string_table, report.file_path.BaseName().value())), |
149 id_index(AddStringToTable(string_table, report.id)), | 157 id_index(AddStringToTable(string_table, report.id)), |
150 creation_time(report.creation_time), | 158 creation_time(report.creation_time), |
151 last_upload_attempt_time(report.last_upload_attempt_time), | 159 last_upload_attempt_time(report.last_upload_attempt_time), |
152 upload_attempts(report.upload_attempts), | 160 upload_attempts(report.upload_attempts), |
153 state(static_cast<uint32_t>(report.state)), | 161 state(static_cast<uint32_t>(report.state)), |
154 uploaded(report.uploaded) { | 162 attributes((report.uploaded ? kAttributeUploaded : 0) | |
| 163 (report.upload_explicitly_requested |
| 164 ? kAttributeUploadExplicitlyRequested |
| 165 : 0)) { |
155 memset(&padding, 0, sizeof(padding)); | 166 memset(&padding, 0, sizeof(padding)); |
156 } | 167 } |
157 | 168 |
158 ReportDisk::ReportDisk(const MetadataFileReportRecord& record, | 169 ReportDisk::ReportDisk(const MetadataFileReportRecord& record, |
159 const base::FilePath& report_dir, | 170 const base::FilePath& report_dir, |
160 const std::string& string_table) | 171 const std::string& string_table) |
161 : Report() { | 172 : Report() { |
162 uuid = record.uuid; | 173 uuid = record.uuid; |
163 file_path = report_dir.Append( | 174 file_path = report_dir.Append( |
164 base::UTF8ToUTF16(&string_table[record.file_path_index])); | 175 base::UTF8ToUTF16(&string_table[record.file_path_index])); |
165 id = &string_table[record.id_index]; | 176 id = &string_table[record.id_index]; |
166 creation_time = record.creation_time; | 177 creation_time = record.creation_time; |
167 uploaded = record.uploaded != 0; | |
168 last_upload_attempt_time = record.last_upload_attempt_time; | 178 last_upload_attempt_time = record.last_upload_attempt_time; |
169 upload_attempts = record.upload_attempts; | 179 upload_attempts = record.upload_attempts; |
170 state = static_cast<ReportState>(record.state); | 180 state = static_cast<ReportState>(record.state); |
| 181 uploaded = (record.attributes & kAttributeUploaded) != 0; |
| 182 upload_explicitly_requested = |
| 183 (record.attributes & kAttributeUploadExplicitlyRequested) != 0; |
171 } | 184 } |
172 | 185 |
173 ReportDisk::ReportDisk(const UUID& uuid, | 186 ReportDisk::ReportDisk(const UUID& uuid, |
174 const base::FilePath& path, | 187 const base::FilePath& path, |
175 time_t creation_time, | 188 time_t creation_time, |
176 ReportState state) | 189 ReportState state) |
177 : Report() { | 190 : Report() { |
178 this->uuid = uuid; | 191 this->uuid = uuid; |
179 this->file_path = path; | 192 this->file_path = path; |
180 this->creation_time = creation_time; | 193 this->creation_time = creation_time; |
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
570 OperationStatus LookUpCrashReport(const UUID& uuid, Report* report) override; | 583 OperationStatus LookUpCrashReport(const UUID& uuid, Report* report) override; |
571 OperationStatus GetPendingReports(std::vector<Report>* reports) override; | 584 OperationStatus GetPendingReports(std::vector<Report>* reports) override; |
572 OperationStatus GetCompletedReports(std::vector<Report>* reports) override; | 585 OperationStatus GetCompletedReports(std::vector<Report>* reports) override; |
573 OperationStatus GetReportForUploading(const UUID& uuid, | 586 OperationStatus GetReportForUploading(const UUID& uuid, |
574 const Report** report) override; | 587 const Report** report) override; |
575 OperationStatus RecordUploadAttempt(const Report* report, | 588 OperationStatus RecordUploadAttempt(const Report* report, |
576 bool successful, | 589 bool successful, |
577 const std::string& id) override; | 590 const std::string& id) override; |
578 OperationStatus SkipReportUpload(const UUID& uuid) override; | 591 OperationStatus SkipReportUpload(const UUID& uuid) override; |
579 OperationStatus DeleteReport(const UUID& uuid) override; | 592 OperationStatus DeleteReport(const UUID& uuid) override; |
| 593 OperationStatus RequestUpload(const UUID& uuid) override; |
580 | 594 |
581 private: | 595 private: |
582 std::unique_ptr<Metadata> AcquireMetadata(); | 596 std::unique_ptr<Metadata> AcquireMetadata(); |
583 | 597 |
584 base::FilePath base_dir_; | 598 base::FilePath base_dir_; |
585 Settings settings_; | 599 Settings settings_; |
586 InitializationStateDcheck initialized_; | 600 InitializationStateDcheck initialized_; |
587 | 601 |
588 DISALLOW_COPY_AND_ASSIGN(CrashReportDatabaseWin); | 602 DISALLOW_COPY_AND_ASSIGN(CrashReportDatabaseWin); |
589 }; | 603 }; |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
766 report->uuid, ReportState::kUploading, &report_disk); | 780 report->uuid, ReportState::kUploading, &report_disk); |
767 if (os != kNoError) | 781 if (os != kNoError) |
768 return os; | 782 return os; |
769 | 783 |
770 time_t now = time(nullptr); | 784 time_t now = time(nullptr); |
771 | 785 |
772 report_disk->uploaded = successful; | 786 report_disk->uploaded = successful; |
773 report_disk->id = id; | 787 report_disk->id = id; |
774 report_disk->last_upload_attempt_time = now; | 788 report_disk->last_upload_attempt_time = now; |
775 report_disk->upload_attempts++; | 789 report_disk->upload_attempts++; |
776 report_disk->state = | 790 if (successful) { |
777 successful ? ReportState::kCompleted : ReportState::kPending; | 791 report_disk->state = ReportState::kCompleted; |
| 792 report_disk->upload_explicitly_requested = false; |
| 793 } else { |
| 794 report_disk->state = ReportState::kPending; |
| 795 report_disk->upload_explicitly_requested = |
| 796 report->upload_explicitly_requested; |
| 797 } |
778 | 798 |
779 if (!settings_.SetLastUploadAttemptTime(now)) | 799 if (!settings_.SetLastUploadAttemptTime(now)) |
780 return kDatabaseError; | 800 return kDatabaseError; |
781 | 801 |
782 return kNoError; | 802 return kNoError; |
783 } | 803 } |
784 | 804 |
785 OperationStatus CrashReportDatabaseWin::DeleteReport(const UUID& uuid) { | 805 OperationStatus CrashReportDatabaseWin::DeleteReport(const UUID& uuid) { |
786 INITIALIZATION_STATE_DCHECK_VALID(initialized_); | 806 INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
787 | 807 |
(...skipping 16 matching lines...) Expand all Loading... |
804 | 824 |
805 OperationStatus CrashReportDatabaseWin::SkipReportUpload(const UUID& uuid) { | 825 OperationStatus CrashReportDatabaseWin::SkipReportUpload(const UUID& uuid) { |
806 INITIALIZATION_STATE_DCHECK_VALID(initialized_); | 826 INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
807 | 827 |
808 std::unique_ptr<Metadata> metadata(AcquireMetadata()); | 828 std::unique_ptr<Metadata> metadata(AcquireMetadata()); |
809 if (!metadata) | 829 if (!metadata) |
810 return kDatabaseError; | 830 return kDatabaseError; |
811 ReportDisk* report_disk; | 831 ReportDisk* report_disk; |
812 OperationStatus os = metadata->FindSingleReportAndMarkDirty( | 832 OperationStatus os = metadata->FindSingleReportAndMarkDirty( |
813 uuid, ReportState::kPending, &report_disk); | 833 uuid, ReportState::kPending, &report_disk); |
814 if (os == kNoError) | 834 if (os == kNoError) { |
815 report_disk->state = ReportState::kCompleted; | 835 report_disk->state = ReportState::kCompleted; |
| 836 report_disk->upload_explicitly_requested = false; |
| 837 } |
816 return os; | 838 return os; |
817 } | 839 } |
818 | 840 |
819 std::unique_ptr<Metadata> CrashReportDatabaseWin::AcquireMetadata() { | 841 std::unique_ptr<Metadata> CrashReportDatabaseWin::AcquireMetadata() { |
820 base::FilePath metadata_file = base_dir_.Append(kMetadataFileName); | 842 base::FilePath metadata_file = base_dir_.Append(kMetadataFileName); |
821 return Metadata::Create(metadata_file, base_dir_.Append(kReportsDirectory)); | 843 return Metadata::Create(metadata_file, base_dir_.Append(kReportsDirectory)); |
822 } | 844 } |
823 | 845 |
824 std::unique_ptr<CrashReportDatabase> InitializeInternal( | 846 std::unique_ptr<CrashReportDatabase> InitializeInternal( |
825 const base::FilePath& path, | 847 const base::FilePath& path, |
826 bool may_create) { | 848 bool may_create) { |
827 std::unique_ptr<CrashReportDatabaseWin> database_win( | 849 std::unique_ptr<CrashReportDatabaseWin> database_win( |
828 new CrashReportDatabaseWin(path)); | 850 new CrashReportDatabaseWin(path)); |
829 return database_win->Initialize(may_create) | 851 return database_win->Initialize(may_create) |
830 ? std::move(database_win) | 852 ? std::move(database_win) |
831 : std::unique_ptr<CrashReportDatabaseWin>(); | 853 : std::unique_ptr<CrashReportDatabaseWin>(); |
832 } | 854 } |
833 | 855 |
| 856 OperationStatus CrashReportDatabaseWin::RequestUpload(const UUID& uuid) { |
| 857 INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
| 858 |
| 859 std::unique_ptr<Metadata> metadata(AcquireMetadata()); |
| 860 if (!metadata) |
| 861 return kDatabaseError; |
| 862 |
| 863 ReportDisk* report_disk; |
| 864 // TODO(gayane): Search for the report only once regardless of its state. |
| 865 OperationStatus os = metadata->FindSingleReportAndMarkDirty( |
| 866 uuid, ReportState::kCompleted, &report_disk); |
| 867 if (os == kBusyError) { |
| 868 os = metadata->FindSingleReportAndMarkDirty( |
| 869 uuid, ReportState::kPending, &report_disk); |
| 870 } |
| 871 |
| 872 if (os != kNoError) |
| 873 return os; |
| 874 |
| 875 // If the crash report has already been uploaded, don't request new upload. |
| 876 if (report_disk->uploaded) |
| 877 return kCannotRequestUpload; |
| 878 |
| 879 // Mark the crash report as having upload explicitly requested by the user, |
| 880 // and move it to the pending state. |
| 881 report_disk->upload_explicitly_requested = true; |
| 882 report_disk->state = ReportState::kPending; |
| 883 |
| 884 return kNoError; |
| 885 } |
| 886 |
834 } // namespace | 887 } // namespace |
835 | 888 |
836 // static | 889 // static |
837 std::unique_ptr<CrashReportDatabase> CrashReportDatabase::Initialize( | 890 std::unique_ptr<CrashReportDatabase> CrashReportDatabase::Initialize( |
838 const base::FilePath& path) { | 891 const base::FilePath& path) { |
839 return InitializeInternal(path, true); | 892 return InitializeInternal(path, true); |
840 } | 893 } |
841 | 894 |
842 // static | 895 // static |
843 std::unique_ptr<CrashReportDatabase> | 896 std::unique_ptr<CrashReportDatabase> |
844 CrashReportDatabase::InitializeWithoutCreating(const base::FilePath& path) { | 897 CrashReportDatabase::InitializeWithoutCreating(const base::FilePath& path) { |
845 return InitializeInternal(path, false); | 898 return InitializeInternal(path, false); |
846 } | 899 } |
847 | 900 |
848 } // namespace crashpad | 901 } // namespace crashpad |
OLD | NEW |