@@ -46,14 +46,21 @@ namespace {
46
46
constexpr const uint32_t kMagic = 0x8495E0B4 ;
47
47
constexpr const char kLegacyPersistentPropertyDir [] = " /data/property" ;
48
48
49
- Result<std::vector<std::pair<std::string, std::string>>> LoadLegacyPersistentProperties () {
49
+ void AddPersistentProperty (const std::string& name, const std::string& value,
50
+ PersistentProperties* persistent_properties) {
51
+ auto persistent_property_record = persistent_properties->add_properties ();
52
+ persistent_property_record->set_name (name);
53
+ persistent_property_record->set_value (value);
54
+ }
55
+
56
+ Result<PersistentProperties> LoadLegacyPersistentProperties () {
50
57
std::unique_ptr<DIR, decltype (&closedir)> dir (opendir (kLegacyPersistentPropertyDir ), closedir);
51
58
if (!dir) {
52
59
return ErrnoError () << " Unable to open persistent property directory \" "
53
60
<< kLegacyPersistentPropertyDir << " \" " ;
54
61
}
55
62
56
- std::vector<std::pair<std::string, std::string>> persistent_properties;
63
+ PersistentProperties persistent_properties;
57
64
dirent* entry;
58
65
while ((entry = readdir (dir.get ())) != nullptr ) {
59
66
if (!StartsWith (entry->d_name , " persist." )) {
@@ -87,7 +94,7 @@ Result<std::vector<std::pair<std::string, std::string>>> LoadLegacyPersistentPro
87
94
88
95
std::string value;
89
96
if (ReadFdToString (fd, &value)) {
90
- persistent_properties. emplace_back (entry->d_name , value);
97
+ AddPersistentProperty (entry->d_name , value, &persistent_properties );
91
98
} else {
92
99
PLOG (ERROR) << " Unable to read persistent property file " << entry->d_name ;
93
100
}
@@ -115,30 +122,28 @@ void RemoveLegacyPersistentPropertyFiles() {
115
122
}
116
123
}
117
124
118
- std::vector<std::pair<std::string, std::string>> LoadPersistentPropertiesFromMemory () {
119
- std::vector<std::pair<std::string, std::string>> properties ;
125
+ PersistentProperties LoadPersistentPropertiesFromMemory () {
126
+ PersistentProperties persistent_properties ;
120
127
__system_property_foreach (
121
128
[](const prop_info* pi, void * cookie) {
122
129
__system_property_read_callback (
123
130
pi,
124
131
[](void * cookie, const char * name, const char * value, unsigned serial) {
125
132
if (StartsWith (name, " persist." )) {
126
- auto properties =
127
- reinterpret_cast <std::vector<std::pair<std::string, std::string>>*>(
128
- cookie);
129
- properties->emplace_back (name, value);
133
+ auto properties = reinterpret_cast <PersistentProperties*>(cookie);
134
+ AddPersistentProperty (name, value, properties);
130
135
}
131
136
},
132
137
cookie);
133
138
},
134
- &properties );
135
- return properties ;
139
+ &persistent_properties );
140
+ return persistent_properties ;
136
141
}
137
142
138
143
class PersistentPropertyFileParser {
139
144
public:
140
145
PersistentPropertyFileParser (const std::string& contents) : contents_(contents), position_(0 ) {}
141
- Result<std::vector<std::pair<std::string, std::string>> > Parse ();
146
+ Result<PersistentProperties > Parse ();
142
147
143
148
private:
144
149
Result<std::string> ReadString ();
@@ -148,9 +153,7 @@ class PersistentPropertyFileParser {
148
153
size_t position_;
149
154
};
150
155
151
- Result<std::vector<std::pair<std::string, std::string>>> PersistentPropertyFileParser::Parse () {
152
- std::vector<std::pair<std::string, std::string>> result;
153
-
156
+ Result<PersistentProperties> PersistentPropertyFileParser::Parse () {
154
157
if (auto magic = ReadUint32 (); magic) {
155
158
if (*magic != kMagic ) {
156
159
return Error () << " Magic value '0x" << std::hex << *magic
@@ -174,24 +177,20 @@ Result<std::vector<std::pair<std::string, std::string>>> PersistentPropertyFileP
174
177
return Error () << " Could not read num_properties: " << num_properties.error ();
175
178
}
176
179
180
+ PersistentProperties result;
177
181
while (position_ < contents_.size ()) {
178
- auto key = ReadString ();
179
- if (!key ) {
180
- return Error () << " Could not read key : " << key .error ();
182
+ auto name = ReadString ();
183
+ if (!name ) {
184
+ return Error () << " Could not read name : " << name .error ();
181
185
}
182
- if (!StartsWith (*key , " persist." )) {
183
- return Error () << " Property '" << *key << " ' does not starts with 'persist.'" ;
186
+ if (!StartsWith (*name , " persist." )) {
187
+ return Error () << " Property '" << *name << " ' does not starts with 'persist.'" ;
184
188
}
185
189
auto value = ReadString ();
186
190
if (!value) {
187
191
return Error () << " Could not read value: " << value.error ();
188
192
}
189
- result.emplace_back (*key, *value);
190
- }
191
-
192
- if (result.size () != *num_properties) {
193
- return Error () << " Mismatch of number of persistent properties read, " << result.size ()
194
- << " and number of persistent properties expected, " << *num_properties;
193
+ AddPersistentProperty (*name, *value, &result);
195
194
}
196
195
197
196
return result;
@@ -220,9 +219,7 @@ Result<uint32_t> PersistentPropertyFileParser::ReadUint32() {
220
219
return result;
221
220
}
222
221
223
- } // namespace
224
-
225
- Result<std::vector<std::pair<std::string, std::string>>> LoadPersistentPropertyFile () {
222
+ Result<std::string> ReadPersistentPropertyFile () {
226
223
const std::string temp_filename = persistent_property_filename + " .tmp" ;
227
224
if (access (temp_filename.c_str (), F_OK) == 0 ) {
228
225
LOG (INFO)
@@ -234,51 +231,47 @@ Result<std::vector<std::pair<std::string, std::string>>> LoadPersistentPropertyF
234
231
if (!file_contents) {
235
232
return Error () << " Unable to read persistent property file: " << file_contents.error ();
236
233
}
237
- auto parsed_contents = PersistentPropertyFileParser (*file_contents).Parse ();
238
- if (!parsed_contents) {
239
- // If the file cannot be parsed, then we don't have any recovery mechanisms, so we delete
240
- // it to allow for future writes to take place successfully.
241
- unlink (persistent_property_filename.c_str ());
242
- return Error () << " Unable to parse persistent property file: " << parsed_contents.error ();
243
- }
244
- return parsed_contents;
234
+ return *file_contents;
245
235
}
246
236
247
- std::string GenerateFileContents (
248
- const std::vector<std::pair<std::string, std::string>>& persistent_properties) {
249
- std::string result;
250
-
251
- uint32_t magic = kMagic ;
252
- result.append (reinterpret_cast <char *>(&magic), sizeof (uint32_t ));
237
+ } // namespace
253
238
254
- uint32_t version = 1 ;
255
- result.append (reinterpret_cast <char *>(&version), sizeof (uint32_t ));
239
+ Result<PersistentProperties> LoadPersistentPropertyFile () {
240
+ auto file_contents = ReadPersistentPropertyFile ();
241
+ if (!file_contents) return file_contents.error ();
256
242
257
- uint32_t num_properties = persistent_properties.size ();
258
- result.append (reinterpret_cast <char *>(&num_properties), sizeof (uint32_t ));
243
+ // Check the intermediate "I should have used protobufs from the start" format.
244
+ // TODO: Remove this.
245
+ auto parsed_contents = PersistentPropertyFileParser (*file_contents).Parse ();
246
+ if (parsed_contents) {
247
+ LOG (INFO) << " Intermediate format persistent property file found, converting to protobuf" ;
259
248
260
- for (const auto & [key, value] : persistent_properties) {
261
- uint32_t key_length = key.length ();
262
- result.append (reinterpret_cast <char *>(&key_length), sizeof (uint32_t ));
263
- result.append (key);
264
- uint32_t value_length = value.length ();
265
- result.append (reinterpret_cast <char *>(&value_length), sizeof (uint32_t ));
266
- result.append (value);
249
+ // Update to the protobuf format
250
+ WritePersistentPropertyFile (*parsed_contents);
251
+ return parsed_contents;
267
252
}
268
- return result;
269
- }
270
253
271
- Result<Success> WritePersistentPropertyFile (
272
- const std::vector<std::pair<std::string, std::string>>& persistent_properties) {
273
- auto file_contents = GenerateFileContents (persistent_properties);
254
+ PersistentProperties persistent_properties;
255
+ if (persistent_properties.ParseFromString (*file_contents)) return persistent_properties;
256
+
257
+ // If the file cannot be parsed in either format, then we don't have any recovery
258
+ // mechanisms, so we delete it to allow for future writes to take place successfully.
259
+ unlink (persistent_property_filename.c_str ());
260
+ return Error () << " Unable to parse persistent property file: " << parsed_contents.error ();
261
+ }
274
262
263
+ Result<Success> WritePersistentPropertyFile (const PersistentProperties& persistent_properties) {
275
264
const std::string temp_filename = persistent_property_filename + " .tmp" ;
276
265
unique_fd fd (TEMP_FAILURE_RETRY (
277
266
open (temp_filename.c_str (), O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC | O_CLOEXEC, 0600 )));
278
267
if (fd == -1 ) {
279
268
return ErrnoError () << " Could not open temporary properties file" ;
280
269
}
281
- if (!WriteStringToFd (file_contents, fd)) {
270
+ std::string serialized_string;
271
+ if (!persistent_properties.SerializeToString (&serialized_string)) {
272
+ return Error () << " Unable to serialize properties" ;
273
+ }
274
+ if (!WriteStringToFd (serialized_string, fd)) {
282
275
return ErrnoError () << " Unable to write file contents" ;
283
276
}
284
277
fsync (fd);
@@ -295,26 +288,30 @@ Result<Success> WritePersistentPropertyFile(
295
288
// Persistent properties are not written often, so we rather not keep any data in memory and read
296
289
// then rewrite the persistent property file for each update.
297
290
void WritePersistentProperty (const std::string& name, const std::string& value) {
298
- auto persistent_properties = LoadPersistentPropertyFile ();
299
- if (!persistent_properties) {
291
+ auto file_contents = ReadPersistentPropertyFile ();
292
+ PersistentProperties persistent_properties;
293
+
294
+ if (!file_contents || !persistent_properties.ParseFromString (*file_contents)) {
300
295
LOG (ERROR) << " Recovering persistent properties from memory: "
301
- << persistent_properties. error ( );
296
+ << (!file_contents ? file_contents. error_string () : " Could not parse protobuf " );
302
297
persistent_properties = LoadPersistentPropertiesFromMemory ();
303
298
}
304
- auto it = std::find_if (persistent_properties->begin (), persistent_properties->end (),
305
- [&name](const auto & entry) { return entry.first == name; });
306
- if (it != persistent_properties->end ()) {
307
- *it = {name, value};
299
+ auto it = std::find_if (persistent_properties.mutable_properties ()->begin (),
300
+ persistent_properties.mutable_properties ()->end (),
301
+ [&name](const auto & record) { return record.name () == name; });
302
+ if (it != persistent_properties.mutable_properties ()->end ()) {
303
+ it->set_name (name);
304
+ it->set_value (value);
308
305
} else {
309
- persistent_properties-> emplace_back (name, value);
306
+ AddPersistentProperty (name, value, &persistent_properties );
310
307
}
311
308
312
- if (auto result = WritePersistentPropertyFile (* persistent_properties); !result) {
309
+ if (auto result = WritePersistentPropertyFile (persistent_properties); !result) {
313
310
LOG (ERROR) << " Could not store persistent property: " << result.error ();
314
311
}
315
312
}
316
313
317
- std::vector<std::pair<std::string, std::string>> LoadPersistentProperties () {
314
+ PersistentProperties LoadPersistentProperties () {
318
315
auto persistent_properties = LoadPersistentPropertyFile ();
319
316
320
317
if (!persistent_properties) {
0 commit comments