[ion] Storage delegate gets notified of storage changes

This commit is contained in:
Léa Saviot
2018-10-24 11:37:52 +02:00
committed by Émilie Feral
parent 34f5f0262b
commit 38f3c5b16d
2 changed files with 39 additions and 1 deletions

View File

@@ -11,6 +11,8 @@ namespace Ion {
*
* A record's fullName is baseName.extension. */
class StorageDelegate;
class Storage {
public:
typedef uint16_t record_size_t;
@@ -76,6 +78,11 @@ public:
Storage();
size_t availableSize();
uint32_t checksum();
// Delegate
void setDelegate(StorageDelegate * delegate) { m_delegate = delegate; }
void notifyChangeToDelegate() const;
int numberOfRecordsWithExtension(const char * extension);
static bool FullNameHasExtension(const char * fullName, const char * extension, size_t extensionLength);
@@ -91,6 +98,7 @@ public:
// Record destruction
void destroyRecordsWithExtension(const char * extension);
private:
constexpr static uint32_t Magic = 0xEE0BDDBA;
constexpr static size_t k_maxRecordSize = (1 << sizeof(record_size_t)*8);
@@ -143,6 +151,18 @@ private:
uint32_t m_magicHeader;
char m_buffer[k_storageSize];
uint32_t m_magicFooter;
StorageDelegate * m_delegate;
};
/* Some apps memoize records and need to be notified when a record might have
* become invalid. We could have computed and compared the checksum of the
* storage to detect storage invalidity, but profiling showed that this slows
* down the execution (for example when scrolling the functions list).
* We thus decided to notify a delegate when the storage changes. */
class StorageDelegate {
public:
virtual void storageDidChange(const Storage * storage) = 0;
};
}

View File

@@ -73,7 +73,8 @@ Storage::Record::Record(const char * basename, int basenameLength, const char *
Storage::Storage() :
m_magicHeader(Magic),
m_buffer(),
m_magicFooter(Magic)
m_magicFooter(Magic),
m_delegate(nullptr)
{
assert(m_magicHeader == Magic);
assert(m_magicFooter == Magic);
@@ -89,6 +90,12 @@ uint32_t Storage::checksum() {
return Ion::crc32PaddedString(m_buffer, endBuffer()-m_buffer);
}
void Storage::notifyChangeToDelegate() const {
if (m_delegate != nullptr) {
m_delegate->storageDidChange(this);
}
}
Storage::Record::ErrorStatus Storage::createRecordWithFullName(const char * fullName, const void * data, size_t size) {
size_t recordSize = sizeOfRecordWithFullName(fullName, size);
if (recordSize >= k_maxRecordSize || recordSize > availableSize()) {
@@ -107,6 +114,7 @@ Storage::Record::ErrorStatus Storage::createRecordWithFullName(const char * full
newRecord += overrideValueAtPosition(newRecord, data, size);
// Next Record is null-sized
overrideSizeAtPosition(newRecord, 0);
notifyChangeToDelegate();
return Record::ErrorStatus::None;
}
@@ -128,6 +136,7 @@ Storage::Record::ErrorStatus Storage::createRecordWithExtension(const char * bas
newRecord += overrideValueAtPosition(newRecord, data, size);
// Next Record is null-sized
overrideSizeAtPosition(newRecord, 0);
notifyChangeToDelegate();
return Record::ErrorStatus::None;
}
@@ -201,15 +210,20 @@ Storage::Record Storage::recordBaseNamedWithExtensions(const char * baseName, co
void Storage::destroyRecordsWithExtension(const char * extension) {
size_t extensionLength = strlen(extension);
char * currentRecordStart = (char *)m_buffer;
bool didChange = false;
while (currentRecordStart != nullptr && sizeOfRecordStarting(currentRecordStart) != 0) {
const char * currentFullName = fullNameOfRecordStarting(currentRecordStart);
if (FullNameHasExtension(currentFullName, extension, extensionLength)) {
Record currentRecord(currentFullName);
currentRecord.destroy();
didChange = true;
continue;
}
currentRecordStart = *(RecordIterator(currentRecordStart).operator++());
}
if (didChange) {
notifyChangeToDelegate();
}
}
const char * Storage::fullNameOfRecord(const Record record) {
@@ -241,6 +255,7 @@ Storage::Record::ErrorStatus Storage::setFullNameOfRecord(const Record record, c
}
overrideSizeAtPosition(p, newRecordSize);
overrideFullNameAtPosition(p+sizeof(record_size_t), fullName);
notifyChangeToDelegate();
return Record::ErrorStatus::None;
}
}
@@ -263,6 +278,7 @@ Storage::Record::ErrorStatus Storage::setBaseNameWithExtensionOfRecord(Record re
}
overrideSizeAtPosition(p, newRecordSize);
overrideBaseNameWithExtensionAtPosition(p+sizeof(record_size_t), baseName, extension);
notifyChangeToDelegate();
return Record::ErrorStatus::None;
}
}
@@ -295,6 +311,7 @@ Storage::Record::ErrorStatus Storage::setValueOfRecord(Record record, Record::Da
record_size_t fullNameSize = strlen(fullName)+1;
overrideSizeAtPosition(p, newRecordSize);
overrideValueAtPosition(p+sizeof(record_size_t)+fullNameSize, data.buffer, data.size);
notifyChangeToDelegate();
return Record::ErrorStatus::None;
}
}
@@ -310,6 +327,7 @@ void Storage::destroyRecord(Record record) {
if (record == currentRecord) {
record_size_t previousRecordSize = sizeOfRecordStarting(p);
slideBuffer(p+previousRecordSize, -previousRecordSize);
notifyChangeToDelegate();
return;
}
}