1 /* 2 * Copyright 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.room.coroutines 18 19 import androidx.room.Transactor 20 import androidx.sqlite.SQLiteConnection 21 import androidx.sqlite.SQLiteDriver 22 import androidx.sqlite.SQLiteException 23 24 /** 25 * A container that manages [SQLiteConnection]s. 26 * 27 * Connection pools provides the means of bounding and managing the resources that are database 28 * connections. They provide safe usage of connections in a multi-threaded application and usually 29 * provide improved performance when performing asynchronous and concurrent database interactions. 30 * 31 * An implementation instance can be created via the factory function [newConnectionPool] and 32 * [newSingleConnectionPool]. 33 */ 34 internal interface ConnectionPool : AutoCloseable { 35 36 /** 37 * Acquires a connection, suspending while waiting if none is available and then calling the 38 * [block] to use the connection once it is acquired. The connection to use in the [block] is an 39 * instance of [Transactor] that provides the capabilities for performing nested transactions. 40 * 41 * Using the connection after [block] completes is prohibited. 42 * 43 * The connection will be confined to the coroutine on which [block] executes, attempting to use 44 * the connection from a different coroutine will result in an error. 45 * 46 * If the current coroutine calling this function already has a confined connection, then that 47 * connection is used as long as it isn't required to be upgraded to a writer. If an upgrade is 48 * required then a [SQLiteException] is thrown. 49 * 50 * If a caller has to wait too long to acquire a connection a [SQLiteException] will be thrown 51 * due to a timeout. 52 * 53 * @param isReadOnly Whether to use a reader or a writer connection. 54 * @param block The code to use the connection. 55 * @throws SQLiteException when the pool is closed or a thread confined connection needs to be 56 * upgraded or there is a timeout acquiring a connection. 57 */ useConnectionnull58 suspend fun <R> useConnection(isReadOnly: Boolean, block: suspend (Transactor) -> R): R 59 60 /** 61 * Closes the pool and any opened connections, attempting to use connections is an error once 62 * the pool is closed. 63 */ 64 override fun close() 65 66 /** Internal exception thrown to rollback a transaction. */ 67 class RollbackException(val result: Any?) : Throwable() 68 } 69 70 /** 71 * Creates a new [ConnectionPool] with a single connection. 72 * 73 * A pool containing a single connection that is used for both reading and writing is useful for 74 * in-memory databases whose schema and data are isolated to a database connection. 75 * 76 * @param driver The driver from which to request the connection to be opened. 77 * @param fileName The database file name. 78 * @return The newly created connection pool 79 * @see newConnectionPool 80 */ 81 internal fun newSingleConnectionPool(driver: SQLiteDriver, fileName: String): ConnectionPool = 82 ConnectionPoolImpl(driver, fileName) 83 84 /** 85 * Creates a new [ConnectionPool] with multiple connections separated by readers and writers. 86 * 87 * If the database journal mode is Write-Ahead Logging (WAL) then it is recommended to create a pool 88 * of one writer and multiple readers. If the database journal mode is not WAL (e.g. TRUNCATE, 89 * DELETE or PERSIST) then a single connection pool is recommended. 90 * 91 * @param driver The driver from which to request new connections to be opened. 92 * @param fileName The database file name. 93 * @param maxNumOfReaders The maximum number of connections to be opened and used as readers. 94 * @param maxNumOfWriters The maximum number of connections to be opened and used as writers. 95 * @return The newly created connection pool 96 * @see newSingleConnectionPool 97 */ 98 internal fun newConnectionPool( 99 driver: SQLiteDriver, 100 fileName: String, 101 maxNumOfReaders: Int, 102 maxNumOfWriters: Int 103 ): ConnectionPool = ConnectionPoolImpl(driver, fileName, maxNumOfReaders, maxNumOfWriters) 104 105 /** Defines an object that provides 'raw' access to a connection. */ 106 internal interface RawConnectionAccessor { 107 val rawConnection: SQLiteConnection 108 } 109