1

I don't get any sense why they are writing two opposite variables in Logical OR. True || False = True, or False || True = True. Why this check is necessary?

if (mDatabase != null) {
            if (!mDatabase.isOpen()) {
                // Darn!  The user closed the database by calling mDatabase.close().
                mDatabase = null;
            } else if (!writable || !mDatabase.isReadOnly()) {
                // The database is already open for business.
                return mDatabase;
            }
        }

Note: The same logic is applied in Samba file share also. There is a Samba explanation http://www.linuxtopia.org/online_books/network_administration_guides/using_samba_book/ch04_05_06.html

Can anyone clarify me here?

The code stub I presented above is in SQLiteOpenHelper class from line 222 to 231

https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/database/sqlite/SQLiteOpenHelper.java

Uddhav P. Gautam
  • 7,362
  • 3
  • 47
  • 64

2 Answers2

1

You've misunderstood the writable parameter. It doesn't indicate the state of the current database or connection. It indicates whether the user wants a database connection that they can write to, or whether a read only connection is adequate.

This particular line says - if the user doesn't want a writable connection, or if the database will allow the user to write, then the current database will do just fine. In other words, we go past this line (and do more connection stuff) if the user has specifically requested a writable database, but the current connection is read only.

Dawood ibn Kareem
  • 77,785
  • 15
  • 98
  • 110
1

Writable is defined by:

  1. If the disk is R-W
  2. If the process that writes to database has write permission.

Note: Writable has nothing to do with your understanding here.

For the ReadOnly, there is a logic because ReadOnly is not opposite of Writable. This is where you are confused.

There are three things in ReadOnly: OPEN_READONLY, OPEN_READ_MASK, and OpenFlags.

Note: OPEN_READONLY is exactly opposite of Writable. This is where you were unclear.

Explanation OPEN_READ_MASK -- We set it to 1 (i.e. 0X00000001 in Hex) OPEN_READONLY -- We set it to 1 (i.e. 0X00000001 in Hex)

OpenFlags - Sometimes it is 1, sometimes it is 0. It is 1 if the disk not not full. It is 0 if the disk is full.

And, we calculate ReadOnly = (OpenFlags & OPEN_READ_MASK == OPEN_READONLY). Now, from this & operation, the ReadOnly always ensures even though the database is OPEN_READONLY, still it needs to satisfy it is not full. If it is full then ReadOnly becomes false.

That's why for every file and database, the above implemented & operation is reliable.

Proof:

If you ctrl+Alt click the method of isReadOnly(), you will see below lines of code.

public boolean isReadOnly() {
        synchronized (mLock) {
            return isReadOnlyLocked();
        }
    }

You further Ctrl+Alt+click on method isReadOnlyLocked(), you will see below lines of code.

private boolean isReadOnlyLocked() {
        return (mConfigurationLocked.openFlags & OPEN_READ_MASK) == OPEN_READONLY;
    }

You can see how OPEN_READ_MASK and OPEN_READONLY defined by further Ctrl+Alt+click, you see below lines of code.

/**
     * Open flag: Flag for {@link #openDatabase} to open the database for reading only.
     * This is the only reliable way to open a database if the disk may be full.
     */
    public static final int OPEN_READONLY = 0x00000001;           // update native code if changing

    private static final int OPEN_READ_MASK = 0x00000001;         // update native code if changing

If the disk is full, they system changes openFlags to 0 to ensure even though the disk is Openly readOnly still because of there is no disk space, you can't write. Now, I believe, you are clear.

Omprakash
  • 94
  • 1
  • 9