diff options
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.kt | 113 |
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 |