Created
March 10, 2015 16:31
-
-
Save simonwoo/aae51852b2125ea8194a to your computer and use it in GitHub Desktop.
automatic migration for cassandra
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.apispark.db; | |
import java.lang.reflect.InvocationTargetException; | |
import java.lang.reflect.Method; | |
import java.net.MalformedURLException; | |
import java.net.URL; | |
import java.net.URLClassLoader; | |
import java.util.ArrayList; | |
import java.util.Iterator; | |
import java.io.File; | |
import java.io.IOException; | |
import com.datastax.driver.core.ResultSet; | |
import com.datastax.driver.core.Row; | |
public class migration extends CassandraMigrator{ | |
//the location of scripts | |
private String cqlsh = "/Applications/dse-4.6.1/bin/cqlsh"; | |
private String location = "/Users/mac/simon/restlet/apispark/modules/com.apispark.db/resources/cassandra/migrations/"; | |
private String table = "Version"; //the version table | |
private String cqlMigrationPrefix = "M"; | |
private String cqlMigrationSeparator = "_"; | |
public void run(String[] args){ | |
//set VM params | |
System.getProperties().setProperty("cassandra.properties.file", "/Users/mac/simon/restlet/apispark.properties"); | |
System.getProperties().setProperty("log4j.configuration", "/Users/mac/simon/restlet/log4j.properties"); | |
super.run(args); | |
} | |
@Override | |
public void migrate() { | |
ArrayList<String> scriptsJava = new ArrayList<String>(); //script file java | |
ArrayList<String> scriptsCql = new ArrayList<String>(); //script file cql | |
//create table Version if it does not exist | |
//String createVersionStatement = "CREATE TABLE IF NOT EXISTS \"Version\"( \"id\" uuid,\"filename\" varchar,\"timestamp\" varchar,PRIMARY KEY(\"id\"));?"; | |
//executeUpdate(createVersionStatement,""); | |
//get all the scripts with a timestamp greater than current database timestamp | |
getScripts(scriptsJava, scriptsCql); | |
//execute all the scripts java | |
executeScriptJavas(scriptsJava); | |
//execute all the scripts cql | |
executeScriptCqls(scriptsCql); | |
} | |
//get all the script file in the cassandra.migrations | |
private void getScripts(ArrayList<String> scriptsJava, ArrayList<String> scriptsCql){ | |
String biggestTimestamp = biggestTimestamp(); //current db timestamp in the table Version | |
ArrayList<File> files = listf(location); //get all the files under cassandra.migrations | |
Iterator iterator = files.iterator(); | |
while(iterator.hasNext()){ | |
File file = (File)iterator.next(); | |
String filename = file.getName(); | |
if(filename.startsWith(cqlMigrationPrefix)){ | |
String timestamp = filename.split(cqlMigrationSeparator)[0]; | |
timestamp = timestamp.substring(1, timestamp.length()); | |
//add the script with the timestamp greater than current db timestamp | |
if(compareTimestamp(timestamp,biggestTimestamp)){ | |
if(filename.indexOf(".java") >= 0) | |
scriptsJava.add(filename); | |
else if(filename.indexOf(".cqlsh.txt") >= 0) | |
scriptsCql.add(filename); | |
} | |
} | |
} | |
} | |
//get the biggest timestamp in the table Version | |
private String biggestTimestamp(){ | |
//get the biggest timestamp | |
String biggestTimestamp = "000000000000"; | |
ResultSet rs = query("select * from \"Version\"" + DEFAULT_QUERY_LIMIT); | |
for(Row row : rs){ | |
String timestamp = row.getString("timestamp"); | |
if(compareTimestamp(timestamp, biggestTimestamp)) | |
biggestTimestamp = timestamp; | |
} | |
return biggestTimestamp; | |
} | |
//a method to compare two timestamp | |
private boolean compareTimestamp(String timestamp1, String timestamp2){ | |
// | |
if(timestamp1.length() != timestamp2.length()) | |
return false; | |
if(timestamp1.length() == 0) | |
return true; | |
else if(timestamp1.length() == 1) | |
return timestamp1.charAt(0) >= timestamp2.charAt(0); | |
else if(timestamp1.charAt(0) > timestamp2.charAt(0)) | |
return true; | |
else if(timestamp1.charAt(0) == timestamp2.charAt(0)) | |
return compareTimestamp(timestamp1.substring(1,timestamp1.length()),timestamp2.substring(1,timestamp2.length())); | |
return false; | |
} | |
//get the all the files under a directory | |
private ArrayList<File> listf(String directoryName) { | |
ArrayList<File> files = new ArrayList<File>(); | |
File directory = new File(directoryName); | |
//test whether the directory exists | |
if(!directory.exists()){ | |
System.out.println("the script file path is not correct!!"); | |
return files; | |
} | |
// get all the files from a directory | |
File[] fList = directory.listFiles(); | |
for (File file : fList) { | |
if (file.isFile()) | |
files.add(file); | |
} | |
return files; | |
} | |
//execute all the script cql | |
private void executeScriptCqls(ArrayList<String> scriptsCql){ | |
Iterator iterator = scriptsCql.iterator(); | |
while(iterator.hasNext()){ | |
String scriptCql = (String)iterator.next(); | |
executeScriptCql(scriptCql); | |
insertVersion(scriptCql); | |
} | |
} | |
//execute a script cql | |
private void executeScriptCql(String scriptCql){ | |
try { | |
Runtime.getRuntime().exec(cqlsh + " < " + scriptCql); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
} | |
//execute all script java | |
private void executeScriptJavas(ArrayList<String> scriptsJava){ | |
Iterator iterator = scriptsJava.iterator(); | |
while(iterator.hasNext()){ | |
String scriptJava = (String)iterator.next(); | |
String className = scriptJava.substring(0, scriptJava.length() - 5); | |
executeScriptJava(className); | |
insertVersion(scriptJava); | |
} | |
} | |
//execute a script java | |
private void executeScriptJava(String scriptJava){ | |
ClassLoader classLoder = migration.class.getClassLoader(); | |
//add the url for searching the class | |
try{ | |
URLClassLoader urls = URLClassLoader.newInstance(new URL[]{ | |
new URL("file:///Users/mac/simon/restlet/apispark/modules/com.apispark.db/src/"), | |
new URL("file:///Users/mac/simon/restlet/apispark/modules/com.apispark.db/resource/") | |
}); | |
}catch(MalformedURLException e){ | |
e.printStackTrace(); | |
} | |
try{ | |
//load class | |
Class update = classLoder.loadClass("cassandra.migrations." + scriptJava); | |
System.out.println(update.getName()); | |
//execute the main method | |
Method method = update.getMethod("main", String[].class); | |
String[] params = {"--dry"}; | |
method.invoke(null, (Object) params); | |
}catch(ClassNotFoundException e){ | |
e.printStackTrace(); | |
} catch (NoSuchMethodException e) { | |
e.printStackTrace(); | |
} catch (SecurityException e) { | |
e.printStackTrace(); | |
} catch (IllegalAccessException e) { | |
e.printStackTrace(); | |
} catch (IllegalArgumentException e) { | |
e.printStackTrace(); | |
} catch (InvocationTargetException e) { | |
e.printStackTrace(); | |
} | |
} | |
private void insertVersion(String filename){ | |
String insertStatement = "insert into \"Version\"(\"id\",\"filename\",\"timestamp\") values(now(),'" + filename + "'," + "?);"; | |
String timestamp = filename.split(cqlMigrationSeparator)[0]; | |
timestamp = timestamp.substring(1, timestamp.length()); | |
executeUpdate(insertStatement,timestamp); | |
} | |
public static void main(String[] args){ | |
new migration().run(args); | |
} | |
} |
//execute all the scripts java
executeScriptJavas(scriptsJava);
//execute all the scripts cql
executeScriptCqls(scriptsCql);
Cql and java scripts should be sorted together, and execute scripts in the correct order (could be cql or a java)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
There are still problems:
1.I have no way to create table "Version" by java.
2.executeCql() does not work.