Remove hasData() method from StoragePlugin

because it is one extra request for packages that do have data and from the looks of it not really needed.
This commit is contained in:
Torsten Grote 2024-08-26 13:28:01 -03:00
parent 27eb95f768
commit 099e0ba6d5
No known key found for this signature in database
GPG key ID: 3E5F77D92CF891FF
8 changed files with 29 additions and 131 deletions

View file

@ -199,37 +199,23 @@ class PluginTest : KoinComponent {
val name1 = getRandomBase64()
val name2 = getRandomBase64()
// no data available initially
assertFalse(storagePlugin.hasData(token, name1))
assertFalse(storagePlugin.hasData(token, name2))
// write full backup data
val data = getRandomByteArray(5 * 1024 * 1024)
storagePlugin.getOutputStream(token, name1).writeAndClose(data)
// data is available now, but only this token
assertTrue(storagePlugin.hasData(token, name1))
assertFalse(storagePlugin.hasData(token + 1, name1))
// restore data matches backed up data
assertReadEquals(data, storagePlugin.getInputStream(token, name1))
// write and check data for second package
val data2 = getRandomByteArray(5 * 1024 * 1024)
storagePlugin.getOutputStream(token, name2).writeAndClose(data2)
assertTrue(storagePlugin.hasData(token, name2))
assertReadEquals(data2, storagePlugin.getInputStream(token, name2))
// remove data of first package again and ensure that no more data is found
storagePlugin.removeData(token, name1)
assertFalse(storagePlugin.hasData(token, name1))
// second package is still there
assertTrue(storagePlugin.hasData(token, name2))
// ensure that it gets deleted as well
storagePlugin.removeData(token, name2)
assertFalse(storagePlugin.hasData(token, name2))
}
private fun initStorage(token: Long) = runBlocking {

View file

@ -39,12 +39,6 @@ interface StoragePlugin<T> {
@Throws(IOException::class)
suspend fun initializeDevice()
/**
* Return true if there is data stored for the given name.
*/
@Throws(IOException::class)
suspend fun hasData(token: Long, name: String): Boolean
/**
* Return a raw byte stream for writing data for the given name.
*/

View file

@ -87,12 +87,6 @@ internal class DocumentsProviderStoragePlugin(
storage.reset(null)
}
@Throws(IOException::class)
override suspend fun hasData(token: Long, name: String): Boolean {
val setDir = storage.getSetDir(token) ?: return false
return setDir.findFileBlocking(context, name) != null
}
@Throws(IOException::class)
override suspend fun getOutputStream(token: Long, name: String): OutputStream {
val setDir = storage.getSetDir(token) ?: throw IOException()

View file

@ -98,28 +98,6 @@ internal class WebDavStoragePlugin(
}
}
@Throws(IOException::class)
override suspend fun hasData(token: Long, name: String): Boolean {
val location = "$url/$token/$name".toHttpUrl()
val davCollection = DavCollection(okHttpClient, location)
return try {
val response = suspendCoroutine { cont ->
davCollection.head { response ->
cont.resume(response)
}
}
debugLog { "hasData($token, $name) = $response" }
response.isSuccessful
} catch (e: NotFoundException) {
debugLog { "hasData($token, $name) = $e" }
false
} catch (e: Exception) {
if (e is IOException) throw e
else throw IOException(e)
}
}
@Throws(IOException::class)
override suspend fun getOutputStream(token: Long, name: String): OutputStream {
val location = "$url/$token/$name".toHttpUrl()

View file

@ -234,48 +234,36 @@ internal class RestoreCoordinator(
if (version == 0.toByte()) return nextRestorePackageV0(state, packageInfo)
val packageName = packageInfo.packageName
val type = try {
when (state.backupMetadata.packageMetadataMap[packageName]?.backupType) {
BackupType.KV -> {
val name = crypto.getNameForPackage(state.backupMetadata.salt, packageName)
if (plugin.hasData(state.token, name)) {
Log.i(TAG, "Found K/V data for $packageName.")
kv.initializeState(
version = version,
token = state.token,
name = name,
packageInfo = packageInfo,
autoRestorePackageInfo = state.autoRestorePackageInfo
)
state.currentPackage = packageName
TYPE_KEY_VALUE
} else throw IOException("No data found for $packageName. Skipping.")
}
BackupType.FULL -> {
val name = crypto.getNameForPackage(state.backupMetadata.salt, packageName)
if (plugin.hasData(state.token, name)) {
Log.i(TAG, "Found full backup data for $packageName.")
full.initializeState(version, state.token, name, packageInfo)
state.currentPackage = packageName
TYPE_FULL_STREAM
} else throw IOException("No data found for $packageName. Skipping...")
}
null -> {
Log.i(TAG, "No backup type found for $packageName. Skipping...")
state.backupMetadata.packageMetadataMap[packageName]?.backupType?.let { s ->
Log.w(TAG, "State was ${s.name}")
}
failedPackages.add(packageName)
return nextRestorePackage()
}
val type = when (state.backupMetadata.packageMetadataMap[packageName]?.backupType) {
BackupType.KV -> {
val name = crypto.getNameForPackage(state.backupMetadata.salt, packageName)
kv.initializeState(
version = version,
token = state.token,
name = name,
packageInfo = packageInfo,
autoRestorePackageInfo = state.autoRestorePackageInfo
)
state.currentPackage = packageName
TYPE_KEY_VALUE
}
BackupType.FULL -> {
val name = crypto.getNameForPackage(state.backupMetadata.salt, packageName)
full.initializeState(version, state.token, name, packageInfo)
state.currentPackage = packageName
TYPE_FULL_STREAM
}
null -> {
Log.i(TAG, "No backup type found for $packageName. Skipping...")
state.backupMetadata.packageMetadataMap[packageName]?.backupType?.let { s ->
Log.w(TAG, "State was ${s.name}")
}
failedPackages.add(packageName)
// don't return null and cause abort here, but try next package
return nextRestorePackage()
}
} catch (e: IOException) {
Log.e(TAG, "Error finding restore data for $packageName.", e)
failedPackages.add(packageName)
// don't return null and cause abort here, but try next package
return nextRestorePackage()
}
return RestoreDescription(packageName, type)
}

View file

@ -64,17 +64,11 @@ internal class WebDavStoragePluginTest : TransportTest() {
// initially, we don't have any backups
assertEquals(emptySet<EncryptedMetadata>(), plugin.getAvailableBackups()?.toSet())
// and no data
assertFalse(plugin.hasData(token, FILE_BACKUP_METADATA))
// write out the metadata file
plugin.getOutputStream(token, FILE_BACKUP_METADATA).use {
it.write(metadata)
}
// now we have data
assertTrue(plugin.hasData(token, FILE_BACKUP_METADATA))
try {
// now we have one backup matching our token
val backups = plugin.getAvailableBackups()?.toSet() ?: fail()
@ -86,9 +80,6 @@ internal class WebDavStoragePluginTest : TransportTest() {
metadata,
plugin.getInputStream(token, FILE_BACKUP_METADATA).use { it.readAllBytes() },
)
// it has data now
assertTrue(plugin.hasData(token, FILE_BACKUP_METADATA))
} finally {
// remove data at the end, so consecutive test runs pass
plugin.removeData(token, FILE_BACKUP_METADATA)

View file

@ -190,7 +190,6 @@ internal class CoordinatorIntegrationTest : TransportTest() {
// find data for K/V backup
every { crypto.getNameForPackage(metadata.salt, packageInfo.packageName) } returns name
coEvery { backupPlugin.hasData(token, name) } returns true
val restoreDescription = restore.nextRestorePackage() ?: fail()
assertEquals(packageInfo.packageName, restoreDescription.packageName)
@ -264,7 +263,6 @@ internal class CoordinatorIntegrationTest : TransportTest() {
// find data for K/V backup
every { crypto.getNameForPackage(metadata.salt, packageInfo.packageName) } returns name
coEvery { backupPlugin.hasData(token, name) } returns true
val restoreDescription = restore.nextRestorePackage() ?: fail()
assertEquals(packageInfo.packageName, restoreDescription.packageName)
@ -327,7 +325,6 @@ internal class CoordinatorIntegrationTest : TransportTest() {
// finds data for full backup
every { crypto.getNameForPackage(salt, packageInfo.packageName) } returns name
coEvery { backupPlugin.hasData(token, name) } returns true
val restoreDescription = restore.nextRestorePackage() ?: fail()
assertEquals(packageInfo.packageName, restoreDescription.packageName)

View file

@ -239,7 +239,6 @@ internal class RestoreCoordinatorTest : TransportTest() {
restore.startRestore(token, packageInfoArray)
every { crypto.getNameForPackage(metadata.salt, packageName) } returns name
coEvery { plugin.hasData(token, name) } returns true
every { kv.initializeState(VERSION, token, name, packageInfo) } just Runs
val expected = RestoreDescription(packageName, TYPE_KEY_VALUE)
@ -273,19 +272,6 @@ internal class RestoreCoordinatorTest : TransportTest() {
assertEquals(expected, restore.nextRestorePackage())
}
@Test
fun `nextRestorePackage() returns NO_MORE_PACKAGES if data not found`() = runBlocking {
restore.beforeStartRestore(metadata)
restore.startRestore(token, packageInfoArray2)
every { crypto.getNameForPackage(metadata.salt, packageName) } returns name
coEvery { plugin.hasData(token, name) } returns false
every { crypto.getNameForPackage(metadata.salt, packageInfo2.packageName) } returns name2
coEvery { plugin.hasData(token, name2) } returns false
assertEquals(NO_MORE_PACKAGES, restore.nextRestorePackage())
}
@Test
fun `nextRestorePackage() tries next package if one has no backup type()`() = runBlocking {
metadata.packageMetadataMap[packageName] =
@ -294,7 +280,6 @@ internal class RestoreCoordinatorTest : TransportTest() {
restore.startRestore(token, packageInfoArray2)
every { crypto.getNameForPackage(metadata.salt, packageInfo2.packageName) } returns name2
coEvery { plugin.hasData(token, name2) } returns true
every { full.initializeState(VERSION, token, name2, packageInfo2) } just Runs
val expected = RestoreDescription(packageInfo2.packageName, TYPE_FULL_STREAM)
@ -309,14 +294,12 @@ internal class RestoreCoordinatorTest : TransportTest() {
restore.startRestore(token, packageInfoArray2)
every { crypto.getNameForPackage(metadata.salt, packageName) } returns name
coEvery { plugin.hasData(token, name) } returns true
every { kv.initializeState(VERSION, token, name, packageInfo) } just Runs
val expected = RestoreDescription(packageInfo.packageName, TYPE_KEY_VALUE)
assertEquals(expected, restore.nextRestorePackage())
every { crypto.getNameForPackage(metadata.salt, packageInfo2.packageName) } returns name2
coEvery { plugin.hasData(token, name2) } returns true
every { full.initializeState(VERSION, token, name2, packageInfo2) } just Runs
val expected2 =
@ -359,19 +342,6 @@ internal class RestoreCoordinatorTest : TransportTest() {
assertEquals(NO_MORE_PACKAGES, restore.nextRestorePackage())
}
@Test
fun `when plugin#hasData() throws, it tries next package`() = runBlocking {
restore.beforeStartRestore(metadata)
restore.startRestore(token, packageInfoArray2)
every { crypto.getNameForPackage(metadata.salt, packageName) } returns name
coEvery { plugin.hasData(token, name) } returns false
every { crypto.getNameForPackage(metadata.salt, packageInfo2.packageName) } returns name2
coEvery { plugin.hasData(token, name2) } throws IOException()
assertEquals(NO_MORE_PACKAGES, restore.nextRestorePackage())
}
@Test
@Suppress("deprecation")
fun `v0 when full#hasDataForPackage() throws, it tries next package`() = runBlocking {