summaryrefslogtreecommitdiff
path: root/src/main/kotlin/io/dico/parcels2/storage
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/kotlin/io/dico/parcels2/storage')
-rw-r--r--src/main/kotlin/io/dico/parcels2/storage/Backing.kt12
-rw-r--r--src/main/kotlin/io/dico/parcels2/storage/Storage.kt27
-rw-r--r--src/main/kotlin/io/dico/parcels2/storage/exposed/ExposedBacking.kt57
-rw-r--r--src/main/kotlin/io/dico/parcels2/storage/exposed/IdTables.kt2
-rw-r--r--src/main/kotlin/io/dico/parcels2/storage/exposed/ListTables.kt42
-rw-r--r--src/main/kotlin/io/dico/parcels2/storage/migration/plotme/PlotmeMigration.kt8
6 files changed, 75 insertions, 73 deletions
diff --git a/src/main/kotlin/io/dico/parcels2/storage/Backing.kt b/src/main/kotlin/io/dico/parcels2/storage/Backing.kt
index 6c91714..69c5b62 100644
--- a/src/main/kotlin/io/dico/parcels2/storage/Backing.kt
+++ b/src/main/kotlin/io/dico/parcels2/storage/Backing.kt
@@ -1,13 +1,13 @@
package io.dico.parcels2.storage
import io.dico.parcels2.*
-import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Job
import kotlinx.coroutines.channels.ReceiveChannel
import kotlinx.coroutines.channels.SendChannel
import org.joda.time.DateTime
import java.util.UUID
+import kotlin.coroutines.CoroutineContext
interface Backing {
@@ -15,7 +15,7 @@ interface Backing {
val isConnected: Boolean
- val dispatcher: CoroutineDispatcher
+ val coroutineContext: CoroutineContext
fun launchJob(job: Backing.() -> Unit): Job
@@ -56,9 +56,9 @@ interface Backing {
fun setParcelOwnerSignOutdated(parcel: ParcelId, outdated: Boolean)
- fun setLocalPlayerStatus(parcel: ParcelId, player: PlayerProfile, status: AddedStatus)
+ fun setLocalPrivilege(parcel: ParcelId, player: PlayerProfile, status: Privilege)
- fun setParcelOptionsInteractBitmask(parcel: ParcelId, bitmask: IntArray?)
+ fun setParcelOptionsInteractConfig(parcel: ParcelId, config: InteractableConfiguration)
/*
fun setParcelAllowsInteractInventory(parcel: ParcelId, value: Boolean)
@@ -67,7 +67,7 @@ interface Backing {
fun transmitAllGlobalAddedData(channel: SendChannel<AddedDataPair<PlayerProfile>>)
- fun readGlobalAddedData(owner: PlayerProfile): MutableAddedDataMap
+ fun readGlobalPrivileges(owner: PlayerProfile): MutablePrivilegeMap
- fun setGlobalPlayerStatus(owner: PlayerProfile, player: PlayerProfile, status: AddedStatus)
+ fun setGlobalPrivilege(owner: PlayerProfile, player: PlayerProfile, status: Privilege)
}
diff --git a/src/main/kotlin/io/dico/parcels2/storage/Storage.kt b/src/main/kotlin/io/dico/parcels2/storage/Storage.kt
index c9c0d4a..fa63496 100644
--- a/src/main/kotlin/io/dico/parcels2/storage/Storage.kt
+++ b/src/main/kotlin/io/dico/parcels2/storage/Storage.kt
@@ -3,6 +3,7 @@
package io.dico.parcels2.storage
import io.dico.parcels2.*
+import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Job
import kotlinx.coroutines.channels.ReceiveChannel
@@ -10,9 +11,10 @@ import kotlinx.coroutines.channels.SendChannel
import kotlinx.coroutines.launch
import org.joda.time.DateTime
import java.util.UUID
+import kotlin.coroutines.CoroutineContext
typealias DataPair = Pair<ParcelId, ParcelData?>
-typealias AddedDataPair<TAttach> = Pair<TAttach, MutableAddedDataMap>
+typealias AddedDataPair<TAttach> = Pair<TAttach, MutablePrivilegeMap>
interface Storage {
val name: String
@@ -48,28 +50,29 @@ interface Storage {
fun setParcelOwnerSignOutdated(parcel: ParcelId, outdated: Boolean): Job
- fun setParcelPlayerStatus(parcel: ParcelId, player: PlayerProfile, status: AddedStatus): Job
+ fun setLocalPrivilege(parcel: ParcelId, player: PlayerProfile, privilege: Privilege): Job
- fun setParcelOptionsInteractBitmask(parcel: ParcelId, bitmask: IntArray): Job
+ fun setParcelOptionsInteractConfig(parcel: ParcelId, config: InteractableConfiguration): Job
fun transmitAllGlobalAddedData(): ReceiveChannel<AddedDataPair<PlayerProfile>>
- fun readGlobalAddedData(owner: PlayerProfile): Deferred<MutableAddedDataMap?>
+ fun readGlobalPrivileges(owner: PlayerProfile): Deferred<MutablePrivilegeMap?>
- fun setGlobalAddedStatus(owner: PlayerProfile, player: PlayerProfile, status: AddedStatus): Job
+ fun setGlobalPrivilege(owner: PlayerProfile, player: PlayerProfile, status: Privilege): Job
fun getChannelToUpdateParcelData(): SendChannel<Pair<ParcelId, ParcelData>>
}
-class BackedStorage internal constructor(val b: Backing) : Storage {
+class BackedStorage internal constructor(val b: Backing) : Storage, CoroutineScope {
override val name get() = b.name
override val isConnected get() = b.isConnected
+ override val coroutineContext: CoroutineContext get() = b.coroutineContext
- override fun init() = launch(b.dispatcher) { b.init() }
+ override fun init() = launch { b.init() }
- override fun shutdown() = launch(b.dispatcher) { b.shutdown() }
+ override fun shutdown() = launch { b.shutdown() }
override fun getWorldCreationTime(worldId: ParcelWorldId): Deferred<DateTime?> = b.launchFuture { b.getWorldCreationTime(worldId) }
@@ -96,16 +99,16 @@ class BackedStorage internal constructor(val b: Backing) : Storage {
override fun setParcelOwnerSignOutdated(parcel: ParcelId, outdated: Boolean): Job = b.launchJob { b.setParcelOwnerSignOutdated(parcel, outdated) }
- override fun setParcelPlayerStatus(parcel: ParcelId, player: PlayerProfile, status: AddedStatus) = b.launchJob { b.setLocalPlayerStatus(parcel, player, status) }
+ override fun setLocalPrivilege(parcel: ParcelId, player: PlayerProfile, privilege: Privilege) = b.launchJob { b.setLocalPrivilege(parcel, player, privilege) }
- override fun setParcelOptionsInteractBitmask(parcel: ParcelId, bitmask: IntArray) = b.launchJob { b.setParcelOptionsInteractBitmask(parcel, bitmask) }
+ override fun setParcelOptionsInteractConfig(parcel: ParcelId, config: InteractableConfiguration) = b.launchJob { b.setParcelOptionsInteractConfig(parcel, config) }
override fun transmitAllGlobalAddedData(): ReceiveChannel<AddedDataPair<PlayerProfile>> = b.openChannel { b.transmitAllGlobalAddedData(it) }
- override fun readGlobalAddedData(owner: PlayerProfile): Deferred<MutableAddedDataMap?> = b.launchFuture { b.readGlobalAddedData(owner) }
+ override fun readGlobalPrivileges(owner: PlayerProfile): Deferred<MutablePrivilegeMap?> = b.launchFuture { b.readGlobalPrivileges(owner) }
- override fun setGlobalAddedStatus(owner: PlayerProfile, player: PlayerProfile, status: AddedStatus) = b.launchJob { b.setGlobalPlayerStatus(owner, player, status) }
+ override fun setGlobalPrivilege(owner: PlayerProfile, player: PlayerProfile, status: Privilege) = b.launchJob { b.setGlobalPrivilege(owner, player, status) }
override fun getChannelToUpdateParcelData(): SendChannel<Pair<ParcelId, ParcelData>> = b.openChannelForWriting { b.setParcelData(it.first, it.second) }
}
diff --git a/src/main/kotlin/io/dico/parcels2/storage/exposed/ExposedBacking.kt b/src/main/kotlin/io/dico/parcels2/storage/exposed/ExposedBacking.kt
index b7f9f82..4c88c11 100644
--- a/src/main/kotlin/io/dico/parcels2/storage/exposed/ExposedBacking.kt
+++ b/src/main/kotlin/io/dico/parcels2/storage/exposed/ExposedBacking.kt
@@ -23,17 +23,16 @@ import javax.sql.DataSource
class ExposedDatabaseException(message: String? = null) : Exception(message)
-class ExposedBacking(private val dataSourceFactory: () -> DataSource, val poolSize: Int) : Backing {
+class ExposedBacking(private val dataSourceFactory: () -> DataSource, val poolSize: Int) : Backing, CoroutineScope {
override val name get() = "Exposed"
- override val dispatcher: ThreadPoolDispatcher = newFixedThreadPoolContext(poolSize, "Parcels StorageThread")
-
+ override val coroutineContext = Job() + newFixedThreadPoolContext(poolSize, "Parcels StorageThread")
private var dataSource: DataSource? = null
private var database: Database? = null
private var isShutdown: Boolean = false
override val isConnected get() = database != null
- override fun launchJob(job: Backing.() -> Unit): Job = launch(dispatcher) { transaction { job() } }
- override fun <T> launchFuture(future: Backing.() -> T): Deferred<T> = async(dispatcher) { transaction { future() } }
+ override fun launchJob(job: Backing.() -> Unit): Job = launch { transaction { job() } }
+ override fun <T> launchFuture(future: Backing.() -> T): Deferred<T> = async { transaction { future() } }
override fun <T> openChannel(future: Backing.(SendChannel<T>) -> Unit): ReceiveChannel<T> {
val channel = LinkedListChannel<T>()
@@ -44,8 +43,8 @@ class ExposedBacking(private val dataSourceFactory: () -> DataSource, val poolSi
override fun <T> openChannelForWriting(action: Backing.(T) -> Unit): SendChannel<T> {
val channel = ArrayChannel<T>(poolSize * 2)
- repeat(poolSize) {
- launch(dispatcher) {
+ repeat(poolSize.clampMax(3)) {
+ launch {
try {
while (true) {
action(channel.receive())
@@ -75,7 +74,7 @@ class ExposedBacking(private val dataSourceFactory: () -> DataSource, val poolSi
dataSource = dataSourceFactory()
database = Database.connect(dataSource!!)
transaction(database!!) {
- create(WorldsT, ProfilesT, ParcelsT, ParcelOptionsT, AddedLocalT, AddedGlobalT)
+ create(WorldsT, ProfilesT, ParcelsT, ParcelOptionsT, PrivilegesLocalT, PrivilegesGlobalT)
}
}
}
@@ -83,11 +82,12 @@ class ExposedBacking(private val dataSourceFactory: () -> DataSource, val poolSi
override fun shutdown() {
synchronized {
if (isShutdown) throw IllegalStateException()
+ isShutdown = true
+ coroutineContext[Job]!!.cancel(CancellationException("ExposedBacking shutdown"))
dataSource?.let {
(it as? HikariDataSource)?.close()
}
database = null
- isShutdown = true
}
}
@@ -173,7 +173,7 @@ class ExposedBacking(private val dataSourceFactory: () -> DataSource, val poolSi
// Below should cascade automatically
/*
- AddedLocalT.deleteIgnoreWhere { AddedLocalT.parcel_id eq id }
+ PrivilegesLocalT.deleteIgnoreWhere { PrivilegesLocalT.parcel_id eq id }
ParcelOptionsT.deleteIgnoreWhere(limit = 1) { ParcelOptionsT.parcel_id eq id }
*/
}
@@ -184,18 +184,16 @@ class ExposedBacking(private val dataSourceFactory: () -> DataSource, val poolSi
transaction {
val id = ParcelsT.getOrInitId(parcel)
- AddedLocalT.deleteIgnoreWhere { AddedLocalT.attach_id eq id }
+ PrivilegesLocalT.deleteIgnoreWhere { PrivilegesLocalT.attach_id eq id }
}
setParcelOwner(parcel, data.owner)
- for ((profile, status) in data.addedMap) {
- AddedLocalT.setPlayerStatus(parcel, profile, status)
+ for ((profile, privilege) in data.map) {
+ PrivilegesLocalT.setPrivilege(parcel, profile, privilege)
}
- val bitmaskArray = (data.interactableConfig as? BitmaskInteractableConfiguration ?: return).bitmaskArray
- val isAllZero = bitmaskArray.fold(false) { cur, elem -> cur || elem != 0 }
- setParcelOptionsInteractBitmask(parcel, if (isAllZero) null else bitmaskArray)
+ setParcelOptionsInteractConfig(parcel, data.interactableConfig)
}
override fun setParcelOwner(parcel: ParcelId, owner: PlayerProfile?) {
@@ -221,19 +219,22 @@ class ExposedBacking(private val dataSourceFactory: () -> DataSource, val poolSi
}
}
- override fun setLocalPlayerStatus(parcel: ParcelId, player: PlayerProfile, status: AddedStatus) {
- AddedLocalT.setPlayerStatus(parcel, player.toRealProfile(), status)
+ override fun setLocalPrivilege(parcel: ParcelId, player: PlayerProfile, privilege: Privilege) {
+ PrivilegesLocalT.setPrivilege(parcel, player.toRealProfile(), privilege)
}
- override fun setParcelOptionsInteractBitmask(parcel: ParcelId, bitmask: IntArray?) {
- if (bitmask == null) {
+ override fun setParcelOptionsInteractConfig(parcel: ParcelId, config: InteractableConfiguration) {
+ val bitmaskArray = (config as? BitmaskInteractableConfiguration ?: return).bitmaskArray
+ val isAllZero = !bitmaskArray.fold(false) { cur, elem -> cur || elem != 0 }
+
+ if (isAllZero) {
val id = ParcelsT.getId(parcel) ?: return
ParcelOptionsT.deleteWhere { ParcelOptionsT.parcel_id eq id }
return
}
- if (bitmask.size != 1) throw IllegalArgumentException()
- val array = bitmask.toByteArray()
+ if (bitmaskArray.size != 1) throw IllegalArgumentException()
+ val array = bitmaskArray.toByteArray()
val id = ParcelsT.getOrInitId(parcel)
ParcelOptionsT.upsert(ParcelOptionsT.parcel_id) {
it[parcel_id] = id
@@ -242,16 +243,16 @@ class ExposedBacking(private val dataSourceFactory: () -> DataSource, val poolSi
}
override fun transmitAllGlobalAddedData(channel: SendChannel<AddedDataPair<PlayerProfile>>) {
- AddedGlobalT.sendAllAddedData(channel)
+ PrivilegesGlobalT.sendAllAddedData(channel)
channel.close()
}
- override fun readGlobalAddedData(owner: PlayerProfile): MutableAddedDataMap {
- return AddedGlobalT.readAddedData(ProfilesT.getId(owner.toOwnerProfile()) ?: return hashMapOf())
+ override fun readGlobalPrivileges(owner: PlayerProfile): MutablePrivilegeMap {
+ return PrivilegesGlobalT.readPrivileges(ProfilesT.getId(owner.toOwnerProfile()) ?: return hashMapOf())
}
- override fun setGlobalPlayerStatus(owner: PlayerProfile, player: PlayerProfile, status: AddedStatus) {
- AddedGlobalT.setPlayerStatus(owner, player.toRealProfile(), status)
+ override fun setGlobalPrivilege(owner: PlayerProfile, player: PlayerProfile, privilege: Privilege) {
+ PrivilegesGlobalT.setPrivilege(owner, player.toRealProfile(), privilege)
}
private fun rowToParcelData(row: ResultRow) = ParcelDataHolder().apply {
@@ -266,7 +267,7 @@ class ExposedBacking(private val dataSourceFactory: () -> DataSource, val poolSi
System.arraycopy(source, 0, target, 0, source.size.clampMax(target.size))
}
- addedMap = AddedLocalT.readAddedData(id)
+ map = PrivilegesLocalT.readPrivileges(id)
}
}
diff --git a/src/main/kotlin/io/dico/parcels2/storage/exposed/IdTables.kt b/src/main/kotlin/io/dico/parcels2/storage/exposed/IdTables.kt
index 696b84c..6f6ad6b 100644
--- a/src/main/kotlin/io/dico/parcels2/storage/exposed/IdTables.kt
+++ b/src/main/kotlin/io/dico/parcels2/storage/exposed/IdTables.kt
@@ -26,7 +26,7 @@ abstract class IdTransactionsTable<TableT : IdTransactionsTable<TableT, QueryObj
internal inline fun getOrInitId(getId: () -> Int?, noinline body: TableT.(UpdateBuilder<*>) -> Unit, objName: () -> String): Int {
return getId() ?: table.insertIgnore(body)[id] ?: getId()
- ?: throw ExposedDatabaseException("This should not happen - failed to insert ${objName()} and get its id")
+ ?: throw ExposedDatabaseException("This should not happen - failed to insert ${objName()} and get its number")
}
abstract fun getId(obj: QueryObj): Int?
diff --git a/src/main/kotlin/io/dico/parcels2/storage/exposed/ListTables.kt b/src/main/kotlin/io/dico/parcels2/storage/exposed/ListTables.kt
index f41d545..600255e 100644
--- a/src/main/kotlin/io/dico/parcels2/storage/exposed/ListTables.kt
+++ b/src/main/kotlin/io/dico/parcels2/storage/exposed/ListTables.kt
@@ -3,30 +3,30 @@
package io.dico.parcels2.storage.exposed
import io.dico.parcels2.*
-import io.dico.parcels2.AddedStatus.ALLOWED
-import io.dico.parcels2.AddedStatus.DEFAULT
+import io.dico.parcels2.Privilege.DEFAULT
import kotlinx.coroutines.channels.SendChannel
import org.jetbrains.exposed.sql.*
-import java.util.UUID
-object AddedLocalT : AddedTable<ParcelId>("parcels_added_local", ParcelsT)
-object AddedGlobalT : AddedTable<PlayerProfile>("parcels_added_global", ProfilesT)
+object PrivilegesLocalT : PrivilegesTable<ParcelId>("parcels_added_local", ParcelsT)
+object PrivilegesGlobalT : PrivilegesTable<PlayerProfile>("parcels_added_global", ProfilesT)
object ParcelOptionsT : Table("parcel_options") {
val parcel_id = integer("parcel_id").primaryKey().references(ParcelsT.id, ReferenceOption.CASCADE)
- val interact_bitmask = binary("interact_bitmask", 4).default(ByteArray(4) { 0 }) // all zero by default
+ val interact_bitmask = binary("interact_bitmask", 4)
}
-typealias AddedStatusSendChannel<AttachT> = SendChannel<Pair<AttachT, MutableAddedDataMap>>
+typealias PrivilegesSendChannel<AttachT> = SendChannel<Pair<AttachT, MutablePrivilegeMap>>
-sealed class AddedTable<AttachT>(name: String, val idTable: IdTransactionsTable<*, AttachT>) : Table(name) {
+sealed class PrivilegesTable<AttachT>(name: String, val idTable: IdTransactionsTable<*, AttachT>) : Table(name) {
val attach_id = integer("attach_id").references(idTable.id, ReferenceOption.CASCADE)
val profile_id = integer("profile_id").references(ProfilesT.id, ReferenceOption.CASCADE)
- val allowed_flag = bool("allowed_flag")
+ val privilege = integer("privilege")
val index_pair = uniqueIndexR("index_pair", attach_id, profile_id)
- fun setPlayerStatus(attachedOn: AttachT, player: PlayerProfile.Real, status: AddedStatus) {
- if (status == DEFAULT) {
+ fun setPrivilege(attachedOn: AttachT, player: PlayerProfile.Real, privilege: Privilege) {
+ privilege.requireNonTransient()
+
+ if (privilege == DEFAULT) {
val player_id = ProfilesT.getId(player) ?: return
idTable.getId(attachedOn)?.let { holder ->
deleteWhere { (attach_id eq holder) and (profile_id eq player_id) }
@@ -39,28 +39,28 @@ sealed class AddedTable<AttachT>(name: String, val idTable: IdTransactionsTable<
upsert(conflictIndex = index_pair) {
it[attach_id] = holder
it[profile_id] = player_id
- it[allowed_flag] = status == ALLOWED
+ it[this.privilege] = privilege.number
}
}
- fun readAddedData(id: Int): MutableAddedDataMap {
- val list = slice(profile_id, allowed_flag).select { attach_id eq id }
- val result = MutableAddedDataMap()
+ fun readPrivileges(id: Int): MutablePrivilegeMap {
+ val list = slice(profile_id, privilege).select { attach_id eq id }
+ val result = MutablePrivilegeMap()
for (row in list) {
val profile = ProfilesT.getRealItem(row[profile_id]) ?: continue
- result[profile] = row[allowed_flag].asAddedStatus()
+ result[profile] = Privilege.safeGetByNumber(row[privilege]) ?: continue
}
return result
}
- fun sendAllAddedData(channel: AddedStatusSendChannel<AttachT>) {
+ fun sendAllAddedData(channel: PrivilegesSendChannel<AttachT>) {
val iterator = selectAll().orderBy(attach_id).iterator()
if (iterator.hasNext()) {
val firstRow = iterator.next()
var id: Int = firstRow[attach_id]
var attach: AttachT? = null
- var map: MutableAddedDataMap? = null
+ var map: MutablePrivilegeMap? = null
fun initAttachAndMap() {
attach = idTable.getItem(id)
@@ -90,14 +90,12 @@ sealed class AddedTable<AttachT>(name: String, val idTable: IdTransactionsTable<
}
val profile = ProfilesT.getRealItem(row[profile_id]) ?: continue
- val status = row[allowed_flag].asAddedStatus()
- map!![profile] = status
+ val privilege = Privilege.safeGetByNumber(row[privilege]) ?: continue
+ map!![profile] = privilege
}
sendIfPresent()
}
}
- private inline fun Boolean?.asAddedStatus() = if (this == null) AddedStatus.DEFAULT else if (this) ALLOWED else AddedStatus.BANNED
-
}
diff --git a/src/main/kotlin/io/dico/parcels2/storage/migration/plotme/PlotmeMigration.kt b/src/main/kotlin/io/dico/parcels2/storage/migration/plotme/PlotmeMigration.kt
index 0dcf36d..b514f87 100644
--- a/src/main/kotlin/io/dico/parcels2/storage/migration/plotme/PlotmeMigration.kt
+++ b/src/main/kotlin/io/dico/parcels2/storage/migration/plotme/PlotmeMigration.kt
@@ -66,11 +66,11 @@ class PlotmeMigration(val options: PlotmeMigrationOptions) : Migration {
return ParcelId(world, row[table.px], row[table.pz])
}
- fun PlotmePlotPlayerMap.transmitPlotmeAddedTable(kind: AddedStatus) {
+ fun PlotmePlotPlayerMap.transmitPlotmeAddedTable(kind: Privilege) {
selectAll().forEach { row ->
val parcel = getParcelId(this, row) ?: return@forEach
val profile = StatusKey.safe(row[player_uuid]?.toUUID(), row[player_name]) ?: return@forEach
- target.setParcelPlayerStatus(parcel, profile, kind)
+ target.setLocalPrivilege(parcel, profile, kind)
}
}
@@ -89,12 +89,12 @@ class PlotmeMigration(val options: PlotmeMigrationOptions) : Migration {
mlogger.info("Transmitting data from plotmeallowed table")
transaction {
- PlotmeAllowedT.transmitPlotmeAddedTable(AddedStatus.ALLOWED)
+ PlotmeAllowedT.transmitPlotmeAddedTable(Privilege.CAN_BUILD)
}
mlogger.info("Transmitting data from plotmedenied table")
transaction {
- PlotmeDeniedT.transmitPlotmeAddedTable(AddedStatus.BANNED)
+ PlotmeDeniedT.transmitPlotmeAddedTable(Privilege.BANNED)
}
mlogger.warn("Data has been **transmitted**.")