Skip to content

Commit

Permalink
stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
mukunda- committed Sep 1, 2014
1 parent 932bc75 commit f9328a6
Show file tree
Hide file tree
Showing 4 changed files with 234 additions and 17 deletions.
122 changes: 118 additions & 4 deletions src/main/java/com/mukunda/shortid/IDDatabase.java
Original file line number Diff line number Diff line change
@@ -1,18 +1,32 @@

package com.mukunda.shortid;

import java.io.IOException;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.ResultSet;
import java.sql.SQLRecoverableException;
import java.sql.SQLTransientException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.UUID;







import org.bukkit.scheduler.BukkitRunnable;

public class IDDatabase extends SQL {

private static final int DB_RETRY_DELAY = 20;

private static class Job {
public Object id;

Expand All @@ -39,8 +53,6 @@ private class Resolver extends BukkitRunnable {

private final Job job;

private static final int RETRY_DELAY = 20;

public Resolver( Job job ) {
this.job = job;
}
Expand Down Expand Up @@ -86,12 +98,12 @@ public void run() {
} catch ( SQLTransientException e ) {
// retry in one second
context.getLogger().warning( "SQL query failed. retrying... reason = " + e.getMessage() );
runTaskLaterAsynchronously( context, RETRY_DELAY );
runTaskLaterAsynchronously( context, DB_RETRY_DELAY );
} catch ( SQLRecoverableException e ) {

context.getLogger().warning( "SQL query failed. retrying... reason = " + e.getMessage() );
disconnect();
runTaskLaterAsynchronously( context, RETRY_DELAY );
runTaskLaterAsynchronously( context, DB_RETRY_DELAY );

} catch ( SQLException e ) {
disconnect();
Expand Down Expand Up @@ -183,4 +195,106 @@ public synchronized void resolve( SID sid ) {

new Resolver( job ).runTaskAsynchronously( context );
}

public boolean importData() {

try {
HashMap<UUID,SID> data = context.buildImport();

while( true ) {
try {
connect();

PreparedStatement statement = getConnection().prepareStatement(
"INSERT INTO " + table + " (`uuid`,`sid`) VALUES(?,?)" );

Iterator<Map.Entry<UUID,SID>> iter = data.entrySet().iterator();
while( iter.hasNext() ) {
Map.Entry<UUID,SID> entry = iter.next();
byte[] uuidBytes = mashUUID( entry.getKey() );

statement.setBytes( 1, uuidBytes );
statement.setInt( 2, entry.getValue().getInt() );
statement.executeUpdate();
iter.remove();
}

statement.close();
break;

} catch ( SQLTransientException|SQLRecoverableException e ) {
// retry in one second
if( e instanceof SQLRecoverableException ) disconnect();

context.getLogger().warning( "Database fault during import: " + e.getMessage() + " -- retrying..." );
try {
Thread.sleep( 50*DB_RETRY_DELAY );
} catch( InterruptedException e2 ) {} // yum.

} catch ( SQLException e ) {
disconnect();
context.getLogger().severe( "SQL encountered a non-recoverable problem: " + e.getMessage() );
context.getLogger().severe( "IDs have **NOT** been imported! " + e.getMessage() );
return false;
}
}

} catch (IOException e) {
context.getLogger().severe(
"IOException while trying to import data! IDs have **NOT** been imported!" );

context.getLogger().severe( e.getMessage() );

return false;
}
return true;

}

public boolean setup() {

boolean importData = false;

while( true ) {

try {
connect();
DatabaseMetaData dbm = getConnection().getMetaData();
ResultSet tables = dbm.getTables(null, null, table, null);
if( !tables.next() ) {
Statement statement = getConnection().createStatement();
statement.executeUpdate( "CREATE TABLE "+table+" (" +
"uuid BINARY(16) NOT NULL," +
"sid INTEGER NOT NULL," +
"PRIMARY KEY (uuid,sid) ) " +
"AUTO_INCREMENT = " + String.format( "%d", ShortID.INITIAL_SID ) );

importData = true;
break;
}


} catch ( SQLTransientException|SQLRecoverableException e ) {
// retry in one second
if( e instanceof SQLRecoverableException ) disconnect();
context.getLogger().warning( "Database setup failure: " + e.getMessage() + " -- retrying..." );
try {
Thread.sleep( 50*DB_RETRY_DELAY );
} catch( InterruptedException e2 ) {

}

} catch ( SQLException e ) {
disconnect();
context.getLogger().severe( "SQL encountered a non-recoverable problem: " + e.getMessage() );
return false;
}
}

if( importData ) {
return importData();
}

return true;
}
}
43 changes: 43 additions & 0 deletions src/main/java/com/mukunda/shortid/NextIDFinder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.mukunda.shortid;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.file.Files;

public final class NextIDFinder {

public static int FindNextID( ShortID context ) throws IOException {

// tbh i think the new file visitor class is fucking stupid
// using the old functions here.

int nextId = ShortID.INITIAL_SID;

File[] files = new File( context.getDataFolder(), "uuid" ).listFiles();
for( File file : files ) {

if( !file.isFile() ) continue;
if( !file.getName().endsWith(".map") ) continue;

ByteBuffer buffer = ByteBuffer.allocate(4);//[4];
//byte[] buffer = new byte[4];

try (
BufferedInputStream input = new BufferedInputStream(
Files.newInputStream( file.toPath() ) ) ) {

for(;;) {
int size = input.read( buffer.array() );
if( size != 4 ) break;
if( buffer.getInt(0) > nextId ) nextId = buffer.getInt(0);
}
} catch( IOException e ) {
throw e;
}

}
return nextId;
}
}
4 changes: 4 additions & 0 deletions src/main/java/com/mukunda/shortid/SID.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,8 @@ public boolean equals( Object other ) {
public String toString() {
return String.format( "%08X", id );
}

public static SID fromString( String string ) {
return new SID(Integer.parseInt( string, 16 ));
}
}
82 changes: 69 additions & 13 deletions src/main/java/com/mukunda/shortid/ShortID.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
/*
* ShortID
* Copyright (c) 2014 mukunda
*
* API for managing 32-bit IDs that represent player UUIDs
*
*/

package com.mukunda.shortid;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SeekableByteChannel;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.sql.SQLException;
import java.sql.SQLNonTransientException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.UUID;

import org.bukkit.Bukkit;
Expand All @@ -26,14 +34,21 @@

//---------------------------------------------------------------------------------------------
public class ShortID extends JavaPlugin implements Listener, ShortIDAPI {

public ShortID instance;
public static ShortID instance;

private IDMap idMap;
private IDDatabase db;

public static final int INITIAL_SID = 0x100;

private int nextLocalID;

//---------------------------------------------------------------------------------------------
public static ShortIDAPI getAPI() {
return instance;
}

//---------------------------------------------------------------------------------------------
public void onEnable() {
saveConfig();
Expand Down Expand Up @@ -79,14 +94,9 @@ public void onEnable() {

db = new IDDatabase( this, idMap, info, table );

try {
db.testConnection();
} catch( SQLNonTransientException e ) {
getLogger().severe( "SQL Error. " + e.getMessage() );
if( !db.setup() ) {
setEnabled( false );
return;
} catch( SQLException e ) {
getLogger().warning( "Could not connect to database. " + e.getMessage() );
}

} else {
Expand All @@ -97,7 +107,7 @@ public void onEnable() {
content = new String( Files.readAllBytes( path ) );

} catch( IOException e ) {
getLogger().severe( "Could not read next id." );
getLogger().severe( "Could not read next id. " + e.getMessage() );
setEnabled(false);
return;
}
Expand All @@ -108,14 +118,19 @@ public void onEnable() {

} catch( NumberFormatException e ) {
getLogger().severe( "Next ID file was corrupted, scanning data files to get next available ID." );
// TODO.. scan data structure
try {
nextLocalID = NextIDFinder.FindNextID( this );
} catch( IOException e2 ) {
getLogger().severe( "Could not read ID file table. " + e2.getMessage() );
setEnabled(false);
}
}

getLogger().info( "Next ID available = " + nextLocalID );

} else {

nextLocalID = 0x100;
nextLocalID = INITIAL_SID;
}
}

Expand Down Expand Up @@ -409,4 +424,45 @@ public void onPlayerJoin( PlayerJoinEvent event ) {
public void Crash() {
this.setEnabled(false);
}

public HashMap<UUID,SID> buildImport() throws IOException {
HashMap<UUID,SID> result = new HashMap<UUID,SID>();

File[] files = new File( getDataFolder(), "sid" ).listFiles();
for( File file : files ) {

if( !file.isFile() ) continue;
if( !file.getName().endsWith(".map") ) continue;

ByteBuffer buffer = ByteBuffer.allocate(16);//[4];
//byte[] buffer = new byte[4];

String sidBase = file.getName().substring( 0, 6 );

try (
BufferedInputStream input = new BufferedInputStream(
Files.newInputStream( file.toPath() ) ) ) {

for( int index = 0; index < 256; index++ ) {

int size = input.read( buffer.array() );
if( size != 16 ) break;

String sidString = sidBase + String.format( "%02X", index );

long dataL, dataH;
dataL = buffer.getLong(0);
dataH = buffer.getLong(1);
if( dataL == 0 && dataH == 0 ) continue;

result.put( new UUID(dataH,dataL), SID.fromString(sidString) );

}
} catch( IOException e ) {
throw e;
}

}
return result;
}
}

0 comments on commit f9328a6

Please sign in to comment.