Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract jacodb-storage module #271

Merged
merged 1 commit into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 27 additions & 12 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import org.jetbrains.dokka.gradle.DokkaTaskPartial
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

val semVer: String? by project
val includeDokka: String? by project
Expand All @@ -26,6 +25,9 @@ allprojects {

apply {
plugin("kotlin")
plugin("java")
plugin("java-library")
plugin("java-test-fixtures")
plugin("org.jetbrains.kotlin.plugin.allopen")
plugin(Plugins.Dokka.id)
plugin(Plugins.Licenser.id)
Expand Down Expand Up @@ -56,32 +58,45 @@ allprojects {
testRuntimeOnly(Libs.guava)
}

kotlin {
compilerOptions {
freeCompilerArgs.add("-Xsam-conversions=class")
freeCompilerArgs.add("-Xcontext-receivers")
freeCompilerArgs.add("-Xjvm-default=all")
allWarningsAsErrors = false
}
}

tasks {
withType<JavaCompile> {
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
options.encoding = "UTF-8"
options.compilerArgs.add("-Xlint:all")
}

withType<KotlinCompile> {
compileJava {
targetCompatibility = "1.8"
}
compileKotlin {
kotlinOptions {
jvmTarget = "1.8"
freeCompilerArgs += "-Xallow-result-return-type"
freeCompilerArgs += "-Xsam-conversions=class"
freeCompilerArgs += "-Xcontext-receivers"
freeCompilerArgs += "-Xjvm-default=all"
allWarningsAsErrors = false
}
}

compileTestJava {
targetCompatibility = runtimeJavaVersion()
}
compileTestFixturesJava {
targetCompatibility = "1.8"
}
compileTestKotlin {
kotlinOptions {
jvmTarget = runtimeJavaVersion()
}
}
compileTestFixturesKotlin {
kotlinOptions {
jvmTarget = "1.8"
freeCompilerArgs += "-Xallow-result-return-type"
freeCompilerArgs += "-Xsam-conversions=class"
freeCompilerArgs += "-Xcontext-receivers"
allWarningsAsErrors = false
}
}

Expand Down
12 changes: 6 additions & 6 deletions buildSrc/src/main/kotlin/Dependencies.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ object Versions {
const val jooq = "3.14.16"
const val juliet = "1.3.2"
const val junit = "5.9.2"
const val kotlin = "1.9.25"
const val kotlin = "2.0.20"
const val kotlin_logging = "1.8.3"
const val kotlinx_benchmark = "0.4.6"
const val kotlinx_cli = "0.3.5"
const val kotlinx_collections_immutable = "0.3.5"
const val kotlinx_coroutines = "1.6.4"
const val kotlinx_metadata = "0.9.0"
const val kotlin_metadata = kotlin
const val kotlinx_serialization = "1.4.1"
const val licenser = "0.6.1"
const val mockk = "1.13.3"
Expand Down Expand Up @@ -114,10 +114,10 @@ object Libs {
version = Versions.kotlinx_collections_immutable
)

val kotlinx_metadata_jvm = dep(
group = "org.jetbrains.kotlinx",
name = "kotlinx-metadata-jvm",
version = Versions.kotlinx_metadata
val kotlin_metadata_jvm = dep(
group = "org.jetbrains.kotlin",
name = "kotlin-metadata-jvm",
version = Versions.kotlin_metadata
)

val javax_activation = dep(
Expand Down
4 changes: 3 additions & 1 deletion buildSrc/src/main/kotlin/Tests.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import org.gradle.api.tasks.TaskProvider
import org.gradle.api.tasks.testing.Test
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
import java.util.StringTokenizer
import java.util.*

object Tests {
val lifecycleTag = "lifecycle"
Expand All @@ -26,3 +26,5 @@ fun Test.setup(jacocoTestReport: TaskProvider<*>) {
)
}
}

fun Any.runtimeJavaVersion(): String = System.getProperty("java.specification.version")
1 change: 1 addition & 0 deletions jacodb-analysis/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ dependencies {

testImplementation(project(":jacodb-api-jvm"))
testImplementation(testFixtures(project(":jacodb-core")))
testImplementation(testFixtures(project(":jacodb-storage")))
testImplementation(kotlin("test"))
testImplementation(Libs.mockk)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ private fun <NODE, T> FlowEntry<NODE, T>.visitEntry(
}

private fun <NODE, T> NODE.toEntry(
pred: FlowEntry<NODE, T>?,
pred: FlowEntry<NODE, T>,
visited: MutableMap<NODE, FlowEntry<NODE, T>>,
): FlowEntry<NODE, T> {
// either we reach a new node or a merge node, the latter one is rare
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ import org.jacodb.api.jvm.cfg.JcNewArrayExpr
import org.jacodb.api.jvm.cfg.JcNullConstant
import org.jacodb.api.jvm.cfg.JcReturnInst
import org.jacodb.api.jvm.ext.findType
import org.jacodb.api.jvm.ext.isNullable
import org.jacodb.impl.bytecode.isNullable
import org.jacodb.taint.configuration.AssignMark
import org.jacodb.taint.configuration.CopyAllMarks
import org.jacodb.taint.configuration.CopyMark
Expand Down
1 change: 1 addition & 0 deletions jacodb-api-jvm/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
dependencies {
api(project(":jacodb-api-common"))
api(project(":jacodb-api-storage"))

api(Libs.asm)
api(Libs.asm_tree)
Expand Down
25 changes: 21 additions & 4 deletions jacodb-api-jvm/src/main/kotlin/org/jacodb/api/jvm/Api.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ package org.jacodb.api.jvm

import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.future.future
import org.jacodb.api.jvm.storage.ers.EntityRelationshipStorage
import org.jacodb.api.jvm.storage.ers.Transaction
import org.jacodb.api.storage.ers.EntityRelationshipStorage
import org.jacodb.api.storage.ers.Transaction
import org.jooq.DSLContext
import java.io.Closeable
import java.io.File
Expand Down Expand Up @@ -79,8 +79,6 @@ interface JcDatabase : Closeable {
fun asyncClasspath(dirOrJars: List<File>, features: List<JcClasspathFeature>?) =
GlobalScope.future { classpath(dirOrJars, features) }

fun classpathOf(locations: List<RegisteredLocation>, features: List<JcClasspathFeature>?): JcClasspath

/**
* process and index single byte-code resource
* @param dirOrJar build folder or jar file
Expand Down Expand Up @@ -135,6 +133,17 @@ interface JcDatabase : Closeable {
suspend fun awaitBackgroundJobs()
fun asyncAwaitBackgroundJobs() = GlobalScope.future { awaitBackgroundJobs() }

/**
* Sets this database's internal state to immutable if corresponding backend supports this operation.
* If it does, any write operation is no longer possible.
* The method can be used in order to "fix" current snapshot of the model.
* Generally, there is no way to switch the database back to mutable.
*/
suspend fun setImmutable() {
awaitBackgroundJobs()
persistence.setImmutable()
}

fun isInstalled(feature: JcFeature<*, *>): Boolean = features.contains(feature)

val features: List<JcFeature<*, *>>
Expand Down Expand Up @@ -165,6 +174,14 @@ interface JcDatabasePersistence : Closeable {
fun findClassSources(cp: JcClasspath, fullName: String): List<ClassSource>

fun createIndexes() {}

/**
* Sets this persistence's internal state to immutable if corresponding backend supports this operation.
* If it does, any write operation is no longer possible.
* The method can be used in order to "fix" current snapshot of the model.
* Generally, there is no way to switch the persistence back to mutable.
*/
fun setImmutable() {}
}

/**
Expand Down
4 changes: 4 additions & 0 deletions jacodb-api-storage/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
dependencies {
api(project(":jacodb-api-common"))
api(Libs.kotlinx_collections_immutable)
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package org.jacodb.api.jvm.spi
package org.jacodb.api.spi

interface CommonSPI {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package org.jacodb.api.jvm.spi
package org.jacodb.api.spi

import java.lang.ref.SoftReference
import java.util.*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package org.jacodb.api.jvm.storage
package org.jacodb.api.storage

import kotlin.math.min

Expand All @@ -36,4 +36,6 @@ class ByteArrayKey(val bytes: ByteArray) : Comparable<ByteArrayKey> {

override fun hashCode(): Int = bytes.contentHashCode()
override fun toString(): String = bytes.contentToString()
}
}

fun ByteArray.asComparable() = ByteArrayKey(this)
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package org.jacodb.api.jvm.storage.ers
package org.jacodb.api.storage.ers

interface Binding<T : Any> {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package org.jacodb.api.jvm.storage.ers
package org.jacodb.api.storage.ers

interface BindingProvider {
fun <T : Any> getBinding(clazz: Class<T>): Binding<T>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package org.jacodb.api.jvm.storage.ers
package org.jacodb.api.storage.ers

abstract class Entity : Comparable<Entity> {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package org.jacodb.api.jvm.storage.ers
package org.jacodb.api.storage.ers

import kotlin.reflect.KProperty

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package org.jacodb.api.jvm.storage.ers
package org.jacodb.api.storage.ers

interface EntityIterable : Sequence<Entity> {

Expand Down Expand Up @@ -84,9 +84,7 @@ class EntityIdCollectionEntityIterable(

override fun contains(e: Entity) = e.id in set

override fun iterator() = buildList {
set.forEach { id -> txn.getEntityOrNull(id)?.let { e -> add(e) } }
}.iterator()
override fun iterator() = set.mapNotNullTo(ArrayList(set.size)) { id -> txn.getEntityOrNull(id) }.iterator()
}

class InstanceIdCollectionEntityIterable(
Expand All @@ -101,7 +99,74 @@ class InstanceIdCollectionEntityIterable(

override fun contains(e: Entity) = e.id.typeId == typeId && e.id.instanceId in set

override fun iterator() = buildList {
set.forEach { instanceId -> txn.getEntityOrNull(EntityId(typeId, instanceId))?.let { e -> add(e) } }
}.iterator()
override fun iterator() =
set.mapNotNullTo(ArrayList(set.size)) { instanceId -> txn.getEntityOrNull(EntityId(typeId, instanceId)) }
.iterator()
}

typealias EntityIdPredicate = (EntityId) -> Boolean
typealias InstanceIdPredicate = (Long) -> Boolean

private class FilterEntityIdEntityIterable(
private val decorated: EntityIterable,
private val predicate: EntityIdPredicate
) : EntityIterable {

override fun iterator(): Iterator<Entity> = Sequence<Entity> {
decorated.iterator()
}.filter { predicate(it.id) }.iterator()
}

private class FilterInstanceIdEntityIterable(
private val decorated: EntityIterable,
private val predicate: InstanceIdPredicate
) : EntityIterable {

override fun iterator(): Iterator<Entity> = Sequence<Entity> {
decorated.iterator()
}.filter { predicate(it.id.instanceId) }.iterator()
}

fun EntityIterable.filterEntityIds(predicate: EntityIdPredicate): EntityIterable {
return FilterEntityIdEntityIterable(this, predicate)
}

fun EntityIterable.filterInstanceIds(predicate: InstanceIdPredicate): EntityIterable {
return FilterInstanceIdEntityIterable(this, predicate)
}

/**
* Iterates entities with instance ids from `LongRange`.
* The range is expected to have step 1.
*/
private class LongRangeEntityIterable(
private val txn: Transaction,
private val typeId: Int,
private val range: LongRange,
private val filterIdPredicate: InstanceIdPredicate? = null
) : EntityIterable {

override val size = if (filterIdPredicate == null) range.last - range.start + 1 else super.size

override fun contains(e: Entity) =
if (filterIdPredicate == null) e.id.typeId == typeId && e.id.instanceId in range else super.contains(e)

override fun iterator(): Iterator<Entity> {
var result = range.asSequence()
filterIdPredicate?.let { result = result.filter(it) }
return result.map { txn.getEntityUnsafe(EntityId(typeId, it)) }.iterator()
}
}

fun Any.longRangeIterable(
txn: Transaction,
typeId: Int,
range: LongRange,
filterIdPredicate: InstanceIdPredicate? = null
): EntityIterable {
return LongRangeEntityIterable(txn, typeId, range, filterIdPredicate)
}

inline fun EntityIterable(crossinline iterator: () -> Iterator<Entity>): EntityIterable = object : EntityIterable {
override fun iterator(): Iterator<Entity> = iterator()
}
Loading
Loading