Search in sources :

Example 1 with SharedRealm

use of io.realm.internal.SharedRealm in project realm-java by realm.

the class BaseRealm method compactRealm.

/**
     * Compacts the Realm file defined by the given configuration.
     *
     * @param configuration configuration for the Realm to compact.
     * @return {@code true} if compaction succeeded, {@code false} otherwise.
     */
static boolean compactRealm(final RealmConfiguration configuration) {
    SharedRealm sharedRealm = SharedRealm.getInstance(configuration);
    Boolean result = sharedRealm.compact();
    sharedRealm.close();
    return result;
}
Also used : SharedRealm(io.realm.internal.SharedRealm) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean)

Example 2 with SharedRealm

use of io.realm.internal.SharedRealm in project realm-java by realm.

the class Realm method executeTransactionAsync.

/**
     * Similar to {@link #executeTransactionAsync(Transaction)}, but also accepts an OnSuccess and OnError callbacks.
     *
     * @param transaction {@link io.realm.Realm.Transaction} to execute.
     * @param onSuccess callback invoked when the transaction succeeds.
     * @param onError callback invoked when the transaction fails.
     * @return a {@link RealmAsyncTask} representing a cancellable task.
     * @throws IllegalArgumentException if the {@code transaction} is {@code null}, or if the realm is opened from
     *                                  another thread.
     */
public RealmAsyncTask executeTransactionAsync(final Transaction transaction, final Realm.Transaction.OnSuccess onSuccess, final Realm.Transaction.OnError onError) {
    checkIfValid();
    if (transaction == null) {
        throw new IllegalArgumentException("Transaction should not be null");
    }
    // Avoid to call canDeliverNotification() in bg thread.
    final boolean canDeliverNotification = sharedRealm.capabilities.canDeliverNotification();
    // the results.
    if ((onSuccess != null || onError != null)) {
        sharedRealm.capabilities.checkCanDeliverNotification("Callback cannot be delivered on current thread.");
    }
    // We need to use the same configuration to open a background SharedRealm (i.e Realm)
    // to perform the transaction
    final RealmConfiguration realmConfiguration = getConfiguration();
    // We need to deliver the callback even if the Realm is closed. So acquire a reference to the notifier here.
    final RealmNotifier realmNotifier = sharedRealm.realmNotifier;
    final Future<?> pendingTransaction = asyncTaskExecutor.submitTransaction(new Runnable() {

        @Override
        public void run() {
            if (Thread.currentThread().isInterrupted()) {
                return;
            }
            SharedRealm.VersionID versionID = null;
            Throwable exception = null;
            final Realm bgRealm = Realm.getInstance(realmConfiguration);
            bgRealm.beginTransaction();
            try {
                transaction.execute(bgRealm);
                if (Thread.currentThread().isInterrupted()) {
                    return;
                }
                bgRealm.commitTransaction();
                // The bgRealm needs to be closed before post event to caller's handler to avoid concurrency
                // problem. This is currently guaranteed by posting callbacks later below.
                versionID = bgRealm.sharedRealm.getVersionID();
            } catch (final Throwable e) {
                exception = e;
            } finally {
                try {
                    if (bgRealm.isInTransaction()) {
                        bgRealm.cancelTransaction();
                    }
                } finally {
                    bgRealm.close();
                }
            }
            final Throwable backgroundException = exception;
            final SharedRealm.VersionID backgroundVersionID = versionID;
            // Cannot be interrupted anymore.
            if (canDeliverNotification) {
                if (backgroundVersionID != null && onSuccess != null) {
                    realmNotifier.post(new Runnable() {

                        @Override
                        public void run() {
                            if (isClosed()) {
                                // The caller Realm is closed. Just call the onSuccess. Since the new created Realm
                                // cannot be behind the background one.
                                onSuccess.onSuccess();
                                return;
                            }
                            if (sharedRealm.getVersionID().compareTo(backgroundVersionID) < 0) {
                                sharedRealm.realmNotifier.addTransactionCallback(new Runnable() {

                                    @Override
                                    public void run() {
                                        onSuccess.onSuccess();
                                    }
                                });
                            } else {
                                onSuccess.onSuccess();
                            }
                        }
                    });
                } else if (backgroundException != null) {
                    realmNotifier.post(new Runnable() {

                        @Override
                        public void run() {
                            if (onError != null) {
                                onError.onError(backgroundException);
                            } else {
                                throw new RealmException("Async transaction failed", backgroundException);
                            }
                        }
                    });
                }
            } else {
                if (backgroundException != null) {
                    // Throw in the worker thread since the caller thread cannot get notifications.
                    throw new RealmException("Async transaction failed", backgroundException);
                }
            }
        }
    });
    return new RealmAsyncTaskImpl(pendingTransaction, asyncTaskExecutor);
}
Also used : RealmAsyncTaskImpl(io.realm.internal.async.RealmAsyncTaskImpl) RealmNotifier(io.realm.internal.RealmNotifier) SharedRealm(io.realm.internal.SharedRealm) RealmException(io.realm.exceptions.RealmException)

Example 3 with SharedRealm

use of io.realm.internal.SharedRealm in project realm-java by realm.

the class RealmCache method createRealmOrGetFromCache.

/**
     * Creates a new Realm instance or get an existing instance for current thread.
     *
     * @param configuration {@link RealmConfiguration} will be used to create or get the instance.
     * @param realmClass class of {@link Realm} or {@link DynamicRealm} to be created in or gotten from the cache.
     * @return the {@link Realm} or {@link DynamicRealm} instance.
     */
static synchronized <E extends BaseRealm> E createRealmOrGetFromCache(RealmConfiguration configuration, Class<E> realmClass) {
    boolean isCacheInMap = true;
    RealmCache cache = cachesMap.get(configuration.getPath());
    if (cache == null) {
        // Creates a new cache.
        cache = new RealmCache(configuration);
        // The new cache should be added to the map later.
        isCacheInMap = false;
        copyAssetFileIfNeeded(configuration);
    } else {
        // Throws the exception if validation failed.
        cache.validateConfiguration(configuration);
    }
    RefAndCount refAndCount = cache.refAndCountMap.get(RealmCacheType.valueOf(realmClass));
    if (refAndCount.globalCount == 0) {
        SharedRealm sharedRealm = SharedRealm.getInstance(configuration);
        if (Table.primaryKeyTableNeedsMigration(sharedRealm)) {
            sharedRealm.beginTransaction();
            if (Table.migratePrimaryKeyTableIfNeeded(sharedRealm)) {
                sharedRealm.commitTransaction();
            } else {
                sharedRealm.cancelTransaction();
            }
        }
        sharedRealm.close();
    }
    if (refAndCount.localRealm.get() == null) {
        // Creates a new local Realm instance
        BaseRealm realm;
        if (realmClass == Realm.class) {
            // RealmMigrationNeededException might be thrown here.
            realm = Realm.createInstance(configuration, cache.typedColumnIndicesArray);
        } else if (realmClass == DynamicRealm.class) {
            realm = DynamicRealm.createInstance(configuration);
        } else {
            throw new IllegalArgumentException(WRONG_REALM_CLASS_MESSAGE);
        }
        // The cache is not in the map yet. Add it to the map after the Realm instance created successfully.
        if (!isCacheInMap) {
            cachesMap.put(configuration.getPath(), cache);
        }
        refAndCount.localRealm.set(realm);
        refAndCount.localCount.set(0);
    }
    Integer refCount = refAndCount.localCount.get();
    if (refCount == 0) {
        if (realmClass == Realm.class && refAndCount.globalCount == 0) {
            final BaseRealm realm = refAndCount.localRealm.get();
            // Stores a copy of local ColumnIndices as a global cache.
            RealmCache.storeColumnIndices(cache.typedColumnIndicesArray, realm.schema.columnIndices.clone());
        }
        // This is the first instance in current thread, increase the global count.
        refAndCount.globalCount++;
    }
    refAndCount.localCount.set(refCount + 1);
    @SuppressWarnings("unchecked") E realm = (E) refAndCount.localRealm.get();
    return realm;
}
Also used : SharedRealm(io.realm.internal.SharedRealm) SharedRealm(io.realm.internal.SharedRealm)

Aggregations

SharedRealm (io.realm.internal.SharedRealm)3 RealmException (io.realm.exceptions.RealmException)1 RealmNotifier (io.realm.internal.RealmNotifier)1 RealmAsyncTaskImpl (io.realm.internal.async.RealmAsyncTaskImpl)1 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)1