Skip to content

Commit 6f5eceb

Browse files
RUM-16305: Refactor checking how much space is left in the current batch
1 parent 8523c51 commit 6f5eceb

26 files changed

Lines changed: 352 additions & 462 deletions

dd-sdk-android-core/api/apiSurface

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,6 @@ interface com.datadog.android.api.net.RequestFactory
200200
interface com.datadog.android.api.storage.DataWriter<T>
201201
fun write(EventBatchWriter, T, EventType): Boolean
202202
interface com.datadog.android.api.storage.EventBatchWriter
203-
fun currentMetadata(): ByteArray?
204203
fun write(RawBatchEvent, ByteArray?, EventType): Boolean
205204
enum com.datadog.android.api.storage.EventType
206205
- DEFAULT

dd-sdk-android-core/api/dd-sdk-android-core.api

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,6 @@ public abstract interface class com/datadog/android/api/storage/DataWriter {
577577
}
578578

579579
public abstract interface class com/datadog/android/api/storage/EventBatchWriter {
580-
public abstract fun currentMetadata ()[B
581580
public abstract fun write (Lcom/datadog/android/api/storage/RawBatchEvent;[BLcom/datadog/android/api/storage/EventType;)Z
582581
}
583582

dd-sdk-android-core/src/main/kotlin/com/datadog/android/api/storage/EventBatchWriter.kt

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,10 @@ package com.datadog.android.api.storage
99
import androidx.annotation.WorkerThread
1010

1111
/**
12-
* Writer allowing [FeatureScope] to write events in the storage exposing current batch metadata.
12+
* Writer allowing [FeatureScope] to write events in the storage.
1313
*/
1414
interface EventBatchWriter {
1515

16-
/**
17-
* @return the metadata of the current writeable batch
18-
*/
19-
@WorkerThread
20-
fun currentMetadata(): ByteArray?
21-
2216
/**
2317
* Writes the content of the event to the current available batch.
2418
* @param event the event to write (content + metadata)

dd-sdk-android-core/src/main/kotlin/com/datadog/android/core/internal/CoreFeature.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ import com.datadog.android.core.internal.net.info.NetworkInfoProvider
4040
import com.datadog.android.core.internal.net.info.NoOpNetworkInfoProvider
4141
import com.datadog.android.core.internal.persistence.JsonObjectDeserializer
4242
import com.datadog.android.core.internal.persistence.file.FilePersistenceConfig
43-
import com.datadog.android.core.internal.persistence.file.FileWriter
4443
import com.datadog.android.core.internal.persistence.file.batch.BatchFileReaderWriter
4544
import com.datadog.android.core.internal.persistence.file.deleteSafe
4645
import com.datadog.android.core.internal.persistence.file.existsSafe
@@ -231,7 +230,7 @@ internal class CoreFeature(
231230

232231
@get:WorkerThread
233232
private val lastViewEventFile: File by lazy { File(storageDir, LAST_RUM_VIEW_EVENT_FILE_NAME) }
234-
private val lastViewEventFileWriter: FileWriter<RawBatchEvent> by lazy {
233+
private val lastViewEventFileWriter: BatchFileReaderWriter by lazy {
235234
BatchFileReaderWriter.create(
236235
internalLogger = internalLogger,
237236
encryption = localDataEncryption
@@ -387,7 +386,8 @@ internal class CoreFeature(
387386

388387
@WorkerThread
389388
internal fun writeLastViewEvent(data: ByteArray) {
390-
lastViewEventFileWriter.writeData(lastViewEventFile, RawBatchEvent(data), false)
389+
val serialized = lastViewEventFileWriter.serializeToBytes(RawBatchEvent(data = data)) ?: return
390+
lastViewEventFileWriter.writeBinaryData(lastViewEventFile, serialized, false)
391391
}
392392

393393
@WorkerThread

dd-sdk-android-core/src/main/kotlin/com/datadog/android/core/internal/persistence/AbstractStorage.kt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,6 @@ internal class AbstractStorage(
6767
): EventWriteScope {
6868
val strategy = resolvePersistenceStrategy(datadogContext)
6969
val writer = object : EventBatchWriter {
70-
@WorkerThread
71-
override fun currentMetadata(): ByteArray? {
72-
return strategy.currentMetadata()
73-
}
74-
7570
@WorkerThread
7671
override fun write(event: RawBatchEvent, batchMetadata: ByteArray?, eventType: EventType): Boolean {
7772
return strategy.write(event, batchMetadata, eventType)

dd-sdk-android-core/src/main/kotlin/com/datadog/android/core/internal/persistence/FileEventBatchWriter.kt

Lines changed: 18 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -14,51 +14,38 @@ import com.datadog.android.api.storage.RawBatchEvent
1414
import com.datadog.android.core.internal.persistence.file.FileOrchestrator
1515
import com.datadog.android.core.internal.persistence.file.FilePersistenceConfig
1616
import com.datadog.android.core.internal.persistence.file.FileReaderWriter
17-
import com.datadog.android.core.internal.persistence.file.FileWriter
18-
import com.datadog.android.core.internal.persistence.file.existsSafe
17+
import com.datadog.android.core.internal.persistence.file.batch.BatchFileReaderWriter
1918
import java.io.File
2019
import java.util.Locale
2120

2221
internal class FileEventBatchWriter(
2322
private val fileOrchestrator: FileOrchestrator,
24-
private val eventsWriter: FileWriter<RawBatchEvent>,
23+
private val eventsWriter: BatchFileReaderWriter,
2524
private val metadataReaderWriter: FileReaderWriter,
2625
private val filePersistenceConfig: FilePersistenceConfig,
2726
private val batchWriteEventListener: BatchWriteEventListener,
2827
private val internalLogger: InternalLogger
2928
) : EventBatchWriter {
3029

31-
@get:WorkerThread
32-
private val batchFile: File? by lazy {
33-
@Suppress("ThreadSafety") // called in the worker context
34-
fileOrchestrator.getWritableFile()
35-
}
36-
37-
@get:WorkerThread
38-
private val metadataFile: File?
39-
get() = batchFile?.let {
40-
@Suppress("ThreadSafety") // called in the worker context
41-
fileOrchestrator.getMetadataFile(it)
42-
}
43-
44-
@WorkerThread
45-
override fun currentMetadata(): ByteArray? {
46-
return with(metadataFile) {
47-
if (this == null || !existsSafe(internalLogger)) {
48-
null
49-
} else {
50-
metadataReaderWriter.readData(this)
51-
}
52-
}
53-
}
54-
5530
@WorkerThread
5631
override fun write(
5732
event: RawBatchEvent,
5833
batchMetadata: ByteArray?,
5934
eventType: EventType
6035
): Boolean {
61-
val (batchFile, metadataFile) = batchFile to metadataFile
36+
// prevent useless operation for empty event
37+
if (event.data.isEmpty()) {
38+
return true
39+
}
40+
if (!checkEventSize(event.data.size)) {
41+
return false
42+
}
43+
44+
// Serialize once (TLV-wrapped, encrypted if configured) so the exact on-disk size is known
45+
// before asking the orchestrator for a file with enough room to hold it.
46+
val serializedEvent = eventsWriter.serializeToBytes(event) ?: return false
47+
48+
val batchFile = fileOrchestrator.getWritableFile(serializedEvent.size.toLong())
6249
if (batchFile == null) {
6350
internalLogger.log(
6451
InternalLogger.Level.ERROR,
@@ -68,12 +55,9 @@ internal class FileEventBatchWriter(
6855
return false
6956
}
7057

71-
// prevent useless operation for empty event
72-
return if (event.data.isEmpty()) {
73-
true
74-
} else if (!checkEventSize(event.data.size)) {
75-
false
76-
} else if (eventsWriter.writeData(batchFile, event, true)) {
58+
val metadataFile = fileOrchestrator.getMetadataFile(batchFile)
59+
60+
return if (eventsWriter.writeBinaryData(batchFile, serializedEvent, true)) {
7761
batchWriteEventListener.onWriteEvent(event.data.size.toLong())
7862
if (batchMetadata?.isNotEmpty() == true && metadataFile != null) {
7963
writeBatchMetadata(metadataFile, batchMetadata)

dd-sdk-android-core/src/main/kotlin/com/datadog/android/core/internal/persistence/NoOpEventBatchWriter.kt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,6 @@ import com.datadog.android.api.storage.RawBatchEvent
1212

1313
internal class NoOpEventBatchWriter : EventBatchWriter {
1414

15-
override fun currentMetadata(): ByteArray? {
16-
return null
17-
}
18-
1915
override fun write(
2016
event: RawBatchEvent,
2117
batchMetadata: ByteArray?,

dd-sdk-android-core/src/main/kotlin/com/datadog/android/core/internal/persistence/file/FileOrchestrator.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,14 @@ import java.io.File
2121
internal interface FileOrchestrator {
2222

2323
/**
24+
* @param eventSize the size (in bytes) of the event about to be written, used to decide
25+
* whether an existing batch file has enough room to accommodate it without exceeding the
26+
* maximum batch size.
2427
* @return a File with enough space to write data, or null if no space is available
2528
* or the disk can't be written to.
2629
*/
2730
@WorkerThread
28-
fun getWritableFile(): File?
31+
fun getWritableFile(eventSize: Long): File?
2932

3033
/**
3134
* @param excludeFiles a set of files to exclude from the readable files

dd-sdk-android-core/src/main/kotlin/com/datadog/android/core/internal/persistence/file/advanced/ConsentAwareFileOrchestrator.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ internal open class ConsentAwareFileOrchestrator(
3939
// region FileOrchestrator
4040

4141
@WorkerThread
42-
override fun getWritableFile(): File? {
43-
return delegateOrchestrator.getWritableFile()
42+
override fun getWritableFile(eventSize: Long): File? {
43+
return delegateOrchestrator.getWritableFile(eventSize)
4444
}
4545

4646
@WorkerThread

dd-sdk-android-core/src/main/kotlin/com/datadog/android/core/internal/persistence/file/batch/BatchFileOrchestrator.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ internal class BatchFileOrchestrator(
5757
// region FileOrchestrator
5858

5959
@WorkerThread
60-
override fun getWritableFile(): File? {
60+
override fun getWritableFile(eventSize: Long): File? {
6161
if (!isRootDirValid()) {
6262
return null
6363
}
@@ -69,7 +69,7 @@ internal class BatchFileOrchestrator(
6969
lastCleanupTimestamp = timeProvider.getDeviceTimestampMillis()
7070
}
7171

72-
return getReusableWritableFile() ?: createNewFile()
72+
return getReusableWritableFile(eventSize) ?: createNewFile()
7373
}
7474

7575
@WorkerThread
@@ -221,7 +221,7 @@ internal class BatchFileOrchestrator(
221221
}
222222

223223
@Suppress("ReturnCount")
224-
private fun getReusableWritableFile(): File? {
224+
private fun getReusableWritableFile(eventSize: Long): File? {
225225
val files = listBatchFiles()
226226
val lastFile = files.latestBatchFile ?: return null
227227

@@ -237,7 +237,7 @@ internal class BatchFileOrchestrator(
237237
}
238238

239239
val isRecentEnough = isFileRecent(lastFile, recentWriteDelayMs)
240-
val hasRoomForMore = lastFile.lengthSafe(internalLogger) < config.maxBatchSize - config.maxItemSize
240+
val hasRoomForMore = lastFile.lengthSafe(internalLogger) + eventSize <= config.maxBatchSize
241241
val hasSlotForMore = (lastKnownFileItemCount < config.maxItemsPerBatch)
242242

243243
return if (isRecentEnough && hasRoomForMore && hasSlotForMore) {

0 commit comments

Comments
 (0)