Improved some repository code in search for an unclosed cursor
(that I didn't find)
This commit is contained in:
parent
2a1aa736cc
commit
35249a0145
@ -86,8 +86,7 @@ class AndroidAddressRepository(private val sql: SqlHelper) : AddressRepository {
|
|||||||
// you will actually use after this query.
|
// you will actually use after this query.
|
||||||
val projection = arrayOf(COLUMN_ADDRESS)
|
val projection = arrayOf(COLUMN_ADDRESS)
|
||||||
|
|
||||||
val db = sql.readableDatabase
|
sql.readableDatabase.query(
|
||||||
db.query(
|
|
||||||
TABLE_NAME, projection,
|
TABLE_NAME, projection,
|
||||||
where, null, null, null,
|
where, null, null, null,
|
||||||
orderBy
|
orderBy
|
||||||
@ -106,8 +105,7 @@ class AndroidAddressRepository(private val sql: SqlHelper) : AddressRepository {
|
|||||||
// you will actually use after this query.
|
// you will actually use after this query.
|
||||||
val projection = arrayOf(COLUMN_ADDRESS, COLUMN_ALIAS, COLUMN_PUBLIC_KEY, COLUMN_PRIVATE_KEY, COLUMN_SUBSCRIBED, COLUMN_CHAN)
|
val projection = arrayOf(COLUMN_ADDRESS, COLUMN_ALIAS, COLUMN_PUBLIC_KEY, COLUMN_PRIVATE_KEY, COLUMN_SUBSCRIBED, COLUMN_CHAN)
|
||||||
|
|
||||||
val db = sql.readableDatabase
|
sql.readableDatabase.query(
|
||||||
db.query(
|
|
||||||
TABLE_NAME, projection,
|
TABLE_NAME, projection,
|
||||||
where, null, null, null, null
|
where, null, null, null, null
|
||||||
).use { c ->
|
).use { c ->
|
||||||
@ -154,8 +152,7 @@ class AndroidAddressRepository(private val sql: SqlHelper) : AddressRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun exists(address: BitmessageAddress): Boolean {
|
private fun exists(address: BitmessageAddress): Boolean {
|
||||||
val db = sql.readableDatabase
|
sql.readableDatabase.rawQuery(
|
||||||
db.rawQuery(
|
|
||||||
"SELECT COUNT(*) FROM Address WHERE address=?",
|
"SELECT COUNT(*) FROM Address WHERE address=?",
|
||||||
arrayOf(address.address)
|
arrayOf(address.address)
|
||||||
).use { cursor ->
|
).use { cursor ->
|
||||||
@ -165,49 +162,45 @@ class AndroidAddressRepository(private val sql: SqlHelper) : AddressRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun update(address: BitmessageAddress) {
|
private fun update(address: BitmessageAddress) {
|
||||||
val db = sql.writableDatabase
|
|
||||||
// Create a new map of values, where column names are the keys
|
// Create a new map of values, where column names are the keys
|
||||||
val values = getContentValues(address)
|
val values = getContentValues(address)
|
||||||
|
|
||||||
val update = db.update(TABLE_NAME, values, "address=?", arrayOf(address.address))
|
val update = sql.writableDatabase.update(TABLE_NAME, values, "address=?", arrayOf(address.address))
|
||||||
if (update < 0) {
|
if (update < 0) {
|
||||||
LOG.error("Could not update address {}", address)
|
LOG.error("Could not update address {}", address)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun insert(address: BitmessageAddress) {
|
private fun insert(address: BitmessageAddress) {
|
||||||
val db = sql.writableDatabase
|
|
||||||
// Create a new map of values, where column names are the keys
|
// Create a new map of values, where column names are the keys
|
||||||
val values = getContentValues(address)
|
val values = getContentValues(address).apply {
|
||||||
values.put(COLUMN_ADDRESS, address.address)
|
put(COLUMN_ADDRESS, address.address)
|
||||||
values.put(COLUMN_VERSION, address.version)
|
put(COLUMN_VERSION, address.version)
|
||||||
values.put(COLUMN_CHAN, address.isChan)
|
put(COLUMN_CHAN, address.isChan)
|
||||||
|
}
|
||||||
|
|
||||||
val insert = db.insert(TABLE_NAME, null, values)
|
val insert = sql.writableDatabase.insert(TABLE_NAME, null, values)
|
||||||
if (insert < 0) {
|
if (insert < 0) {
|
||||||
LOG.error("Could not insert address {}", address)
|
LOG.error("Could not insert address {}", address)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getContentValues(address: BitmessageAddress): ContentValues {
|
private fun getContentValues(address: BitmessageAddress) = ContentValues().apply {
|
||||||
val values = ContentValues()
|
address.alias?.let { put(COLUMN_ALIAS, it) }
|
||||||
address.alias?.let { values.put(COLUMN_ALIAS, it) }
|
|
||||||
address.pubkey?.let { pubkey ->
|
address.pubkey?.let { pubkey ->
|
||||||
val out = ByteArrayOutputStream()
|
val out = ByteArrayOutputStream()
|
||||||
pubkey.writer().writeUnencrypted(out)
|
pubkey.writer().writeUnencrypted(out)
|
||||||
values.put(COLUMN_PUBLIC_KEY, out.toByteArray())
|
put(COLUMN_PUBLIC_KEY, out.toByteArray())
|
||||||
}
|
}
|
||||||
address.privateKey?.let { values.put(COLUMN_PRIVATE_KEY, Encode.bytes(it)) }
|
address.privateKey?.let { put(COLUMN_PRIVATE_KEY, Encode.bytes(it)) }
|
||||||
if (address.isChan) {
|
if (address.isChan) {
|
||||||
values.put(COLUMN_CHAN, true)
|
put(COLUMN_CHAN, true)
|
||||||
}
|
}
|
||||||
values.put(COLUMN_SUBSCRIBED, address.isSubscribed)
|
put(COLUMN_SUBSCRIBED, address.isSubscribed)
|
||||||
return values
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun remove(address: BitmessageAddress) {
|
override fun remove(address: BitmessageAddress) {
|
||||||
val db = sql.writableDatabase
|
sql.writableDatabase.delete(TABLE_NAME, "address = ?", arrayOf(address.address))
|
||||||
db.delete(TABLE_NAME, "address = ?", arrayOf(address.address))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getAddress(address: String) = find("address = '$address'").firstOrNull()
|
override fun getAddress(address: String) = find("address = '$address'").firstOrNull()
|
||||||
|
@ -57,10 +57,10 @@ class AndroidInventory(private val sql: SqlHelper) : Inventory {
|
|||||||
cache.put(stream, result)
|
cache.put(stream, result)
|
||||||
|
|
||||||
val projection = arrayOf(COLUMN_HASH, COLUMN_EXPIRES)
|
val projection = arrayOf(COLUMN_HASH, COLUMN_EXPIRES)
|
||||||
val db = sql.readableDatabase
|
|
||||||
db.query(
|
sql.readableDatabase.query(
|
||||||
TABLE_NAME, projection,
|
TABLE_NAME, projection,
|
||||||
"stream = $stream", null, null, null, null
|
"stream = $stream", null, null, null, null
|
||||||
).use { c ->
|
).use { c ->
|
||||||
while (c.moveToNext()) {
|
while (c.moveToNext()) {
|
||||||
val blob = c.getBlob(c.getColumnIndex(COLUMN_HASH))
|
val blob = c.getBlob(c.getColumnIndex(COLUMN_HASH))
|
||||||
@ -84,10 +84,9 @@ class AndroidInventory(private val sql: SqlHelper) : Inventory {
|
|||||||
// you will actually use after this query.
|
// you will actually use after this query.
|
||||||
val projection = arrayOf(COLUMN_VERSION, COLUMN_DATA)
|
val projection = arrayOf(COLUMN_VERSION, COLUMN_DATA)
|
||||||
|
|
||||||
val db = sql.readableDatabase
|
sql.readableDatabase.query(
|
||||||
db.query(
|
TABLE_NAME, projection,
|
||||||
TABLE_NAME, projection,
|
"hash = X'$vector'", null, null, null, null
|
||||||
"hash = X'$vector'", null, null, null, null
|
|
||||||
).use { c ->
|
).use { c ->
|
||||||
if (!c.moveToFirst()) {
|
if (!c.moveToFirst()) {
|
||||||
LOG.info("Object requested that we don't have. IV: {}", vector)
|
LOG.info("Object requested that we don't have. IV: {}", vector)
|
||||||
@ -115,11 +114,10 @@ class AndroidInventory(private val sql: SqlHelper) : Inventory {
|
|||||||
where.append(" AND type IN (").append(types.joinToString(separator = "', '", prefix = "'", postfix = "'", transform = { it.number.toString() })).append(")")
|
where.append(" AND type IN (").append(types.joinToString(separator = "', '", prefix = "'", postfix = "'", transform = { it.number.toString() })).append(")")
|
||||||
}
|
}
|
||||||
|
|
||||||
val db = sql.readableDatabase
|
|
||||||
val result = LinkedList<ObjectMessage>()
|
val result = LinkedList<ObjectMessage>()
|
||||||
db.query(
|
sql.readableDatabase.query(
|
||||||
TABLE_NAME, projection,
|
TABLE_NAME, projection,
|
||||||
where.toString(), null, null, null, null
|
where.toString(), null, null, null, null
|
||||||
).use { c ->
|
).use { c ->
|
||||||
while (c.moveToNext()) {
|
while (c.moveToNext()) {
|
||||||
val objectVersion = c.getInt(c.getColumnIndex(COLUMN_VERSION))
|
val objectVersion = c.getInt(c.getColumnIndex(COLUMN_VERSION))
|
||||||
@ -139,31 +137,29 @@ class AndroidInventory(private val sql: SqlHelper) : Inventory {
|
|||||||
LOG.trace("Storing object {}", iv)
|
LOG.trace("Storing object {}", iv)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val db = sql.writableDatabase
|
|
||||||
// Create a new map of values, where column names are the keys
|
// Create a new map of values, where column names are the keys
|
||||||
val values = ContentValues()
|
val values = ContentValues().apply {
|
||||||
values.put(COLUMN_HASH, objectMessage.inventoryVector.hash)
|
put(COLUMN_HASH, objectMessage.inventoryVector.hash)
|
||||||
values.put(COLUMN_STREAM, objectMessage.stream)
|
put(COLUMN_STREAM, objectMessage.stream)
|
||||||
values.put(COLUMN_EXPIRES, objectMessage.expiresTime)
|
put(COLUMN_EXPIRES, objectMessage.expiresTime)
|
||||||
values.put(COLUMN_DATA, Encode.bytes(objectMessage))
|
put(COLUMN_DATA, Encode.bytes(objectMessage))
|
||||||
values.put(COLUMN_TYPE, objectMessage.type)
|
put(COLUMN_TYPE, objectMessage.type)
|
||||||
values.put(COLUMN_VERSION, objectMessage.version)
|
put(COLUMN_VERSION, objectMessage.version)
|
||||||
|
}
|
||||||
|
|
||||||
db.insertOrThrow(TABLE_NAME, null, values)
|
sql.writableDatabase.insertOrThrow(TABLE_NAME, null, values)
|
||||||
|
|
||||||
getCache(objectMessage.stream).put(iv, objectMessage.expiresTime)
|
getCache(objectMessage.stream).put(iv, objectMessage.expiresTime)
|
||||||
} catch (e: SQLiteConstraintException) {
|
} catch (e: SQLiteConstraintException) {
|
||||||
LOG.trace(e.message, e)
|
LOG.trace(e.message, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun contains(objectMessage: ObjectMessage) = getCache(objectMessage.stream).keys.contains(objectMessage.inventoryVector)
|
override fun contains(objectMessage: ObjectMessage) = getCache(objectMessage.stream).keys.contains(objectMessage.inventoryVector)
|
||||||
|
|
||||||
override fun cleanup() {
|
override fun cleanup() {
|
||||||
val fiveMinutesAgo = now - 5 * MINUTE
|
val fiveMinutesAgo = now - 5 * MINUTE
|
||||||
val db = sql.writableDatabase
|
sql.writableDatabase.delete(TABLE_NAME, "expires < ?", arrayOf(fiveMinutesAgo.toString()))
|
||||||
db.delete(TABLE_NAME, "expires < ?", arrayOf(fiveMinutesAgo.toString()))
|
|
||||||
|
|
||||||
cache.values.map { it.entries }.forEach { entries -> entries.removeAll { it.value < fiveMinutesAgo } }
|
cache.values.map { it.entries }.forEach { entries -> entries.removeAll { it.value < fiveMinutesAgo } }
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,6 @@ package ch.dissem.apps.abit.repository
|
|||||||
import android.content.ContentValues
|
import android.content.ContentValues
|
||||||
import android.database.Cursor
|
import android.database.Cursor
|
||||||
import android.database.DatabaseUtils
|
import android.database.DatabaseUtils
|
||||||
import android.database.sqlite.SQLiteConstraintException
|
|
||||||
import android.database.sqlite.SQLiteDatabase
|
import android.database.sqlite.SQLiteDatabase
|
||||||
import ch.dissem.apps.abit.repository.AndroidLabelRepository.Companion.LABEL_ARCHIVE
|
import ch.dissem.apps.abit.repository.AndroidLabelRepository.Companion.LABEL_ARCHIVE
|
||||||
import ch.dissem.apps.abit.util.UuidUtils
|
import ch.dissem.apps.abit.util.UuidUtils
|
||||||
@ -29,7 +28,6 @@ import ch.dissem.bitmessage.entity.Plaintext
|
|||||||
import ch.dissem.bitmessage.entity.valueobject.InventoryVector
|
import ch.dissem.bitmessage.entity.valueobject.InventoryVector
|
||||||
import ch.dissem.bitmessage.entity.valueobject.Label
|
import ch.dissem.bitmessage.entity.valueobject.Label
|
||||||
import ch.dissem.bitmessage.ports.AbstractMessageRepository
|
import ch.dissem.bitmessage.ports.AbstractMessageRepository
|
||||||
import ch.dissem.bitmessage.ports.AlreadyStoredException
|
|
||||||
import ch.dissem.bitmessage.ports.MessageRepository
|
import ch.dissem.bitmessage.ports.MessageRepository
|
||||||
import ch.dissem.bitmessage.utils.Encode
|
import ch.dissem.bitmessage.utils.Encode
|
||||||
import ch.dissem.bitmessage.utils.Strings.hex
|
import ch.dissem.bitmessage.utils.Strings.hex
|
||||||
@ -137,8 +135,7 @@ class AndroidMessageRepository(private val sql: SqlHelper) : AbstractMessageRepo
|
|||||||
// you will actually use after this query.
|
// you will actually use after this query.
|
||||||
val projection = arrayOf(COLUMN_ID, COLUMN_IV, COLUMN_TYPE, COLUMN_SENDER, COLUMN_RECIPIENT, COLUMN_DATA, COLUMN_ACK_DATA, COLUMN_SENT, COLUMN_RECEIVED, COLUMN_STATUS, COLUMN_TTL, COLUMN_RETRIES, COLUMN_NEXT_TRY, COLUMN_CONVERSATION)
|
val projection = arrayOf(COLUMN_ID, COLUMN_IV, COLUMN_TYPE, COLUMN_SENDER, COLUMN_RECIPIENT, COLUMN_DATA, COLUMN_ACK_DATA, COLUMN_SENT, COLUMN_RECEIVED, COLUMN_STATUS, COLUMN_TTL, COLUMN_RETRIES, COLUMN_NEXT_TRY, COLUMN_CONVERSATION)
|
||||||
|
|
||||||
val db = sql.readableDatabase
|
sql.readableDatabase.query(
|
||||||
db.query(
|
|
||||||
TABLE_NAME, projection,
|
TABLE_NAME, projection,
|
||||||
where, null, null, null,
|
where, null, null, null,
|
||||||
"$COLUMN_RECEIVED DESC, $COLUMN_SENT DESC",
|
"$COLUMN_RECEIVED DESC, $COLUMN_SENT DESC",
|
||||||
@ -206,23 +203,21 @@ class AndroidMessageRepository(private val sql: SqlHelper) : AbstractMessageRepo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getValues(message: Plaintext): ContentValues {
|
private fun getValues(message: Plaintext) = ContentValues(14).apply {
|
||||||
val values = ContentValues()
|
put(COLUMN_IV, message.inventoryVector?.hash)
|
||||||
values.put(COLUMN_IV, message.inventoryVector?.hash)
|
put(COLUMN_TYPE, message.type.name)
|
||||||
values.put(COLUMN_TYPE, message.type.name)
|
put(COLUMN_SENDER, message.from.address)
|
||||||
values.put(COLUMN_SENDER, message.from.address)
|
put(COLUMN_RECIPIENT, message.to?.address)
|
||||||
values.put(COLUMN_RECIPIENT, message.to?.address)
|
put(COLUMN_DATA, Encode.bytes(message))
|
||||||
values.put(COLUMN_DATA, Encode.bytes(message))
|
put(COLUMN_ACK_DATA, message.ackData)
|
||||||
values.put(COLUMN_ACK_DATA, message.ackData)
|
put(COLUMN_SENT, message.sent)
|
||||||
values.put(COLUMN_SENT, message.sent)
|
put(COLUMN_RECEIVED, message.received)
|
||||||
values.put(COLUMN_RECEIVED, message.received)
|
put(COLUMN_STATUS, message.status.name)
|
||||||
values.put(COLUMN_STATUS, message.status.name)
|
put(COLUMN_INITIAL_HASH, message.initialHash)
|
||||||
values.put(COLUMN_INITIAL_HASH, message.initialHash)
|
put(COLUMN_TTL, message.ttl)
|
||||||
values.put(COLUMN_TTL, message.ttl)
|
put(COLUMN_RETRIES, message.retries)
|
||||||
values.put(COLUMN_RETRIES, message.retries)
|
put(COLUMN_NEXT_TRY, message.nextTry)
|
||||||
values.put(COLUMN_NEXT_TRY, message.nextTry)
|
put(COLUMN_CONVERSATION, UuidUtils.asBytes(message.conversationId))
|
||||||
values.put(COLUMN_CONVERSATION, UuidUtils.asBytes(message.conversationId))
|
|
||||||
return values
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun insert(db: SQLiteDatabase, message: Plaintext) {
|
private fun insert(db: SQLiteDatabase, message: Plaintext) {
|
||||||
@ -235,8 +230,7 @@ class AndroidMessageRepository(private val sql: SqlHelper) : AbstractMessageRepo
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun remove(message: Plaintext) {
|
override fun remove(message: Plaintext) {
|
||||||
val db = sql.writableDatabase
|
sql.writableDatabase.delete(TABLE_NAME, "id = ?", arrayOf(message.id.toString()))
|
||||||
db.delete(TABLE_NAME, "id = ?", arrayOf(message.id.toString()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -5,7 +5,6 @@ import android.database.sqlite.SQLiteConstraintException
|
|||||||
import android.database.sqlite.SQLiteDoneException
|
import android.database.sqlite.SQLiteDoneException
|
||||||
import android.database.sqlite.SQLiteStatement
|
import android.database.sqlite.SQLiteStatement
|
||||||
import ch.dissem.bitmessage.entity.valueobject.NetworkAddress
|
import ch.dissem.bitmessage.entity.valueobject.NetworkAddress
|
||||||
import ch.dissem.bitmessage.exception.ApplicationException
|
|
||||||
import ch.dissem.bitmessage.ports.NodeRegistry
|
import ch.dissem.bitmessage.ports.NodeRegistry
|
||||||
import ch.dissem.bitmessage.ports.NodeRegistryHelper.loadStableNodes
|
import ch.dissem.bitmessage.ports.NodeRegistryHelper.loadStableNodes
|
||||||
import ch.dissem.bitmessage.utils.Collections
|
import ch.dissem.bitmessage.utils.Collections
|
||||||
@ -120,19 +119,20 @@ class AndroidNodeRegistry(private val sql: SqlHelper) : NodeRegistry {
|
|||||||
private fun insert(node: NetworkAddress) {
|
private fun insert(node: NetworkAddress) {
|
||||||
try {
|
try {
|
||||||
// Create a new map of values, where column names are the keys
|
// Create a new map of values, where column names are the keys
|
||||||
val values = ContentValues()
|
val values = ContentValues().apply {
|
||||||
values.put(COLUMN_STREAM, node.stream)
|
put(COLUMN_STREAM, node.stream)
|
||||||
values.put(COLUMN_ADDRESS, node.IPv6)
|
put(COLUMN_ADDRESS, node.IPv6)
|
||||||
values.put(COLUMN_PORT, node.port)
|
put(COLUMN_PORT, node.port)
|
||||||
values.put(COLUMN_SERVICES, node.services)
|
put(COLUMN_SERVICES, node.services)
|
||||||
values.put(COLUMN_TIME,
|
put(COLUMN_TIME,
|
||||||
if (node.time > UnixTime.now) {
|
if (node.time > UnixTime.now) {
|
||||||
// This might be an attack, let's not use those nodes with priority
|
// This might be an attack, let's not use those nodes with priority
|
||||||
UnixTime.now - 7 * UnixTime.DAY
|
UnixTime.now - 7 * UnixTime.DAY
|
||||||
} else {
|
} else {
|
||||||
node.time
|
node.time
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
sql.writableDatabase.insertOrThrow(TABLE_NAME, null, values)
|
sql.writableDatabase.insertOrThrow(TABLE_NAME, null, values)
|
||||||
} catch (e: SQLiteConstraintException) {
|
} catch (e: SQLiteConstraintException) {
|
||||||
@ -150,9 +150,10 @@ class AndroidNodeRegistry(private val sql: SqlHelper) : NodeRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a new map of values, where column names are the keys
|
// Create a new map of values, where column names are the keys
|
||||||
val values = ContentValues()
|
val values = ContentValues().apply {
|
||||||
values.put(COLUMN_SERVICES, node.services)
|
put(COLUMN_SERVICES, node.services)
|
||||||
values.put(COLUMN_TIME, max(node.time, time))
|
put(COLUMN_TIME, max(node.time, time))
|
||||||
|
}
|
||||||
|
|
||||||
sql.writableDatabase.update(
|
sql.writableDatabase.update(
|
||||||
TABLE_NAME,
|
TABLE_NAME,
|
||||||
|
@ -48,28 +48,27 @@ class AndroidProofOfWorkRepository(private val sql: SqlHelper) : ProofOfWorkRepo
|
|||||||
// you will actually use after this query.
|
// you will actually use after this query.
|
||||||
val projection = arrayOf(COLUMN_DATA, COLUMN_VERSION, COLUMN_NONCE_TRIALS_PER_BYTE, COLUMN_EXTRA_BYTES, COLUMN_EXPIRATION_TIME, COLUMN_MESSAGE_ID)
|
val projection = arrayOf(COLUMN_DATA, COLUMN_VERSION, COLUMN_NONCE_TRIALS_PER_BYTE, COLUMN_EXTRA_BYTES, COLUMN_EXPIRATION_TIME, COLUMN_MESSAGE_ID)
|
||||||
|
|
||||||
val db = sql.readableDatabase
|
sql.readableDatabase.query(
|
||||||
db.query(
|
TABLE_NAME, projection,
|
||||||
TABLE_NAME, projection,
|
"initial_hash=X'${hex(initialHash)}'",
|
||||||
"initial_hash=X'${hex(initialHash)}'",
|
null, null, null, null
|
||||||
null, null, null, null
|
|
||||||
).use { c ->
|
).use { c ->
|
||||||
if (c.moveToFirst()) {
|
if (c.moveToFirst()) {
|
||||||
val version = c.getInt(c.getColumnIndex(COLUMN_VERSION))
|
val version = c.getInt(c.getColumnIndex(COLUMN_VERSION))
|
||||||
val blob = c.getBlob(c.getColumnIndex(COLUMN_DATA))
|
val blob = c.getBlob(c.getColumnIndex(COLUMN_DATA))
|
||||||
return if (c.isNull(c.getColumnIndex(COLUMN_MESSAGE_ID))) {
|
return if (c.isNull(c.getColumnIndex(COLUMN_MESSAGE_ID))) {
|
||||||
ProofOfWorkRepository.Item(
|
ProofOfWorkRepository.Item(
|
||||||
Factory.getObjectMessage(version, ByteArrayInputStream(blob), blob.size) ?: throw RuntimeException("Invalid object in repository"),
|
Factory.getObjectMessage(version, ByteArrayInputStream(blob), blob.size) ?: throw RuntimeException("Invalid object in repository"),
|
||||||
c.getLong(c.getColumnIndex(COLUMN_NONCE_TRIALS_PER_BYTE)),
|
c.getLong(c.getColumnIndex(COLUMN_NONCE_TRIALS_PER_BYTE)),
|
||||||
c.getLong(c.getColumnIndex(COLUMN_EXTRA_BYTES))
|
c.getLong(c.getColumnIndex(COLUMN_EXTRA_BYTES))
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
ProofOfWorkRepository.Item(
|
ProofOfWorkRepository.Item(
|
||||||
Factory.getObjectMessage(version, ByteArrayInputStream(blob), blob.size) ?: throw RuntimeException("Invalid object in repository"),
|
Factory.getObjectMessage(version, ByteArrayInputStream(blob), blob.size) ?: throw RuntimeException("Invalid object in repository"),
|
||||||
c.getLong(c.getColumnIndex(COLUMN_NONCE_TRIALS_PER_BYTE)),
|
c.getLong(c.getColumnIndex(COLUMN_NONCE_TRIALS_PER_BYTE)),
|
||||||
c.getLong(c.getColumnIndex(COLUMN_EXTRA_BYTES)),
|
c.getLong(c.getColumnIndex(COLUMN_EXTRA_BYTES)),
|
||||||
c.getLong(c.getColumnIndex(COLUMN_EXPIRATION_TIME)),
|
c.getLong(c.getColumnIndex(COLUMN_EXPIRATION_TIME)),
|
||||||
bmc.messageRepository.getMessage(c.getLong(c.getColumnIndex(COLUMN_MESSAGE_ID)))
|
bmc.messageRepository.getMessage(c.getLong(c.getColumnIndex(COLUMN_MESSAGE_ID)))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -82,10 +81,9 @@ class AndroidProofOfWorkRepository(private val sql: SqlHelper) : ProofOfWorkRepo
|
|||||||
// you will actually use after this query.
|
// you will actually use after this query.
|
||||||
val projection = arrayOf(COLUMN_INITIAL_HASH)
|
val projection = arrayOf(COLUMN_INITIAL_HASH)
|
||||||
|
|
||||||
val db = sql.readableDatabase
|
|
||||||
val result = LinkedList<ByteArray>()
|
val result = LinkedList<ByteArray>()
|
||||||
db.query(
|
sql.readableDatabase.query(
|
||||||
TABLE_NAME, projection, null, null, null, null, null
|
TABLE_NAME, projection, null, null, null, null, null
|
||||||
).use { c ->
|
).use { c ->
|
||||||
while (c.moveToNext()) {
|
while (c.moveToNext()) {
|
||||||
val initialHash = c.getBlob(c.getColumnIndex(COLUMN_INITIAL_HASH))
|
val initialHash = c.getBlob(c.getColumnIndex(COLUMN_INITIAL_HASH))
|
||||||
@ -97,20 +95,20 @@ class AndroidProofOfWorkRepository(private val sql: SqlHelper) : ProofOfWorkRepo
|
|||||||
|
|
||||||
override fun putObject(item: ProofOfWorkRepository.Item) {
|
override fun putObject(item: ProofOfWorkRepository.Item) {
|
||||||
try {
|
try {
|
||||||
val db = sql.writableDatabase
|
|
||||||
// Create a new map of values, where column names are the keys
|
// Create a new map of values, where column names are the keys
|
||||||
val values = ContentValues()
|
val values = ContentValues().apply {
|
||||||
values.put(COLUMN_INITIAL_HASH, cryptography().getInitialHash(item.objectMessage))
|
put(COLUMN_INITIAL_HASH, cryptography().getInitialHash(item.objectMessage))
|
||||||
values.put(COLUMN_DATA, Encode.bytes(item.objectMessage))
|
put(COLUMN_DATA, Encode.bytes(item.objectMessage))
|
||||||
values.put(COLUMN_VERSION, item.objectMessage.version)
|
put(COLUMN_VERSION, item.objectMessage.version)
|
||||||
values.put(COLUMN_NONCE_TRIALS_PER_BYTE, item.nonceTrialsPerByte)
|
put(COLUMN_NONCE_TRIALS_PER_BYTE, item.nonceTrialsPerByte)
|
||||||
values.put(COLUMN_EXTRA_BYTES, item.extraBytes)
|
put(COLUMN_EXTRA_BYTES, item.extraBytes)
|
||||||
item.message?.let { message ->
|
item.message?.let { message ->
|
||||||
values.put(COLUMN_EXPIRATION_TIME, item.expirationTime)
|
put(COLUMN_EXPIRATION_TIME, item.expirationTime)
|
||||||
values.put(COLUMN_MESSAGE_ID, message.id as Long?)
|
put(COLUMN_MESSAGE_ID, message.id as Long?)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
db.insertOrThrow(TABLE_NAME, null, values)
|
sql.writableDatabase.insertOrThrow(TABLE_NAME, null, values)
|
||||||
} catch (e: SQLiteConstraintException) {
|
} catch (e: SQLiteConstraintException) {
|
||||||
LOG.trace(e.message, e)
|
LOG.trace(e.message, e)
|
||||||
}
|
}
|
||||||
@ -121,8 +119,7 @@ class AndroidProofOfWorkRepository(private val sql: SqlHelper) : ProofOfWorkRepo
|
|||||||
putObject(ProofOfWorkRepository.Item(objectMessage, nonceTrialsPerByte, extraBytes))
|
putObject(ProofOfWorkRepository.Item(objectMessage, nonceTrialsPerByte, extraBytes))
|
||||||
|
|
||||||
override fun removeObject(initialHash: ByteArray) {
|
override fun removeObject(initialHash: ByteArray) {
|
||||||
val db = sql.writableDatabase
|
sql.writableDatabase.delete(TABLE_NAME, "initial_hash=X'${hex(initialHash)}'", null)
|
||||||
db.delete(TABLE_NAME, "initial_hash=X'${hex(initialHash)}'", null)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -32,42 +32,42 @@ class SqlHelper(private val ctx: Context) : SQLiteOpenHelper(ctx, DATABASE_NAME,
|
|||||||
override fun onCreate(db: SQLiteDatabase) = onUpgrade(db, 0, DATABASE_VERSION)
|
override fun onCreate(db: SQLiteDatabase) = onUpgrade(db, 0, DATABASE_VERSION)
|
||||||
|
|
||||||
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) = mapOf(
|
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) = mapOf(
|
||||||
0 to {
|
0 to {
|
||||||
executeMigration(db, "V1.0__Create_table_inventory")
|
executeMigration(db, "V1.0__Create_table_inventory")
|
||||||
executeMigration(db, "V1.1__Create_table_address")
|
executeMigration(db, "V1.1__Create_table_address")
|
||||||
executeMigration(db, "V1.2__Create_table_message")
|
executeMigration(db, "V1.2__Create_table_message")
|
||||||
},
|
},
|
||||||
1 to {
|
1 to {
|
||||||
// executeMigration(db, "V2.0__Update_table_message");
|
// executeMigration(db, "V2.0__Update_table_message");
|
||||||
executeMigration(db, "V2.1__Create_table_POW")
|
executeMigration(db, "V2.1__Create_table_POW")
|
||||||
},
|
},
|
||||||
2 to {
|
2 to {
|
||||||
executeMigration(db, "V3.0__Update_table_address")
|
executeMigration(db, "V3.0__Update_table_address")
|
||||||
},
|
},
|
||||||
3 to {
|
3 to {
|
||||||
executeMigration(db, "V3.1__Update_table_POW")
|
executeMigration(db, "V3.1__Update_table_POW")
|
||||||
executeMigration(db, "V3.2__Update_table_message")
|
executeMigration(db, "V3.2__Update_table_message")
|
||||||
},
|
},
|
||||||
4 to {
|
4 to {
|
||||||
executeMigration(db, "V3.3__Create_table_node")
|
executeMigration(db, "V3.3__Create_table_node")
|
||||||
},
|
},
|
||||||
5 to {
|
5 to {
|
||||||
executeMigration(db, "V3.4__Add_label_outbox")
|
executeMigration(db, "V3.4__Add_label_outbox")
|
||||||
},
|
},
|
||||||
6 to {
|
6 to {
|
||||||
executeMigration(db, "V4.0__Create_table_message_parent")
|
executeMigration(db, "V4.0__Create_table_message_parent")
|
||||||
},
|
},
|
||||||
7 to {
|
7 to {
|
||||||
setMissingConversationIds(db)
|
setMissingConversationIds(db)
|
||||||
}
|
}
|
||||||
).filterKeys { it in oldVersion until newVersion }.forEach { (_, v) -> v.invoke() }
|
).filterKeys { it in oldVersion until newVersion }.forEach { (_, v) -> v.invoke() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set UUIDs for all messages that have no conversation ID
|
* Set UUIDs for all messages that have no conversation ID
|
||||||
*/
|
*/
|
||||||
private fun setMissingConversationIds(db: SQLiteDatabase) = db.query(
|
private fun setMissingConversationIds(db: SQLiteDatabase) = db.query(
|
||||||
"Message", arrayOf("id"),
|
"Message", arrayOf("id"),
|
||||||
"conversation IS NULL", null, null, null, null
|
"conversation IS NULL", null, null, null, null
|
||||||
).use { c ->
|
).use { c ->
|
||||||
while (c.moveToNext()) {
|
while (c.moveToNext()) {
|
||||||
val id = c.getLong(0)
|
val id = c.getLong(0)
|
||||||
@ -76,8 +76,9 @@ class SqlHelper(private val ctx: Context) : SQLiteOpenHelper(ctx, DATABASE_NAME,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun setMissingConversationId(id: Long, db: SQLiteDatabase) {
|
private fun setMissingConversationId(id: Long, db: SQLiteDatabase) {
|
||||||
val values = ContentValues(1)
|
val values = ContentValues(1).apply {
|
||||||
values.put("conversation", UuidUtils.asBytes(UUID.randomUUID()))
|
put("conversation", UuidUtils.asBytes(UUID.randomUUID()))
|
||||||
|
}
|
||||||
db.update("Message", values, "id=?", arrayOf(id.toString()))
|
db.update("Message", values, "id=?", arrayOf(id.toString()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user