summaryrefslogtreecommitdiff
path: root/src/main/kotlin/io/dico/parcels2/storage/migration/plotme/PlotmeMigration.kt
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/kotlin/io/dico/parcels2/storage/migration/plotme/PlotmeMigration.kt')
-rw-r--r--src/main/kotlin/io/dico/parcels2/storage/migration/plotme/PlotmeMigration.kt113
1 files changed, 53 insertions, 60 deletions
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 e5b7d9d..f0c0cd8 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
@@ -1,37 +1,35 @@
+@file:Suppress("RedundantSuspendModifier", "DEPRECATION")
+
package io.dico.parcels2.storage.migration.plotme
import com.zaxxer.hikari.HikariDataSource
import io.dico.parcels2.*
+import io.dico.parcels2.options.PlotmeMigrationOptions
import io.dico.parcels2.storage.Storage
+import io.dico.parcels2.storage.exposed.abs
+import io.dico.parcels2.storage.exposed.greater
import io.dico.parcels2.storage.migration.Migration
-import io.dico.parcels2.util.Vec2i
-import io.dico.parcels2.util.isValid
import io.dico.parcels2.util.toUUID
-import io.dico.parcels2.util.uuid
-import kotlinx.coroutines.experimental.asCoroutineDispatcher
+import kotlinx.coroutines.experimental.Job
import kotlinx.coroutines.experimental.launch
-import org.bukkit.Bukkit
+import kotlinx.coroutines.experimental.newFixedThreadPoolContext
import org.jetbrains.exposed.sql.*
import org.slf4j.LoggerFactory
-import java.io.ByteArrayOutputStream
import java.sql.Blob
import java.util.UUID
-import java.util.concurrent.Executors
import javax.sql.DataSource
-class PlotmeMigration(val parcelProvider: ParcelProvider,
- val worldMapper: Map<String, String>,
- val dataSourceFactory: () -> DataSource) : Migration {
+class PlotmeMigration(val options: PlotmeMigrationOptions) : Migration {
private var dataSource: DataSource? = null
private var database: Database? = null
private var isShutdown: Boolean = false
- private val dispatcher = Executors.newSingleThreadExecutor { Thread(it, "PlotMe Migration Thread") }.asCoroutineDispatcher()
private val mlogger = LoggerFactory.getLogger("PlotMe Migrator")
+ val dispatcher = newFixedThreadPoolContext(1, "PlotMe Migration Thread")
private fun <T> transaction(statement: Transaction.() -> T) = org.jetbrains.exposed.sql.transactions.transaction(database!!, statement)
- override fun migrateTo(storage: Storage) {
- launch(context = dispatcher) {
+ override fun migrateTo(storage: Storage): Job {
+ return launch(dispatcher) {
init()
doWork(storage)
shutdown()
@@ -39,8 +37,8 @@ class PlotmeMigration(val parcelProvider: ParcelProvider,
}
fun init() {
- if (isShutdown) throw IllegalStateException()
- dataSource = dataSourceFactory()
+ if (isShutdown || database != null) throw IllegalStateException()
+ dataSource = options.storage.getDataSourceFactory()!!()
database = Database.connect(dataSource!!)
}
@@ -53,66 +51,61 @@ class PlotmeMigration(val parcelProvider: ParcelProvider,
isShutdown = true
}
- val parcelsCache = hashMapOf<String, MutableMap<Vec2i, ParcelData>>()
-
- private fun getMap(worldName: String): MutableMap<Vec2i, ParcelData>? {
- val mapped = worldMapper[worldName] ?: return null
- return parcelsCache.computeIfAbsent(mapped) { mutableMapOf() }
- }
+ suspend fun doWork(target: Storage) {
+ val exit = transaction {
+ (!PlotmePlotsT.exists()).also {
+ if (it) mlogger.warn("Plotme tables don't appear to exist. Exiting.")
+ }
+ }
+ if (exit) return
- private fun getData(worldName: String, position: Vec2i): ParcelData? {
- return getMap(worldName)?.computeIfAbsent(position) { ParcelDataHolder() }
- }
+ val worldCache = options.worldsFromTo.mapValues { ParcelWorldId(it.value) }
- fun doWork(target: Storage): Unit = transaction {
- if (!PlotmePlotsT.exists()) {
- mlogger.warn("Plotme tables don't appear to exist. Exiting.")
- return@transaction
+ fun getParcelId(table: PlotmeTable, row: ResultRow): ParcelId? {
+ val world = worldCache[row[table.world_name]] ?: return null
+ return ParcelId(world, row[table.px], row[table.pz])
}
- parcelsCache.clear()
- iterPlotmeTable(PlotmePlotsT) { data, row ->
- // in practice, owner_uuid is not null for any plot currently. It will convert well.
- data.owner = ParcelOwner(row[owner_uuid]?.toUUID(), row[owner_name])
+ fun PlotmePlotPlayerMap.transmitPlotmeAddedTable(kind: AddedStatus) {
+ 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)
+ }
}
- iterPlotmeTable(PlotmeAllowedT) { data, row ->
- val uuid = row[player_uuid]?.toUUID()
- ?: Bukkit.getOfflinePlayer(row[player_name]).takeIf { it.isValid }?.uuid
- ?: return@iterPlotmeTable
-
- data.setAddedStatus(uuid, AddedStatus.ALLOWED)
+ mlogger.info("Transmitting data from plotmeplots table")
+ transaction {
+ PlotmePlotsT.selectAll()
+ .orderBy(PlotmePlotsT.world_name)
+ .orderBy(with(SqlExpressionBuilder) { greater(PlotmePlotsT.px.abs(), PlotmePlotsT.pz.abs()) })
+ .forEach { row ->
+ val parcel = getParcelId(PlotmePlotsT, row) ?: return@forEach
+ val owner = PlayerProfile.safe(row[PlotmePlotsT.owner_uuid]?.toUUID(), row[PlotmePlotsT.owner_name])
+ target.setParcelOwner(parcel, owner)
+ }
}
- iterPlotmeTable(PlotmeDeniedT) { data, row ->
- val uuid = row[PlotmeAllowedT.player_uuid]?.toUUID()
- ?: Bukkit.getOfflinePlayer(row[PlotmeAllowedT.player_name]).takeIf { it.isValid }?.uuid
- ?: return@iterPlotmeTable
-
- data.setAddedStatus(uuid, AddedStatus.BANNED)
+ mlogger.info("Transmitting data from plotmeallowed table")
+ transaction {
+ PlotmeAllowedT.transmitPlotmeAddedTable(AddedStatus.ALLOWED)
}
- for ((worldName, map) in parcelsCache) {
- val world = ParcelWorldId(worldName)
- for ((pos, data) in map) {
- val parcel = ParcelId(world, pos)
- target.setParcelData(parcel, data)
- }
+ mlogger.info("Transmitting data from plotmedenied table")
+ transaction {
+ PlotmeDeniedT.transmitPlotmeAddedTable(AddedStatus.BANNED)
}
+ mlogger.warn("Data has been **transmitted**.")
+ mlogger.warn("Loading parcel data might take a while as enqueued transactions from this migration are completed.")
}
- private fun Blob.toUUID(): UUID {
- val out = ByteArrayOutputStream(16)
- binaryStream.copyTo(out, bufferSize = 16)
- return out.toByteArray().toUUID()
+ private fun Blob.toUUID(): UUID? {
+ val ba = ByteArray(16)
+ val count = binaryStream.read(ba, 0, 16)
+ if (count < 16) return null
+ return ba.toUUID()
}
- private inline fun <T : PlotmeTable> iterPlotmeTable(table: T, block: T.(ParcelData, ResultRow) -> Unit) {
- table.selectAll().forEach { row ->
- val data = getData(row[table.world_name], Vec2i(row[table.px], row[table.pz])) ?: return@forEach
- table.block(data, row)
- }
- }
} \ No newline at end of file