Example usage for android.database.sqlite SQLiteDatabase endTransaction

List of usage examples for android.database.sqlite SQLiteDatabase endTransaction

Introduction

In this page you can find the example usage for android.database.sqlite SQLiteDatabase endTransaction.

Prototype

public void endTransaction() 

Source Link

Document

End a transaction.

Usage

From source file:org.opendatakit.common.android.utilities.ODKDatabaseUtils.java

/**
 * Insert or update a list of table-level metadata KVS entries. If clear is
 * true, then delete the existing set of values for this tableId before
 * inserting the new values.//from  w ww  . j  ava2  s .c om
 * 
 * @param db
 * @param tableId
 * @param metadata
 *          a List<KeyValueStoreEntry>
 * @param clear
 *          if true then delete the existing set of values for this tableId
 *          before inserting the new ones.
 */
public void replaceDBTableMetadata(SQLiteDatabase db, String tableId, List<KeyValueStoreEntry> metadata,
        boolean clear) {

    boolean dbWithinTransaction = db.inTransaction();
    try {
        if (!dbWithinTransaction) {
            db.beginTransaction();
        }

        if (clear) {
            db.delete(DatabaseConstants.KEY_VALUE_STORE_ACTIVE_TABLE_NAME, KeyValueStoreColumns.TABLE_ID + "=?",
                    new String[] { tableId });
        }
        for (KeyValueStoreEntry e : metadata) {
            ContentValues values = new ContentValues();
            if (!tableId.equals(e.tableId)) {
                throw new IllegalArgumentException(
                        "updateDBTableMetadata: expected all kvs entries to share the same tableId");
            }
            if (e.value == null || e.value.trim().length() == 0) {
                deleteDBTableMetadata(db, e.tableId, e.partition, e.aspect, e.key);
            } else {
                values.put(KeyValueStoreColumns.TABLE_ID, e.tableId);
                values.put(KeyValueStoreColumns.PARTITION, e.partition);
                values.put(KeyValueStoreColumns.ASPECT, e.aspect);
                values.put(KeyValueStoreColumns.KEY, e.key);
                values.put(KeyValueStoreColumns.VALUE_TYPE, e.type);
                values.put(KeyValueStoreColumns.VALUE, e.value);
                db.replace(DatabaseConstants.KEY_VALUE_STORE_ACTIVE_TABLE_NAME, null, values);
            }
        }

        if (!dbWithinTransaction) {
            db.setTransactionSuccessful();
        }
    } finally {
        if (!dbWithinTransaction) {
            db.endTransaction();
        }
    }
}

From source file:ru.orangesoftware.financisto2.db.DatabaseAdapter.java

/**
 * Re-populates running_balance for specific account
 *
 * @param account selected account/*  w  w w.  ja v a 2 s .c  o  m*/
 */
public void rebuildRunningBalanceForAccount(Account account) {
    SQLiteDatabase db = db();
    db.beginTransaction();
    try {
        String accountId = String.valueOf(account.getId());
        db.execSQL("delete from running_balance where account_id=?", new Object[] { accountId });
        WhereFilter filter = new WhereFilter("");
        filter.put(Criteria.eq(BlotterFilter.FROM_ACCOUNT_ID, accountId));
        filter.asc("datetime");
        filter.asc("_id");
        Cursor c = getBlotterForAccountWithSplits(filter);
        Object[] values = new Object[4];
        values[0] = accountId;
        try {
            long balance = 0;
            while (c.moveToNext()) {
                long parentId = c.getLong(BlotterColumns.parent_id.ordinal());
                int isTransfer = c.getInt(BlotterColumns.is_transfer.ordinal());
                if (parentId > 0) {
                    if (isTransfer >= 0) {
                        // we only interested in the second part of the transfer-split
                        // which is marked with is_transfer=-1 (see v_blotter_for_account_with_splits)
                        continue;
                    }
                }
                long fromAccountId = c.getLong(BlotterColumns.from_account_id.ordinal());
                long toAccountId = c.getLong(BlotterColumns.to_account_id.ordinal());
                if (toAccountId > 0 && toAccountId == fromAccountId) {
                    // weird bug when a transfer is done from an account to the same account
                    continue;
                }
                balance += c.getLong(DatabaseHelper.BlotterColumns.from_amount.ordinal());
                values[1] = c.getString(DatabaseHelper.BlotterColumns._id.ordinal());
                values[2] = c.getString(DatabaseHelper.BlotterColumns.datetime.ordinal());
                values[3] = balance;
                db.execSQL(
                        "insert into running_balance(account_id,transaction_id,datetime,balance) values (?,?,?,?)",
                        values);
            }
        } finally {
            c.close();
        }
        updateAccountLastTransactionDate(account.id);
        db.setTransactionSuccessful();
    } finally {
        db.endTransaction();
    }
}

From source file:com.google.android.apps.santatracker.service.APIProcessor.java

private int processRoute(JSONArray json) {
    SQLiteDatabase db = mDestinationDBHelper.getWritableDatabase();

    db.beginTransaction();/*from  w  w  w  .  j  av  a 2s .  com*/
    try {
        // loop over each destination
        long previousPresents = mPreferences.getTotalPresents();

        int i;
        for (i = 0; i < json.length(); i++) {
            JSONObject dest = json.getJSONObject(i);

            JSONObject location = dest.getJSONObject(FIELD_DETAILS_LOCATION);

            long presentsTotal = dest.getLong(FIELD_DETAILS_PRESENTSDELIVERED);
            long presents = presentsTotal - previousPresents;
            previousPresents = presentsTotal;

            // Name
            String city = dest.getString(FIELD_DETAILS_CITY);
            String region = null;
            String country = null;

            if (dest.has(FIELD_DETAILS_REGION)) {
                region = dest.getString(FIELD_DETAILS_REGION);
                if (region.length() < 1) {
                    region = null;
                }
            }
            if (dest.has(FIELD_DETAILS_COUNTRY)) {
                country = dest.getString(FIELD_DETAILS_COUNTRY);
                if (country.length() < 1) {
                    country = null;
                }
            }

            //                if (mDebugLog) {
            //                    Log.d(TAG, "Location: " + city);
            //                }

            // Detail fields
            JSONObject details = dest.getJSONObject(FIELD_DETAILS_DETAILS);
            long timezone = details.isNull(FIELD_DETAILS_TIMEZONE) ? 0L
                    : details.getLong(FIELD_DETAILS_TIMEZONE);
            long altitude = details.getLong(FIELD_DETAILS_ALTITUDE);
            String photos = details.has(FIELD_DETAILS_PHOTOS) ? details.getString(FIELD_DETAILS_PHOTOS)
                    : EMPTY_STRING;
            String weather = details.has(FIELD_DETAILS_WEATHER) ? details.getString(FIELD_DETAILS_WEATHER)
                    : EMPTY_STRING;
            String streetview = details.has(FIELD_DETAILS_STREETVIEW)
                    ? details.getString(FIELD_DETAILS_STREETVIEW)
                    : EMPTY_STRING;
            String gmmStreetview = details.has(FIELD_DETAILS_GMMSTREETVIEW)
                    ? details.getString(FIELD_DETAILS_GMMSTREETVIEW)
                    : EMPTY_STRING;

            try {
                // All parsed, insert into DB
                mDestinationDBHelper.insertDestination(db, dest.getString(FIELD_IDENTIFIER),
                        dest.getLong(FIELD_ARRIVAL), dest.getLong(FIELD_DEPARTURE),

                        city, region, country,

                        location.getDouble(FIELD_DETAILS_LOCATION_LAT),
                        location.getDouble(FIELD_DETAILS_LOCATION_LNG), presentsTotal, presents, timezone,
                        altitude, photos, weather, streetview, gmmStreetview);
            } catch (android.database.sqlite.SQLiteConstraintException e) {
                // ignore duplicate locations
            }
        }

        db.setTransactionSuccessful();
        // Update mPreferences
        mPreferences.setDBTimestamp(System.currentTimeMillis());
        mPreferences.setTotalPresents(previousPresents);
        return i;
    } catch (JSONException e) {
        Log.d(TAG, "Santa location tracking error 30");
        SantaLog.d(TAG, "JSON Exception", e);
    } finally {
        db.endTransaction();
    }

    return 0;
}

From source file:org.opendatakit.common.android.provider.impl.InstanceProviderImpl.java

@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    List<String> segments = uri.getPathSegments();

    if (segments.size() < 2 || segments.size() > 3) {
        throw new SQLException("Unknown URI (too many segments!) " + uri);
    }/*from   ww  w.  ja  v a 2s  .  c  o  m*/

    String appName = segments.get(0);
    ODKFileUtils.verifyExternalStorageAvailability();
    ODKFileUtils.assertDirectoryStructure(appName);
    String tableId = segments.get(1);
    String instanceName = null;
    // _ID in UPLOADS_TABLE_NAME
    String instanceId = (segments.size() == 3 ? segments.get(2) : null);

    SQLiteDatabase db = null;
    String fullQuery;
    String filterArgs[];
    Cursor c = null;

    String dbTableName;
    List<ColumnDefinition> orderedDefns;

    StringBuilder b = new StringBuilder();

    try {
        db = DatabaseFactory.get().getDatabase(getContext(), appName);
        db.beginTransaction();

        boolean success = false;
        try {
            success = ODKDatabaseUtils.get().hasTableId(db, tableId);
        } catch (Exception e) {
            e.printStackTrace();
            throw new SQLException("Unknown URI (exception testing for tableId) " + uri);
        }
        if (!success) {
            throw new SQLException("Unknown URI (missing data table for tableId) " + uri);
        }

        dbTableName = "\"" + tableId + "\"";

        try {
            c = db.query(DatabaseConstants.KEY_VALUE_STORE_ACTIVE_TABLE_NAME,
                    new String[] { KeyValueStoreColumns.VALUE },
                    KeyValueStoreColumns.TABLE_ID + "=? AND " + KeyValueStoreColumns.PARTITION + "=? AND "
                            + KeyValueStoreColumns.ASPECT + "=? AND " + KeyValueStoreColumns.KEY + "=?",
                    new String[] { tableId, KeyValueStoreConstants.PARTITION_TABLE,
                            KeyValueStoreConstants.ASPECT_DEFAULT, KeyValueStoreConstants.XML_INSTANCE_NAME },
                    null, null, null);

            if (c.getCount() == 1) {
                c.moveToFirst();
                int idxInstanceName = c.getColumnIndex(KeyValueStoreColumns.VALUE);
                instanceName = c.getString(idxInstanceName);
            }
        } finally {
            c.close();
        }

        // ARGH! we must ensure that we have records in our UPLOADS_TABLE_NAME
        // for every distinct instance in the data table.
        b.setLength(0);
        //@formatter:off
        b.append("INSERT INTO ").append(DatabaseConstants.UPLOADS_TABLE_NAME).append("(")
                .append(InstanceColumns.DATA_INSTANCE_ID).append(",")
                .append(InstanceColumns.DATA_TABLE_TABLE_ID).append(") ").append("SELECT ")
                .append(InstanceColumns.DATA_INSTANCE_ID).append(",")
                .append(InstanceColumns.DATA_TABLE_TABLE_ID).append(" FROM (").append("SELECT DISTINCT ")
                .append(DATA_TABLE_ID_COLUMN).append(" as ").append(InstanceColumns.DATA_INSTANCE_ID)
                .append(",").append("? as ").append(InstanceColumns.DATA_TABLE_TABLE_ID).append(" FROM ")
                .append(dbTableName).append(" EXCEPT SELECT DISTINCT ").append(InstanceColumns.DATA_INSTANCE_ID)
                .append(",").append(InstanceColumns.DATA_TABLE_TABLE_ID).append(" FROM ")
                .append(DatabaseConstants.UPLOADS_TABLE_NAME).append(")");
        //@formatter:on

        // TODO: should we collapse across FORM_ID or leave it this way?
        String[] args = { tableId };
        db.execSQL(b.toString(), args);

        // Can't get away with dataTable.* because of collision with _ID column
        // get map of (elementKey -> ColumnDefinition)
        try {
            orderedDefns = TableUtil.get().getColumnDefinitions(db, appName, tableId);
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
            throw new SQLException("Unable to retrieve column definitions for tableId " + tableId);
        }

        db.setTransactionSuccessful();
    } finally {
        if (db != null) {
            db.endTransaction();
            db.close();
        }
    }

    ////////////////////////////////////////////////////////////////
    // OK we have the info we need -- now build the query we want...

    // We can now join through and access the data table rows

    b.setLength(0);
    // @formatter:off
    b.append("SELECT ");
    b.append(DatabaseConstants.UPLOADS_TABLE_NAME).append(".").append(InstanceColumns._ID).append(" as ")
            .append(InstanceColumns._ID).append(",").append(DatabaseConstants.UPLOADS_TABLE_NAME).append(".")
            .append(InstanceColumns.DATA_INSTANCE_ID).append(" as ").append(InstanceColumns.DATA_INSTANCE_ID)
            .append(",").append(DatabaseConstants.UPLOADS_TABLE_NAME).append(".")
            .append(InstanceColumns.SUBMISSION_INSTANCE_ID).append(" as ")
            .append(InstanceColumns.SUBMISSION_INSTANCE_ID).append(",");
    // add the dataTable metadata except for _ID (which conflicts with InstanceColumns._ID)
    b.append(dbTableName).append(".").append(DataTableColumns.ROW_ETAG).append(" as ")
            .append(DataTableColumns.ROW_ETAG).append(",").append(dbTableName).append(".")
            .append(DataTableColumns.SYNC_STATE).append(" as ").append(DataTableColumns.SYNC_STATE).append(",")
            .append(dbTableName).append(".").append(DataTableColumns.CONFLICT_TYPE).append(" as ")
            .append(DataTableColumns.CONFLICT_TYPE).append(",").append(dbTableName).append(".")
            .append(DataTableColumns.FILTER_TYPE).append(" as ").append(DataTableColumns.FILTER_TYPE)
            .append(",").append(dbTableName).append(".").append(DataTableColumns.FILTER_VALUE).append(" as ")
            .append(DataTableColumns.FILTER_VALUE).append(",").append(dbTableName).append(".")
            .append(DataTableColumns.FORM_ID).append(" as ").append(DataTableColumns.FORM_ID).append(",")
            .append(dbTableName).append(".").append(DataTableColumns.LOCALE).append(" as ")
            .append(DataTableColumns.LOCALE).append(",").append(dbTableName).append(".")
            .append(DataTableColumns.SAVEPOINT_TYPE).append(" as ").append(DataTableColumns.SAVEPOINT_TYPE)
            .append(",").append(dbTableName).append(".").append(DataTableColumns.SAVEPOINT_TIMESTAMP)
            .append(" as ").append(DataTableColumns.SAVEPOINT_TIMESTAMP).append(",").append(dbTableName)
            .append(".").append(DataTableColumns.SAVEPOINT_CREATOR).append(" as ")
            .append(DataTableColumns.SAVEPOINT_CREATOR).append(",");
    // add the user-specified data fields in this dataTable
    for (ColumnDefinition cd : orderedDefns) {
        if (cd.isUnitOfRetention()) {
            b.append(dbTableName).append(".").append(cd.getElementKey()).append(" as ")
                    .append(cd.getElementKey()).append(",");
        }
    }
    b.append("CASE WHEN ").append(DATA_TABLE_SAVEPOINT_TIMESTAMP_COLUMN).append(" IS NULL THEN null")
            .append(" WHEN ").append(InstanceColumns.XML_PUBLISH_TIMESTAMP).append(" IS NULL THEN null")
            .append(" WHEN ").append(DATA_TABLE_SAVEPOINT_TIMESTAMP_COLUMN).append(" > ")
            .append(InstanceColumns.XML_PUBLISH_TIMESTAMP).append(" THEN null").append(" ELSE ")
            .append(InstanceColumns.XML_PUBLISH_TIMESTAMP).append(" END as ")
            .append(InstanceColumns.XML_PUBLISH_TIMESTAMP).append(",");
    b.append("CASE WHEN ").append(DATA_TABLE_SAVEPOINT_TIMESTAMP_COLUMN).append(" IS NULL THEN null")
            .append(" WHEN ").append(InstanceColumns.XML_PUBLISH_TIMESTAMP).append(" IS NULL THEN null")
            .append(" WHEN ").append(DATA_TABLE_SAVEPOINT_TIMESTAMP_COLUMN).append(" > ")
            .append(InstanceColumns.XML_PUBLISH_TIMESTAMP).append(" THEN null").append(" ELSE ")
            .append(InstanceColumns.XML_PUBLISH_STATUS).append(" END as ")
            .append(InstanceColumns.XML_PUBLISH_STATUS).append(",");
    b.append("CASE WHEN ").append(DATA_TABLE_SAVEPOINT_TIMESTAMP_COLUMN).append(" IS NULL THEN null")
            .append(" WHEN ").append(InstanceColumns.XML_PUBLISH_TIMESTAMP).append(" IS NULL THEN null")
            .append(" WHEN ").append(DATA_TABLE_SAVEPOINT_TIMESTAMP_COLUMN).append(" > ")
            .append(InstanceColumns.XML_PUBLISH_TIMESTAMP).append(" THEN null").append(" ELSE ")
            .append(InstanceColumns.DISPLAY_SUBTEXT).append(" END as ").append(InstanceColumns.DISPLAY_SUBTEXT)
            .append(",");
    if (instanceName == null) {
        b.append(DataTableColumns.SAVEPOINT_TIMESTAMP);
    } else {
        b.append(instanceName);
    }
    b.append(" as ").append(InstanceColumns.DISPLAY_NAME);
    b.append(" FROM ");
    b.append("( SELECT * FROM ").append(dbTableName).append(" AS T WHERE T.")
            .append(DATA_TABLE_SAVEPOINT_TIMESTAMP_COLUMN).append("=(SELECT MAX(V.")
            .append(DATA_TABLE_SAVEPOINT_TIMESTAMP_COLUMN).append(") FROM ").append(dbTableName)
            .append(" AS V WHERE V.").append(DATA_TABLE_ID_COLUMN).append("=T.").append(DATA_TABLE_ID_COLUMN)
            .append(" AND V.").append(DATA_TABLE_SAVEPOINT_TYPE_COLUMN).append(" IS NOT NULL").append(")")
            .append(") as ").append(dbTableName);
    b.append(" JOIN ").append(DatabaseConstants.UPLOADS_TABLE_NAME).append(" ON ").append(dbTableName)
            .append(".").append(DATA_TABLE_ID_COLUMN).append("=").append(DatabaseConstants.UPLOADS_TABLE_NAME)
            .append(".").append(InstanceColumns.DATA_INSTANCE_ID).append(" AND ").append("? =")
            .append(DatabaseConstants.UPLOADS_TABLE_NAME).append(".")
            .append(InstanceColumns.DATA_TABLE_TABLE_ID);
    b.append(" WHERE ").append(DATA_TABLE_SAVEPOINT_TYPE_COLUMN).append("=?");
    // @formatter:on

    if (instanceId != null) {
        b.append(" AND ").append(DatabaseConstants.UPLOADS_TABLE_NAME).append(".").append(InstanceColumns._ID)
                .append("=?");
        String tempArgs[] = { tableId, InstanceColumns.STATUS_COMPLETE, instanceId };
        filterArgs = tempArgs;
    } else {
        String tempArgs[] = { tableId, InstanceColumns.STATUS_COMPLETE };
        filterArgs = tempArgs;
    }

    if (selection != null) {
        b.append(" AND (").append(selection).append(")");
    }

    if (selectionArgs != null) {
        String[] tempArgs = new String[filterArgs.length + selectionArgs.length];
        for (int i = 0; i < filterArgs.length; ++i) {
            tempArgs[i] = filterArgs[i];
        }
        for (int i = 0; i < selectionArgs.length; ++i) {
            tempArgs[filterArgs.length + i] = selectionArgs[i];
        }
        filterArgs = tempArgs;
    }

    if (sortOrder != null) {
        b.append(" ORDER BY ").append(sortOrder);
    }

    fullQuery = b.toString();

    db = null;
    boolean success = false;
    try {
        db = DatabaseFactory.get().getDatabase(getContext(), appName);
        c = db.rawQuery(fullQuery, filterArgs);
        // Tell the cursor what uri to watch, so it knows when its source data
        // changes
        c.setNotificationUri(getContext().getContentResolver(), uri);
        success = true;
        return c;
    } finally {
        if (db != null && !success) {
            // leave database open for cursor...
            db.close();
        }
    }
}

From source file:mobisocial.musubi.service.AddressBookUpdateHandler.java

@Override
public void onChange(boolean selfChange) {
    final DatabaseManager dbManager = new DatabaseManager(mContext);
    if (!dbManager.getIdentitiesManager().hasConnectedAccounts()) {
        Log.w(TAG, "no connected accounts, skipping friend import");
        return;/*from ww  w .  ja  va 2s . c  o  m*/
    }

    //a new meta contact appears (and the previous ones disappear) if the user merges
    //or if a new entry is added, we can detect the ones that have changed by
    //this condition
    long highestContactIdAlreadySeen = dbManager.getContactDataVersionManager().getMaxContactIdSeen();
    //a new data item corresponds with a new contact, but its possible
    //that a users just adds a new contact method to an existing contact
    //and we need to detect that
    long highestDataIdAlreadySeen = dbManager.getContactDataVersionManager().getMaxDataIdSeen();

    // BJD -- this didn't end up being faster once all import features were added.
    /*if (highestContactIdAlreadySeen == -1) {
       importFullAddressBook(mContext);
       return;
    }*/
    long now = System.currentTimeMillis();
    if (mLastRun + ONCE_PER_PERIOD > now) {
        //wake up when the period expires
        if (!mScheduled) {
            new Handler(mThread.getLooper()).postDelayed(new Runnable() {
                @Override
                public void run() {
                    mScheduled = false;
                    dispatchChange(false);
                }
            }, ONCE_PER_PERIOD - (now - mLastRun) + 1);
        }
        mScheduled = true;
        //skip this update
        return;
    }
    Log.i(TAG, "waking up to handle contact changes...");
    boolean identityAdded = false, profileDataChanged = false;
    Date start = new Date();

    assert (SYNC_EMAIL);
    String account_type_selection = getAccountSelectionString();

    Cursor c = mContext.getContentResolver().query(
            ContactsContract.Data.CONTENT_URI, new String[] { ContactsContract.Data._ID,
                    ContactsContract.Data.DATA_VERSION, ContactsContract.Data.CONTACT_ID },
            "(" + ContactsContract.Data.DATA_VERSION + ">0 OR " + //maybe updated
                    ContactsContract.Data.CONTACT_ID + ">? OR " + //definitely new or merged
                    ContactsContract.Data._ID + ">? " + //definitely added a data item
                    ") AND (" + ContactsContract.RawContacts.ACCOUNT_TYPE + "<>'" + mAccountType + "'"
                    + ") AND (" + NAME_OR_OTHER_SELECTION + account_type_selection + ")", // All known contacts.
            new String[] { String.valueOf(highestContactIdAlreadySeen),
                    String.valueOf(highestDataIdAlreadySeen) },
            null);

    if (c == null) {
        Log.e(TAG, "no valid cursor", new Throwable());
        mContext.getContentResolver().notifyChange(MusubiService.ADDRESS_BOOK_SCANNED, this);
        return;
    }

    HashMap<Pair<String, String>, MMyAccount> account_mapping = new HashMap<Pair<String, String>, MMyAccount>();
    int max_changes = c.getCount();
    TLongArrayList raw_data_ids = new TLongArrayList(max_changes);
    TLongArrayList versions = new TLongArrayList(max_changes);
    long new_max_data_id = highestDataIdAlreadySeen;
    long new_max_contact_id = highestContactIdAlreadySeen;
    TLongHashSet potentially_changed = new TLongHashSet();
    try {
        //the cursor points to a list of raw contact data items that may have changed
        //the items will include a type specific field that we are interested in updating
        //it is possible that multiple data item entries mention the same identifier
        //so we build a list of contacts to update and then perform synchronization
        //by refreshing given that we know the top level contact id.
        if (DBG)
            Log.d(TAG, "Scanning " + c.getCount() + " contacts...");
        while (c.moveToNext()) {
            if (DBG)
                Log.v(TAG, "check for updates of contact " + c.getLong(0));

            long raw_data_id = c.getLong(0);
            long version = c.getLong(1);
            long contact_id = c.getLong(2);

            //if the contact was split or merged, then we get a higher contact id
            //so if we have a higher id, data version doesnt really matter
            if (contact_id <= highestContactIdAlreadySeen) {
                //the data associated with this contact may not be dirty
                //we just can't do the join against our table because thise
                //api is implmented over the content provider
                if (dbManager.getContactDataVersionManager().getVersion(raw_data_id) == version)
                    continue;
            } else {
                new_max_contact_id = Math.max(new_max_contact_id, contact_id);
            }
            raw_data_ids.add(raw_data_id);
            versions.add(version);
            potentially_changed.add(contact_id);
            new_max_data_id = Math.max(new_max_data_id, raw_data_id);
        }
        if (DBG)
            Log.d(TAG, "Finished iterating over " + c.getCount() + " contacts for " + potentially_changed.size()
                    + " candidates.");
    } finally {
        c.close();
    }
    if (potentially_changed.size() == 0) {
        Log.w(TAG,
                "possible bug, woke up to update contacts, but no change was detected; there are extra wakes so it could be ok");
    }

    final SQLiteDatabase db = dbManager.getDatabase();

    Pattern emailPattern = getEmailPattern();
    Pattern numberPattern = getNumberPattern();
    //slice it up so we don't use too much system resource on keeping a lot of state in memory
    int total = potentially_changed.size();
    sAddressBookTotal = total;
    sAddressBookPosition = 0;

    final TLongArrayList slice_of_changed = new TLongArrayList(BATCH_SIZE);
    final StringBuilder to_fetch = new StringBuilder();
    final HashMap<Pair<String, String>, TLongHashSet> ids_for_account = new HashMap<Pair<String, String>, TLongHashSet>();
    final TLongObjectHashMap<String> names = new TLongObjectHashMap<String>();

    TLongIterator it = potentially_changed.iterator();
    for (int i = 0; i < total && it.hasNext();) {
        sAddressBookPosition = i;

        if (BootstrapActivity.isBootstrapped()) {
            try {
                Thread.sleep(mSleepTime * SLEEP_SCALE);
            } catch (InterruptedException e) {
            }
        }

        slice_of_changed.clear();
        ids_for_account.clear();
        names.clear();

        int max = i + BATCH_SIZE;
        for (; i < max && it.hasNext(); ++i) {
            slice_of_changed.add(it.next());
        }

        if (DBG)
            Log.v(TAG, "looking up names ");
        to_fetch.setLength(0);
        to_fetch.append(ContactsContract.Contacts._ID + " IN ");
        SQLClauseHelper.appendArray(to_fetch, slice_of_changed.iterator());
        //lookup the fields we care about from a user profile perspective
        c = mContext.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,
                new String[] { ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME, },
                to_fetch.toString(), null, null);
        try {
            while (c.moveToNext()) {
                long id = c.getLong(0);
                String name = c.getString(1);
                if (name == null)
                    continue;
                //reject names that are just the email address or are just a number 
                //the default for android is just to propagate this as the name
                //if there is no name
                if (emailPattern.matcher(name).matches() || numberPattern.matcher(name).matches())
                    continue;
                names.put(id, name);
            }
        } finally {
            c.close();
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            db.beginTransactionNonExclusive();
        } else {
            db.beginTransaction();
        }

        long before = SystemClock.elapsedRealtime();
        SliceUpdater updater = new SliceUpdater(dbManager, slice_of_changed, ids_for_account, names,
                account_type_selection);
        long after = SystemClock.elapsedRealtime();
        mSleepTime = (mSleepTime + after - before) / 2;
        slice_of_changed.forEach(updater);
        profileDataChanged |= updater.profileDataChanged;
        identityAdded |= updater.identityAdded;
        db.setTransactionSuccessful();
        db.endTransaction();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            db.beginTransactionNonExclusive();
        } else {
            db.beginTransaction();
        }
        //add all detected members to account feed
        for (Entry<Pair<String, String>, TLongHashSet> e : ids_for_account.entrySet()) {
            Pair<String, String> k = e.getKey();
            TLongHashSet v = e.getValue();
            MMyAccount cached_account = account_mapping.get(k);
            if (cached_account == null) {
                cached_account = lookupOrCreateAccount(dbManager, k.getValue0(), k.getValue1());
                prepareAccountWhitelistFeed(dbManager.getMyAccountManager(), dbManager.getFeedManager(),
                        cached_account);
                account_mapping.put(k, cached_account);
            }

            final MMyAccount account = cached_account;
            v.forEach(new TLongProcedure() {
                @Override
                public boolean execute(long id) {
                    dbManager.getFeedManager().ensureFeedMember(account.feedId_, id);
                    db.yieldIfContendedSafely(75);
                    return true;
                }
            });
        }
        db.setTransactionSuccessful();
        db.endTransaction();
    }

    sAddressBookTotal = sAddressBookPosition = 0;

    //TODO: handle deleted
    //for all android data ids in our table, check if they still exist in the
    //contacts table, probably in batches of 100 or something.  if they don't
    //null them out.  this is annoyingly non-differential.

    //TODO: adding friend should update accepted feed status, however,
    //if a crashe happens for whatever reason, then its possible that this may need to
    //be run for identities which actually exist in the db.  so this update code
    //needs to do the feed accepted status change for all users that were touched
    //by the profile update process

    //update the version ids so we can be faster on subsequent runs
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        db.beginTransactionNonExclusive();
    } else {
        db.beginTransaction();
    }
    int changed_data_rows = raw_data_ids.size();
    for (int i = 0; i < changed_data_rows; ++i) {
        dbManager.getContactDataVersionManager().setVersion(raw_data_ids.get(i), versions.get(i));
    }
    db.setTransactionSuccessful();
    db.endTransaction();

    dbManager.getContactDataVersionManager().setMaxDataIdSeen(new_max_data_id);
    dbManager.getContactDataVersionManager().setMaxContactIdSeen(new_max_contact_id);
    ContentResolver resolver = mContext.getContentResolver();

    Date end = new Date();
    double time = end.getTime() - start.getTime();
    time /= 1000;
    Log.w(TAG, "update address book " + mChangeCount++ + " took " + time + " seconds");
    if (identityAdded) {
        //wake up the profile push
        resolver.notifyChange(MusubiService.WHITELIST_APPENDED, this);
    }
    if (profileDataChanged) {
        //refresh the ui...
        resolver.notifyChange(MusubiService.PRIMARY_CONTENT_CHANGED, this);
    }
    if (identityAdded || profileDataChanged) {
        //update the our musubi address book as needed.
        String accountName = mContext.getString(R.string.account_name);
        String accountType = mContext.getString(R.string.account_type);
        Account account = new Account(accountName, accountType);
        ContentResolver.requestSync(account, ContactsContract.AUTHORITY, new Bundle());
    }

    dbManager.close();
    mLastRun = new Date().getTime();
    resolver.notifyChange(MusubiService.ADDRESS_BOOK_SCANNED, this);
}

From source file:org.ttrssreader.controllers.DBHelper.java

/**
 * Set unread counters for feeds and categories according to real amount of unread articles.
 *///from  www  .ja  va  2s  . c om
void calculateCounters() {
    if (!isDBAvailable())
        return;

    long time = System.currentTimeMillis();
    int total = 0;
    Cursor c = null;

    SQLiteDatabase db = getOpenHelper().getWritableDatabase();
    writeLock(true);
    db.beginTransaction();
    try {
        ContentValues cv = new ContentValues(1);

        // First of all, reset all feeds and all categories to unread=0
        cv.put("unread", 0);
        db.update(TABLE_FEEDS, cv, null, null);
        db.update(TABLE_CATEGORIES, cv, null, null);

        // Count all feeds where unread articles exist
        try {
            // select feedId, count(*) from articles where isUnread>0 group by feedId
            c = db.query(TABLE_ARTICLES, new String[] { "feedId", "count(*)" }, "isUnread>0", null, "feedId",
                    null, null, null);

            // update feeds
            while (c.moveToNext()) {
                int feedId = c.getInt(0);
                int unreadCount = c.getInt(1);

                total += unreadCount;

                cv.put("unread", unreadCount);
                db.update(TABLE_FEEDS, cv, "_id=" + feedId, null);
            }
        } finally {
            if (c != null && !c.isClosed())
                c.close();
        }

        // Count all categories where feeds with unread articles exist
        try {
            // select categoryId, sum(unread) from feeds where categoryId >= 0 group by categoryId
            c = db.query(TABLE_FEEDS, new String[] { "categoryId", "sum(unread)" }, "categoryId>=0", null,
                    "categoryId", null, null, null);

            // update real categories
            while (c.moveToNext()) {
                int categoryId = c.getInt(0);
                int unreadCount = c.getInt(1);

                cv.put("unread", unreadCount);
                db.update(TABLE_CATEGORIES, cv, "_id=" + categoryId, null);
            }
        } finally {
            if (c != null && !c.isClosed())
                c.close();
        }

        // Count special categories
        cv.put("unread", total);
        db.update(TABLE_CATEGORIES, cv, "_id=" + Data.VCAT_ALL, null);

        cv.put("unread", getUnreadCount(Data.VCAT_FRESH, true));
        db.update(TABLE_CATEGORIES, cv, "_id=" + Data.VCAT_FRESH, null);

        cv.put("unread", getUnreadCount(Data.VCAT_PUB, true));
        db.update(TABLE_CATEGORIES, cv, "_id=" + Data.VCAT_PUB, null);

        cv.put("unread", getUnreadCount(Data.VCAT_STAR, true));
        db.update(TABLE_CATEGORIES, cv, "_id=" + Data.VCAT_STAR, null);

        db.setTransactionSuccessful();
    } finally {
        db.endTransaction();
        writeLock(false);
    }

    Log.i(TAG, String.format("Fixed counters, total unread: %s (took %sms)", total,
            (System.currentTimeMillis() - time)));
}

From source file:com.wheelermarine.publicAccessSites.Updater.java

@Override
protected Integer doInBackground(URL... urls) {

    try {// ww w  .  ja v a  2s  .  c om
        final DatabaseHelper db = new DatabaseHelper(context);

        SQLiteDatabase database = db.getWritableDatabase();
        if (database == null)
            throw new IllegalStateException("Unable to open database!");

        database.beginTransaction();
        try {
            // Clear out the old data.
            database.delete(DatabaseHelper.PublicAccessEntry.TABLE_NAME, null, null);

            // Connect to the web server and locate the FTP download link.
            Log.v(TAG, "Finding update: " + urls[0]);
            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    progress.setMessage("Locating update...");
                    progress.setIndeterminate(true);
                }
            });
            Document doc = Jsoup.connect(urls[0].toString()).timeout(timeout * 1000).userAgent(userAgent).get();
            URL dataURL = null;
            for (Element element : doc.select("a")) {
                if (element.hasAttr("href") && element.attr("href").endsWith(".zip")) {
                    dataURL = new URL(element.attr("href"));
                }
            }

            // Make sure the download URL was fund.
            if (dataURL == null)
                throw new FileNotFoundException("Unable to locate data URL.");

            // Connect to the FTP server and download the update.
            Log.v(TAG, "Downloading update: " + dataURL);
            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    progress.setMessage("Downloading update...");
                    progress.setIndeterminate(true);
                }
            });
            HttpClient client = new DefaultHttpClient();
            HttpGet get = new HttpGet(dataURL.toString());
            HttpResponse response = client.execute(get);
            HttpEntity entity = response.getEntity();
            if (entity == null)
                throw new IOException("Error downloading update.");

            Map<Integer, Location> locations = null;

            // Download the ZIP archive.
            Log.v(TAG, "Downloading: " + dataURL.getFile());
            InputStream in = entity.getContent();
            if (in == null)
                throw new FileNotFoundException(dataURL.getFile() + " was not found!");
            try {
                ZipInputStream zin = new ZipInputStream(in);
                try {
                    // Locate the .dbf entry in the ZIP archive.
                    ZipEntry entry;
                    while ((entry = zin.getNextEntry()) != null) {
                        if (entry.getName().endsWith(entryName)) {
                            readDBaseFile(zin, database);
                        } else if (entry.getName().endsWith(shapeEntryName)) {
                            locations = readShapeFile(zin);
                        }
                    }
                } finally {
                    try {
                        zin.close();
                    } catch (Exception e) {
                        // Ignore this error.
                    }
                }
            } finally {
                in.close();
            }

            if (locations != null) {
                final int recordCount = locations.size();
                activity.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        progress.setIndeterminate(false);
                        progress.setMessage("Updating locations...");
                        progress.setMax(recordCount);
                    }
                });

                int progress = 0;
                for (int recordNumber : locations.keySet()) {
                    PublicAccess access = db.getPublicAccessByRecordNumber(recordNumber);
                    Location loc = locations.get(recordNumber);
                    access.setLatitude(loc.getLatitude());
                    access.setLongitude(loc.getLongitude());
                    db.updatePublicAccess(access);
                    publishProgress(++progress);
                }
            }
            database.setTransactionSuccessful();
            return db.getPublicAccessesCount();
        } finally {
            database.endTransaction();
        }
    } catch (Exception e) {
        error = e;
        Log.e(TAG, "Error loading data: " + e.getLocalizedMessage(), e);
        return -1;
    }
}

From source file:ru.gkpromtech.exhibition.db.DbHelper.java

public void applyUpdates(SQLiteDatabase db, JsonNode updates, boolean isStatic) throws Exception {

    JsonNode nodeRev = updates.get("revision");
    if (nodeRev == null)
        return;/* ww w.  j  a v a2  s  .  c o  m*/

    final String synchronous = getPragma(db, "synchronous");
    final String journalMode = getPragma(db, "journal_mode");

    db.rawQuery("PRAGMA synchronous = OFF", null);
    db.rawQuery("PRAGMA journal_mode = MEMORY", null);
    //  FK,  ?   ???    add-update
    db.execSQL("PRAGMA foreign_keys = OFF");

    SharedPreferences prefs = getPrefs();

    int langId = Profile.getInstance(mContext).getLangId();
    int currentRevision = prefs.getInt("revision", 0);
    ObjectMapper mapper = new ObjectMapper();
    int revision = nodeRev.asInt();
    ArrayNode nodeChanges = (ArrayNode) updates.get("changes");

    TypeReference<List<Change>> typeRef = new TypeReference<List<Change>>() {
    };
    List<Change> changes = mapper.readValue(nodeChanges.traverse(), typeRef);

    Map<Table, List<Integer>> deletedTableRowIds = new HashMap<>();

    try {
        db.beginTransaction();

        for (Change change : changes) {
            if (currentRevision > change.id) {
                Log.w("PPDB", "Skipping old change #" + change.id);
                continue;
            }

            boolean tr = change.entity.endsWith("_tr");
            String entityName = !tr ? change.entity : change.entity.substring(0, change.entity.length() - 3);

            Class<? extends Entity> entity = getEntityForTableName(entityName);
            if (entity == null) {
                Log.e("PPDB", "Cannot find entity for " + entityName);
                continue;
            }

            Table<? extends Entity> table = getTableFor(entity);
            if (table == null) {
                Log.e("PPDB", "Cannot find table for entity " + entityName);
                continue;
            }

            if (!tr) {
                if (change.data != null) {
                    switch (change.changetype) {
                    case Change.ADDED:
                        table.insert(db, change.data, SQLiteDatabase.CONFLICT_FAIL);
                        break;
                    case Change.UPDATED:
                        change.data.remove("id");
                        table.partialUpdate(db, change.rowid, change.data, SQLiteDatabase.CONFLICT_FAIL);
                        break;
                    }
                } else {
                    if (change.changetype == Change.DELETED) {
                        List<Integer> ids = deletedTableRowIds.get(table);
                        if (ids == null) {
                            ids = new ArrayList<>();
                            deletedTableRowIds.put(table, ids);
                        }
                        ids.add(change.rowid);
                    }
                }
            } else if (change.data != null) {
                int changeLangId = change.data.get("languageid").asInt();
                if (changeLangId != langId)
                    continue;
                change.data.remove("languageid");
                switch (change.changetype) {
                case Change.ADDED:
                case Change.UPDATED:
                    TableRef annotation = entity.getAnnotation(TableRef.class);
                    if (annotation == null) {
                        Log.e("PPDB", "Cannot get trid field for entity " + entityName);
                        continue;
                    }
                    String trIdName = annotation.trid();
                    JsonNode nodeTrId = change.data.get(trIdName);
                    if (nodeTrId == null) {
                        Log.e("PPDB", "Change data don't have a field [" + trIdName + "]: " + entityName);
                        continue;
                    }
                    int id = nodeTrId.asInt();
                    change.data.remove("id");
                    change.data.remove(trIdName);
                    table.partialUpdate(db, id, change.data, SQLiteDatabase.CONFLICT_FAIL);
                    break;
                }
            }
        }

        db.setTransactionSuccessful();

    } finally {
        db.endTransaction();
    }

    //   ??? ?, ? FK
    db.execSQL("PRAGMA foreign_keys = ON");

    try {
        db.beginTransaction();

        for (Map.Entry<Table, List<Integer>> entry : deletedTableRowIds.entrySet()) {
            Table table = entry.getKey();
            List<Integer> ids = entry.getValue();
            for (Integer id : ids)
                table.delete(db, id);
        }

        db.setTransactionSuccessful();
    } finally {
        db.endTransaction();
    }

    if (synchronous != null)
        db.rawQuery("PRAGMA synchronous = " + synchronous, null);
    if (journalMode != null)
        db.rawQuery("PRAGMA journal_mode = " + journalMode, null);

    if (revision > currentRevision)
        prefs.edit().putInt("revision", revision).apply();

    if (isStatic)
        prefs.edit().putInt("jsonRevision", revision).apply();
}

From source file:edu.stanford.mobisocial.dungbeetle.DBHelper.java

@Override
public void onCreate(SQLiteDatabase db) {
    db.beginTransaction();//from w  w w  . j  a  v  a  2s . c  om

    createTable(db, MyInfo.TABLE, null, MyInfo._ID, "INTEGER PRIMARY KEY", MyInfo.PUBLIC_KEY, "TEXT",
            MyInfo.PRIVATE_KEY, "TEXT", MyInfo.NAME, "TEXT", MyInfo.EMAIL, "TEXT", MyInfo.PICTURE, "BLOB",
            MyInfo.ABOUT, "TEXT DEFAULT ''");

    createTable(db, DbObject.TABLE, null, DbObject._ID, "INTEGER PRIMARY KEY", DbObject.TYPE, "TEXT",
            DbObject.SEQUENCE_ID, "INTEGER", DbObject.FEED_NAME, "TEXT", DbObject.APP_ID, "TEXT",
            DbObject.CONTACT_ID, "INTEGER", DbObject.DESTINATION, "TEXT", DbObject.JSON, "TEXT",
            DbObject.TIMESTAMP, "INTEGER", DbObject.LAST_MODIFIED_TIMESTAMP, "INTEGER", DbObject.SENT,
            "INTEGER DEFAULT 0", DbObject.DELETED, "INTEGER DEFAULT 0", DbObject.HASH, "INTEGER",
            DbObject.ENCODED, "BLOB", DbObject.CHILD_FEED_NAME, "TEXT", DbObject.RAW, "BLOB", DbObject.KEY_INT,
            "INTEGER");
    db.execSQL("CREATE INDEX objects_by_sequence_id ON " + DbObject.TABLE + "(" + DbObject.CONTACT_ID + ", "
            + DbObject.FEED_NAME + ", " + DbObject.SEQUENCE_ID + ")");
    createIndex(db, "INDEX", "objects_by_feed_name", DbObject.TABLE, DbObject.FEED_NAME);
    db.execSQL("CREATE INDEX objects_by_creator_id ON " + DbObject.TABLE + "(" + DbObject.CONTACT_ID + ", "
            + DbObject.SENT + ")");
    createIndex(db, "INDEX", "child_feeds", DbObject.TABLE, DbObject.CHILD_FEED_NAME);
    createIndex(db, "INDEX", "objects_by_hash", DbObject.TABLE, DbObject.HASH);
    createIndex(db, "INDEX", "objects_by_int_key", DbObject.TABLE, DbObject.KEY_INT);
    createIndex(db, "INDEX", "objects_last_modified", DbObject.TABLE, DbObject.LAST_MODIFIED_TIMESTAMP);

    createTable(db, Contact.TABLE, null, Contact._ID, "INTEGER PRIMARY KEY", Contact.NAME, "TEXT",
            Contact.PUBLIC_KEY, "TEXT", Contact.PUBLIC_KEY_HASH_64, "INTEGER", Contact.SHARED_SECRET, "BLOB",
            Contact.PERSON_ID, "TEXT", Contact.EMAIL, "TEXT", Contact.PRESENCE,
            "INTEGER DEFAULT " + Presence.AVAILABLE, Contact.LAST_PRESENCE_TIME, "INTEGER DEFAULT 0",
            Contact.LAST_OBJECT_ID, "INTEGER", Contact.LAST_UPDATED, "INTEGER", Contact.NUM_UNREAD,
            "INTEGER DEFAULT 0", Contact.NEARBY, "INTEGER DEFAULT 0", Contact.STATUS, "TEXT", Contact.PICTURE,
            "BLOB", Contact.HIDDEN, "INTEGER DEFAULT 0");
    createIndex(db, "UNIQUE INDEX", "contacts_by_person_id", Contact.TABLE, Contact.PERSON_ID);
    createIndex(db, "INDEX", "contacts_by_pkp", Contact.TABLE, Contact.PUBLIC_KEY_HASH_64);

    createTable(db, Subscriber.TABLE, new String[] { Subscriber.CONTACT_ID, Subscriber.FEED_NAME },
            Subscriber._ID, "INTEGER PRIMARY KEY", Subscriber.CONTACT_ID,
            "INTEGER REFERENCES " + Contact.TABLE + "(" + Contact._ID + ") ON DELETE CASCADE",
            Subscriber.FEED_NAME, "TEXT");
    createIndex(db, "INDEX", "subscribers_by_contact_id", Subscriber.TABLE, Subscriber.CONTACT_ID);

    createGroupBaseTable(db);
    createGroupMemberBaseTable(db);
    createRelationBaseTable(db);
    addRelationIndexes(db);
    createUserAttributesTable(db);
    generateAndStorePersonalInfo(db);

    db.setVersion(VERSION);
    db.setTransactionSuccessful();
    db.endTransaction();
    this.onOpen(db);
    //}
}

From source file:mobisocial.musubi.ui.fragments.AccountLinkDialog.java

/**
 * Adds an account to the local database. Must not be called on the main thread.
 *//*from  w w  w. jav a  2s  .  c  om*/
public static MMyAccount addAccountToDatabase(Activity activity, AccountDetails accountDetails) {
    SQLiteOpenHelper databaseSource = App.getDatabaseSource(activity);
    IdentitiesManager im = new IdentitiesManager(databaseSource);
    MyAccountManager am = new MyAccountManager(databaseSource);
    DeviceManager dm = new DeviceManager(databaseSource);
    FeedManager fm = new FeedManager(databaseSource);

    String accountType = accountDetails.accountType;
    String accountName = accountDetails.accountName;
    String principal = accountDetails.principal;
    boolean owned = accountDetails.owned;
    IBIdentity ibid;
    if (accountType.equals(ACCOUNT_TYPE_GOOGLE)) {
        ibid = new IBIdentity(Authority.Email, principal, 0);
    } else if (accountType.equals(ACCOUNT_TYPE_FACEBOOK)) {
        ibid = new IBIdentity(Authority.Facebook, principal, 0);
    } else if (accountType.equals(ACCOUNT_TYPE_PHONE)) {
        ibid = new IBIdentity(Authority.PhoneNumber, principal, 0);
    } else {
        throw new RuntimeException("Unsupported account type " + accountType);
    }

    SQLiteDatabase db = databaseSource.getWritableDatabase();
    db.beginTransaction();
    try {
        // Ensure identity in the database
        MIdentity id = im.getIdentityForIBHashedIdentity(ibid);
        //don't repeatedly add profile broadcast groups or do any
        //of this processing if the account is already owned.
        if (id != null && id.owned_) {
            return null;
        }

        MIdentity original = im.getOwnedIdentities().get(0);
        //if this identity wasnt already in the contact book, we need to update it
        if (id == null) {
            id = new MIdentity();
            populateMyNewIdentity(activity, principal, im, ibid, id, original, owned);
            im.insertIdentity(id);
        } else {
            populateMyNewIdentity(activity, principal, im, ibid, id, original, owned);
            im.updateIdentity(id);
        }

        im.updateMyProfileName(activity, id.musubiName_, false);
        im.updateMyProfileThumbnail(activity, id.musubiThumbnail_, false);

        // Ensure account entry exists
        MMyAccount account = am.lookupAccount(accountName, accountType);
        if (account == null) {
            //create the account
            account = new MMyAccount();
            account.accountName_ = accountName;
            account.accountType_ = accountType;
            account.identityId_ = id.id_;
            am.insertAccount(account);
        } else {
            account.identityId_ = id.id_;
            am.updateAccount(account);
        }

        // For accounts linked to identities that are not yet owned,
        // skip further initialization
        if (owned) {
            MDevice dev = dm.getDeviceForName(id.id_, dm.getLocalDeviceName());
            // Ensure device exists
            if (dev == null) {
                dev = new MDevice();
                dev.deviceName_ = dm.getLocalDeviceName();
                dev.identityId_ = id.id_;
                dm.insertDevice(dev);
            }
            //this feed will contain all members who should receive
            //a profile for the account because of a friend introduction
            MFeed provisional = new MFeed();
            provisional.name_ = MFeed.PROVISONAL_WHITELIST_FEED_NAME;
            provisional.type_ = MFeed.FeedType.ASYMMETRIC;
            fm.insertFeed(provisional);
            //XXX
            //TODO: in other places in the code, we should be pruning the
            //provisional whitelist feed as people become whitelisted..

            //these get inserted for owned identities to allow profile
            //broadcasts to go out
            MMyAccount provAccount = new MMyAccount();
            provAccount.accountName_ = MMyAccount.PROVISIONAL_WHITELIST_ACCOUNT;
            provAccount.accountType_ = MMyAccount.INTERNAL_ACCOUNT_TYPE;
            provAccount.identityId_ = id.id_;
            provAccount.feedId_ = provisional.id_;
            am.insertAccount(provAccount);

            //this feed will contain all members who should receive
            //a profile for the account because they are whitelisted
            //and contacted you on one of your accounts.
            MFeed accountBroadcastFeed = new MFeed();
            accountBroadcastFeed.name_ = MFeed.LOCAL_WHITELIST_FEED_NAME;
            accountBroadcastFeed.type_ = MFeed.FeedType.ASYMMETRIC;
            fm.insertFeed(accountBroadcastFeed);

            MMyAccount localAccount = new MMyAccount();
            localAccount.accountName_ = MMyAccount.LOCAL_WHITELIST_ACCOUNT;
            localAccount.accountType_ = MMyAccount.INTERNAL_ACCOUNT_TYPE;
            localAccount.identityId_ = id.id_;
            localAccount.feedId_ = accountBroadcastFeed.id_;
            am.insertAccount(localAccount);

            db.setTransactionSuccessful();

            ContentResolver resolver = activity.getContentResolver();
            // Notify interested services (identity available makes AMQP wake up for example)
            resolver.notifyChange(MusubiService.OWNED_IDENTITY_AVAILABLE, null);
            resolver.notifyChange(MusubiService.MY_PROFILE_UPDATED, null);

            // Makes key update wake up
            resolver.notifyChange(MusubiService.AUTH_TOKEN_REFRESH, null);
            WizardStepHandler.accomplishTask(activity, WizardStepHandler.TASK_LINK_ACCOUNT);

            App.getUsageMetrics(activity).report(MusubiMetrics.ACCOUNT_CONNECTED, account.accountType_);
        } else {
            db.setTransactionSuccessful();
        }
        return account;
    } finally {
        db.endTransaction();
    }
}