move game data from separate files into a BLOB column in the existing

summaries db table, using the existing SNAPSHOT column rather than
adding a new one and upping the version.  Includes utility fired at
game-start to convert existing games that seems to work.  Also
improved a few queries and updates to -- I think -- use the API
better.
This commit is contained in:
Andy2 2010-11-24 17:22:04 -08:00
parent 7c96048ba2
commit be35d875b2
5 changed files with 203 additions and 63 deletions

View file

@ -150,7 +150,6 @@ public class DBUtils {
db.delete( DBHelper.TABLE_NAME_SUM, selection, null ); db.delete( DBHelper.TABLE_NAME_SUM, selection, null );
} else { } else {
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
values.put( DBHelper.FILE_NAME, path );
values.put( DBHelper.NUM_MOVES, summary.nMoves ); values.put( DBHelper.NUM_MOVES, summary.nMoves );
values.put( DBHelper.NUM_PLAYERS, summary.nPlayers ); values.put( DBHelper.NUM_PLAYERS, summary.nPlayers );
values.put( DBHelper.PLAYERS, values.put( DBHelper.PLAYERS,
@ -158,6 +157,7 @@ public class DBUtils {
values.put( DBHelper.DICTLANG, summary.dictLang ); values.put( DBHelper.DICTLANG, summary.dictLang );
values.put( DBHelper.DICTNAME, summary.dictName ); values.put( DBHelper.DICTNAME, summary.dictName );
values.put( DBHelper.GAME_OVER, summary.gameOver ); values.put( DBHelper.GAME_OVER, summary.gameOver );
values.put( DBHelper.HASMSGS, 0 );
if ( null != summary.scores ) { if ( null != summary.scores ) {
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
@ -178,16 +178,14 @@ public class DBUtils {
Utils.logf( "saveSummary: nMoves=%d", summary.nMoves ); Utils.logf( "saveSummary: nMoves=%d", summary.nMoves );
try { String selection = DBHelper.FILE_NAME + "=\"" + path + "\"";
long result = db.replaceOrThrow( DBHelper.TABLE_NAME_SUM, long result = db.update( DBHelper.TABLE_NAME_SUM,
"", values ); values, selection, null );
} catch ( Exception ex ) { Assert.assertTrue( result >= 0 );
Utils.logf( "ex: %s", ex.toString() );
}
} }
db.close(); db.close();
} }
} } // saveSummary
public static int countGamesUsing( Context context, String dict ) public static int countGamesUsing( Context context, String dict )
{ {
@ -214,11 +212,13 @@ public class DBUtils {
synchronized( s_dbHelper ) { synchronized( s_dbHelper ) {
SQLiteDatabase db = s_dbHelper.getWritableDatabase(); SQLiteDatabase db = s_dbHelper.getWritableDatabase();
String cmd = String.format( "UPDATE %s SET %s = 1 WHERE %s = '%s'", String selection = DBHelper.RELAYID + "=\'" + relayID + "\'";
DBHelper.TABLE_NAME_SUM, ContentValues values = new ContentValues();
DBHelper.HASMSGS, values.put( DBHelper.HASMSGS, 1 );
DBHelper.RELAYID, relayID );
db.execSQL( cmd ); int result = db.update( DBHelper.TABLE_NAME_SUM,
values, selection, null );
Assert.assertTrue( result == 1 );
db.close(); db.close();
} }
} }
@ -356,6 +356,90 @@ public class DBUtils {
} }
} }
public static void saveGame( Context context, String path, byte[] bytes )
{
initDB( context );
synchronized( s_dbHelper ) {
SQLiteDatabase db = s_dbHelper.getWritableDatabase();
String selection = DBHelper.FILE_NAME + "=\"" + path + "\"";
ContentValues values = new ContentValues();
values.put( DBHelper.SNAPSHOT, bytes );
int result = db.update( DBHelper.TABLE_NAME_SUM,
values, selection, null );
if ( 0 == result ) {
values.put( DBHelper.FILE_NAME, path );
long row = db.insert( DBHelper.TABLE_NAME_SUM, null, values );
Assert.assertTrue( row >= 0 );
}
db.close();
}
}
public static byte[] loadGame( Context context, String path )
{
Assert.assertNotNull( path );
byte[] result = null;
initDB( context );
synchronized( s_dbHelper ) {
SQLiteDatabase db = s_dbHelper.getReadableDatabase();
String[] columns = { DBHelper.SNAPSHOT };
String selection = DBHelper.FILE_NAME + "=\"" + path + "\"";
Cursor cursor = db.query( DBHelper.TABLE_NAME_SUM, columns,
selection, null, null, null, null );
if ( 1 == cursor.getCount() && cursor.moveToFirst() ) {
result = cursor.getBlob( cursor
.getColumnIndex(DBHelper.SNAPSHOT));
}
cursor.close();
db.close();
}
return result;
}
public static void deleteGame( Context context, String path )
{
initDB( context );
synchronized( s_dbHelper ) {
SQLiteDatabase db = s_dbHelper.getWritableDatabase();
String selection = DBHelper.FILE_NAME + "=\"" + path + "\"";
db.delete( DBHelper.TABLE_NAME_SUM, selection, null );
db.close();
}
}
public static String[] gamesList( Context context )
{
ArrayList<String> al = new ArrayList<String>();
initDB( context );
synchronized( s_dbHelper ) {
SQLiteDatabase db = s_dbHelper.getReadableDatabase();
String[] columns = { DBHelper.FILE_NAME };
Cursor cursor = db.query( DBHelper.TABLE_NAME_SUM, columns,
null, null, null, null, null );
if ( 0 < cursor.getCount() ) {
cursor.moveToFirst();
for ( ; ; ) {
int index = cursor.getColumnIndex( DBHelper.FILE_NAME );
String name = cursor.getString( index );
al.add( cursor.getString( index ) );
if ( cursor.isLast() ) {
break;
}
cursor.moveToNext();
}
}
cursor.close();
db.close();
}
return al.toArray( new String[al.size()] );
}
private static void initDB( Context context ) private static void initDB( Context context )
{ {
if ( null == s_dbHelper ) { if ( null == s_dbHelper ) {

View file

@ -0,0 +1,81 @@
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
/*
* Copyright 2010 by Eric House (xwords@eehouse.org). All rights
* reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.eehouse.android.xw4;
import android.content.Context;
import java.io.FileInputStream;
import java.util.ArrayList;
// Rip this out a month or so after releasing...
public class GameConverter {
public static void convert( Context context )
{
String[] games = gamesList( context );
if ( null == games ) {
Utils.logf( "GameConverter::convert() no old games found" );
} else {
for ( String game : games ) {
Utils.logf( "GameConverter::convert() converting %s",
game );
byte[] bytes = savedGame( context, game );
DBUtils.saveGame( context, game, bytes );
context.deleteFile( game );
}
}
}
private static byte[] savedGame( Context context, String path )
{
byte[] stream = null;
try {
FileInputStream in = context.openFileInput( path );
int len = in.available();
stream = new byte[len];
in.read( stream, 0, len );
in.close();
} catch ( java.io.FileNotFoundException fnf ) {
Utils.logf( fnf.toString() );
stream = null;
} catch ( java.io.IOException io ) {
Utils.logf( io.toString() );
stream = null;
}
return stream;
}
private static String[] gamesList( Context context )
{
ArrayList<String> al = new ArrayList<String>();
for ( String file : context.fileList() ) {
if ( file.endsWith( XWConstants.GAME_EXTN ) ) {
al.add( file );
}
}
int siz = al.size();
String[] result = null;
if ( siz > 0 ) {
result = al.toArray( new String[siz] );
}
return result;
}
}

View file

@ -41,7 +41,7 @@ public class GameListAdapter extends XWListAdapter {
private HashMap<String,View> m_viewsCache; private HashMap<String,View> m_viewsCache;
public GameListAdapter( Context context ) { public GameListAdapter( Context context ) {
super( context, GameUtils.gamesList(context).length ); super( context, DBUtils.gamesList(context).length );
m_context = context; m_context = context;
m_factory = LayoutInflater.from( context ); m_factory = LayoutInflater.from( context );
@ -56,12 +56,12 @@ public class GameListAdapter extends XWListAdapter {
} }
public int getCount() { public int getCount() {
return GameUtils.gamesList(m_context).length; return DBUtils.gamesList(m_context).length;
} }
public Object getItem( int position ) public Object getItem( int position )
{ {
final String path = GameUtils.gamesList(m_context)[position]; final String path = DBUtils.gamesList(m_context)[position];
View layout = m_viewsCache.get( path ); View layout = m_viewsCache.get( path );
if ( null == layout ) { if ( null == layout ) {

View file

@ -40,23 +40,7 @@ public class GameUtils {
public static byte[] savedGame( Context context, String path ) public static byte[] savedGame( Context context, String path )
{ {
byte[] stream = null; return DBUtils.loadGame( context, path );
try {
synchronized( s_syncObj ) {
FileInputStream in = context.openFileInput( path );
int len = in.available();
stream = new byte[len];
in.read( stream, 0, len );
in.close();
}
} catch ( java.io.FileNotFoundException fnf ) {
Utils.logf( fnf.toString() );
stream = null;
} catch ( java.io.IOException io ) {
Utils.logf( io.toString() );
stream = null;
}
return stream;
} // savedGame } // savedGame
/** /**
@ -125,17 +109,6 @@ public class GameUtils {
return summary; return summary;
} }
public static String[] gamesList( Context context )
{
ArrayList<String> al = new ArrayList<String>();
for ( String file : context.fileList() ) {
if ( isGame( file ) ){
al.add( file );
}
}
return al.toArray( new String[al.size()] );
}
public static String dupeGame( Context context, String pathIn ) public static String dupeGame( Context context, String pathIn )
{ {
String newName = newName( context ); String newName = newName( context );
@ -148,8 +121,7 @@ public class GameUtils {
{ {
// does this need to be synchronized? // does this need to be synchronized?
tellRelayDied( context, path, informNow ); tellRelayDied( context, path, informNow );
context.deleteFile( path ); DBUtils.deleteGame( context, path );
DBUtils.saveSummary( context, path, null );
} }
public static void loadMakeGame( Context context, int gamePtr, public static void loadMakeGame( Context context, int gamePtr,
@ -185,16 +157,17 @@ public class GameUtils {
public static void saveGame( Context context, byte[] bytes, String path ) public static void saveGame( Context context, byte[] bytes, String path )
{ {
try { DBUtils.saveGame( context, path, bytes );
synchronized( s_syncObj ) { // try {
FileOutputStream out = // synchronized( s_syncObj ) {
context.openFileOutput( path, Context.MODE_PRIVATE ); // FileOutputStream out =
out.write( bytes ); // context.openFileOutput( path, Context.MODE_PRIVATE );
out.close(); // out.write( bytes );
} // out.close();
} catch ( java.io.IOException ex ) { // }
Utils.logf( "got IOException: " + ex.toString() ); // } catch ( java.io.IOException ex ) {
} // Utils.logf( "got IOException: " + ex.toString() );
// }
} }
public static String saveGame( Context context, byte[] bytes ) public static String saveGame( Context context, byte[] bytes )
@ -228,7 +201,7 @@ public class GameUtils {
public static boolean gameDictHere( Context context, int indx, public static boolean gameDictHere( Context context, int indx,
String[] name, int[] lang ) String[] name, int[] lang )
{ {
String path = GameUtils.gamesList( context )[indx]; String path = DBUtils.gamesList( context )[indx];
return gameDictHere( context, path, name, lang ); return gameDictHere( context, path, name, lang );
} }
@ -237,7 +210,7 @@ public class GameUtils {
String name = null; String name = null;
Integer num = 1; Integer num = 1;
int ii; int ii;
String[] files = context.fileList(); String[] files = DBUtils.gamesList( context );
String fmt = context.getString( R.string.gamef ); String fmt = context.getString( R.string.gamef );
while ( name == null ) { while ( name == null ) {

View file

@ -153,6 +153,8 @@ public class GamesList extends XWListActivity
} }
}); });
GameConverter.convert( this );
m_adapter = new GameListAdapter( this ); m_adapter = new GameListAdapter( this );
setListAdapter( m_adapter ); setListAdapter( m_adapter );
@ -281,12 +283,12 @@ public class GamesList extends XWListActivity
switch (item.getItemId()) { switch (item.getItemId()) {
case R.id.gamel_menu_delete_all: case R.id.gamel_menu_delete_all:
if ( GameUtils.gamesList( this ).length > 0 ) { if ( DBUtils.gamesList( this ).length > 0 ) {
DialogInterface.OnClickListener lstnr = DialogInterface.OnClickListener lstnr =
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dlg, int item ) { public void onClick( DialogInterface dlg, int item ) {
String[] games = String[] games =
GameUtils.gamesList( GamesList.this ); DBUtils.gamesList( GamesList.this );
for ( int ii = games.length - 1; ii >= 0; --ii ) { for ( int ii = games.length - 1; ii >= 0; --ii ) {
GameUtils.deleteGame( GamesList.this, games[ii], GameUtils.deleteGame( GamesList.this, games[ii],
ii == 0 ); ii == 0 );
@ -338,7 +340,7 @@ public class GamesList extends XWListActivity
protected void onListItemClick( ListView l, View v, int position, long id ) protected void onListItemClick( ListView l, View v, int position, long id )
{ {
super.onListItemClick( l, v, position, id ); super.onListItemClick( l, v, position, id );
String path = GameUtils.gamesList( this )[position]; String path = DBUtils.gamesList( this )[position];
// We need a way to let the user get back to the basic-config // We need a way to let the user get back to the basic-config
// dialog in case it was dismissed. That way it to check for // dialog in case it was dismissed. That way it to check for
@ -373,7 +375,7 @@ public class GamesList extends XWListActivity
boolean handled = true; boolean handled = true;
DialogInterface.OnClickListener lstnr; DialogInterface.OnClickListener lstnr;
final String path = GameUtils.gamesList( this )[position]; final String path = DBUtils.gamesList( this )[position];
if ( R.id.list_item_delete == menuID ) { if ( R.id.list_item_delete == menuID ) {
lstnr = new DialogInterface.OnClickListener() { lstnr = new DialogInterface.OnClickListener() {