/* * Copyright (C) 2011-2012 asksven * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.asksven.betterbatterystats.data; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InvalidClassException; import java.io.ObjectInput; import java.io.ObjectInputStream; import java.io.ObjectOutput; import java.io.ObjectOutputStream; import java.io.StreamCorruptedException; import java.util.ArrayList; import java.util.List; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; import android.util.Log; /** * Singleton DBHelper class (makes sure there is only on database connection) * * Database layer for cell log data */ public class ReferenceDBHelper { private static final String DATABASE_NAME = "betterbatterystats"; private static final String TABLE_DBVERSION = "dbversion"; private static final String TABLE_NAME = "samples"; private static final int DATABASE_VERSION = 3; private static final String TAG = "ReferenceDBHelper"; private static final String[] COLS = new String[] {"ref_name", "ref_type", "ref_label", "time_created", "ref_blob"}; Context m_context; static ReferenceDBHelper m_helper; private static final String DBVERSION_CREATE = "create table " + TABLE_DBVERSION + " (" + "version integer not null);"; private static final String DBVERSION_DROP = " drop table " + TABLE_DBVERSION + ";"; private static final String PURGE_EVENTS = " delete from " + TABLE_NAME + ";"; private static final String TABLE_CREATE = "create table " + TABLE_NAME + " (" + "ref_name text primary key, " + "ref_type integer, " + "ref_label text, " + "time_created integer, " + "ref_blob blob" + ");"; private static final String TABLE_DROP = "drop table " + TABLE_NAME + ";"; private SQLiteDatabase m_db; protected static ReferenceDBHelper getInstance(Context context) { if (m_helper == null) { m_helper = new ReferenceDBHelper(context); } return m_helper; } /** * Hidden constructor, use as singleton * @param ctx */ private ReferenceDBHelper(Context ctx) { m_context = ctx; try { m_db = m_context.openOrCreateDatabase(DATABASE_NAME, SQLiteDatabase.CREATE_IF_NECESSARY, null); // Check for the existence of the DBVERSION table // If it doesn't exist than create the overall data, // otherwise double check the version Cursor c = m_db.query("sqlite_master", new String[] { "name" }, "type='table' and name='" + TABLE_DBVERSION + "'", null, null, null, null); try { int numRows = c.getCount(); if (numRows < 1) { createDatabase(m_db); } else { int version=0; Cursor vc = m_db.query(true, TABLE_DBVERSION, new String[] {"version"}, null, null, null, null, null,null); try { if(vc.getCount() > 0) { vc.moveToLast(); version=vc.getInt(0); } } finally { vc.close(); } if (version!=DATABASE_VERSION) { Log.e(TAG,"database version mismatch"); migrateDatabase(m_db, version, DATABASE_VERSION); } } } finally { c.close(); } } catch (SQLException e) { Log.d(TAG,"SQLite exception: " + e.getLocalizedMessage()); } } private synchronized void close() { if ((m_db != null) && (m_db.isOpen())) { try { m_db.close(); } catch (Exception e) { Log.e(TAG, "An error occured when closing the database: " + e.getMessage()); } } } private synchronized void createDatabase(SQLiteDatabase db) { try { db.execSQL(DBVERSION_CREATE); ContentValues args = new ContentValues(); args.put("version", DATABASE_VERSION); db.insert(TABLE_DBVERSION, null, args); db.execSQL(TABLE_CREATE); } catch (SQLException e) { Log.d(TAG,"SQLite exception: " + e.getLocalizedMessage()); } } private synchronized void deleteDatabase() { try { m_db.execSQL(DBVERSION_DROP); } catch (SQLException e) { Log.d(TAG,"SQLite exception: " + e.getLocalizedMessage()); } try { m_db.execSQL(TABLE_DROP); } catch (SQLException e) { Log.d(TAG,"SQLite exception: " + e.getLocalizedMessage()); } } protected synchronized void deleteReferences() { try { m_db.execSQL(PURGE_EVENTS); } catch (SQLException e) { Log.e(TAG,"SQLite exception: " + e.getLocalizedMessage()); } } /** * * @param entry */ protected synchronized void addOrUpdateReference(Reference entry) { ContentValues val = new ContentValues(); val.put("ref_name", entry.m_fileName); val.put("ref_type", entry.m_refType); val.put("time_created", entry.m_creationTime); val.put("ref_label", entry.m_refLabel); // val.put("ref_blob", entry.serialize()); val.put("ref_blob", entry.toReferenceDto().marshall()); try { long lRes = m_db.replace(TABLE_NAME, null, val); if (lRes == -1) { Log.e(TAG, "Error inserting or updating row"); } } catch (SQLException e) { Log.d(TAG, "SQLite exception: " + e.getLocalizedMessage()); } } protected synchronized void deleteReference(String refName) { try { long lRes = m_db.delete(TABLE_NAME, "ref_name='" + refName + "'", null); if (lRes == 0) { Log.e(TAG, "No row with key '" + refName + "' was deleted"); } } catch (SQLException e) { Log.d(TAG, "SQLite exception: " + e.getLocalizedMessage()); } } /** * * @return */ protected List<Reference> fetchAllRows() { ArrayList<Reference> ret = new ArrayList<Reference>(); try { Cursor c; c = m_db.query(TABLE_NAME, COLS, null, null, null, null, "time_created ASC"); try { int numRows = c.getCount(); c.moveToFirst(); for (int i = 0; i < numRows; ++i) { // cctor with id, name, command, command_status Reference row = createReferenceFromRow(c); ret.add(row); c.moveToNext(); } } finally { c.close(); } } catch (SQLException e) { Log.d(TAG,"SQLite exception: " + e.getLocalizedMessage()); } return ret; } public void logCacheContent() { List<Reference> refs = fetchAllRows(); Log.i(TAG, "Reference store"); for (int i=0; i < refs.size(); i++) { Reference ref = refs.get(i); if (ref != null) { Log.i(TAG, ref.whoAmI()); } } } protected synchronized List<String> fetchAllKeys(long time) { ArrayList<String> ret = new ArrayList<String>(); try { Cursor c; c = m_db.query(TABLE_NAME, new String[] {"ref_name", "time_created"}, null, null, null, null, "time_created ASC"); try { int numRows = c.getCount(); c.moveToFirst(); for (int i = 0; i < numRows; ++i) { String name = c.getString(c.getColumnIndex("ref_name")); long timeCreated = c.getLong(c.getColumnIndex("time_created")); String refName = c.getString(c.getColumnIndex("ref_name")); if ((timeCreated > time) || (refName.equals(Reference.CURRENT_REF_FILENAME))) { ret.add(name); } c.moveToNext(); } } finally { c.close(); } } catch (SQLException e) { Log.d(TAG,"SQLite exception: " + e.getLocalizedMessage()); } return ret; } protected List<String> fetchAllLabels(long time) { ArrayList<String> ret = new ArrayList<String>(); Cursor c; try { c = m_db.query(TABLE_NAME, new String[] {"ref_label", "time_created"}, null, null, null, null, "time_created ASC"); try { int numRows = c.getCount(); c.moveToFirst(); for (int i = 0; i < numRows; ++i) { String name = c.getString(c.getColumnIndex("ref_label")); long timeCreated = c.getLong(c.getColumnIndex("time_created")); if (timeCreated > time) { ret.add(name); } c.moveToNext(); } } catch (SQLException e) { Log.d(TAG,"SQLite exception: " + e.getLocalizedMessage()); } finally { c.close(); } } catch (SQLiteException e) { Log.e(TAG, "An error occured: " +e.getMessage()); } return ret; } protected Reference fetchReferenceByKey(String refName) { Reference myRet = null; if (m_db == null) { return myRet; } try { Cursor c; c = m_db.query(TABLE_NAME, COLS, "ref_name='" + refName + "'", null, null, null, null); try { int numRows = c.getCount(); c.moveToFirst(); if (numRows == 1) { // cctor with id, name, command, command_status try { myRet = createReferenceFromRow(c); } catch (Exception e) { Log.e(TAG, "An error occured deserializing the reference: " + e.getMessage()); } } } finally { c.close(); } } catch (SQLException e) { Log.d(TAG,"SQLite exception: " + e.getLocalizedMessage()); } return myRet; } private Reference createReferenceFromRow(Cursor c) { // return Reference.deserialize(c.getBlob(c.getColumnIndex("ref_blob"))); return new Reference(ReferenceDto.unmarshall(c.getBlob(c.getColumnIndex("ref_blob")))); } private void migrateDatabase(SQLiteDatabase db, int fromVersion, int toVersion) { try { // if ((fromVersion == 1)&&(toVersion == 2)) // { deleteDatabase(); createDatabase(db); // } } catch (SQLException e) { Log.d(TAG,"SQLite exception: " + e.getLocalizedMessage()); } } }