diff --git a/src/main/kotlin/mdnet/base/Main.kt b/src/main/kotlin/mdnet/base/Main.kt index 9c1af90..7b1a5b2 100644 --- a/src/main/kotlin/mdnet/base/Main.kt +++ b/src/main/kotlin/mdnet/base/Main.kt @@ -129,6 +129,10 @@ object Main { dieWithError("Config Error: Invalid UI port number") } } + if (settings.experimental != null) { + if (settings.experimental.maxBufferSizeForCacheHit < 0) + dieWithError("Config Error: Max cache buffer multiple must be >= 0") + } } private const val CLIENT_KEY_LENGTH = 52 diff --git a/src/main/kotlin/mdnet/base/server/Application.kt b/src/main/kotlin/mdnet/base/server/Application.kt index 456128f..09b5748 100644 --- a/src/main/kotlin/mdnet/base/server/Application.kt +++ b/src/main/kotlin/mdnet/base/server/Application.kt @@ -63,7 +63,7 @@ fun getServer(cache: DiskLruCache, serverSettings: ServerSettings, clientSetting .setMaxConnPerRoute(3000) .build()) - val imageServer = ImageServer(cache, database, statistics, serverSettings, client) + val imageServer = ImageServer(cache, database, statistics, serverSettings, clientSettings, client) return timeRequest() .then(catchAllHideDetails()) diff --git a/src/main/kotlin/mdnet/base/server/ImageServer.kt b/src/main/kotlin/mdnet/base/server/ImageServer.kt index aebc2aa..3ab7d10 100644 --- a/src/main/kotlin/mdnet/base/server/ImageServer.kt +++ b/src/main/kotlin/mdnet/base/server/ImageServer.kt @@ -48,6 +48,7 @@ import mdnet.base.data.ImageDatum import mdnet.base.data.Statistics import mdnet.base.data.Token import mdnet.base.info +import mdnet.base.settings.ClientSettings import mdnet.base.settings.ServerSettings import mdnet.base.trace import mdnet.base.warn @@ -66,6 +67,7 @@ class ImageServer( private val database: Database, private val statistics: AtomicReference, private val serverSettings: ServerSettings, + private val clientSettings: ClientSettings, private val client: HttpHandler ) { init { @@ -74,6 +76,9 @@ class ImageServer( } } private val executor = Executors.newCachedThreadPool() + private val maxBufferSizeForCacheHit: Int? = clientSettings.experimental?.maxBufferSizeForCacheHit + ?.takeUnless { it == 0 } + ?.times(8 * 1024) fun handler(dataSaver: Boolean, tokenized: Boolean = false): HttpHandler { val sodium = LazySodiumJava(SodiumJava()) @@ -189,11 +194,16 @@ class ImageServer( } LOGGER.info { "Request for $sanitizedUri hit cache" } + val cacheStream = snapshot.getInputStream(0) + val bufferSize = maxBufferSizeForCacheHit?.coerceAtMost(snapshot.getLength(0).toInt()) + val bufferedStream = bufferSize?.let { + BufferedInputStream(cacheStream, bufferSize) + } ?: BufferedInputStream(cacheStream) // Todo: Move into builder. It's untidy having the null propagate all the way here but I'm tired and tomorrow is a fast day. respondWithImage( - CipherInputStream(BufferedInputStream(snapshot.getInputStream(0)), cipher), - snapshot.getLength(0).toString(), imageDatum.contentType, imageDatum.lastModified, - true + CipherInputStream(bufferedStream, cipher), + snapshot.getLength(0).toString(), imageDatum.contentType, imageDatum.lastModified, + true ) } } diff --git a/src/main/kotlin/mdnet/base/settings/ClientSettings.kt b/src/main/kotlin/mdnet/base/settings/ClientSettings.kt index f9254be..3798085 100644 --- a/src/main/kotlin/mdnet/base/settings/ClientSettings.kt +++ b/src/main/kotlin/mdnet/base/settings/ClientSettings.kt @@ -35,7 +35,8 @@ data class ClientSettings( val threads: Int = 4, val gracefulShutdownWaitSeconds: Int = 60, val webSettings: WebSettings? = null, - val devSettings: DevSettings? = null + val devSettings: DevSettings? = null, + val experimental: Experimental? = null ) @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy::class) @@ -48,3 +49,8 @@ data class WebSettings( data class DevSettings( val isDev: Boolean = false ) + +@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy::class) +data class Experimental( + val maxBufferSizeForCacheHit: Int = 0 +)