Android native CursorWindow数据保存原理
阅读原文时间:2023年07月13日阅读:1

我们通过Uri查询数据库所得到的数据集,保存在native层的CursorWindow中。CursorWindow的实质是共享内存的抽象,以实现跨进程数据共享。共享内存所採用的实现方式是文件映射。

在ContentProvider端透过SQLiteDatabase的封装查询到的数据集保存在CursorWindow所指向的共享内存中。然后通过Binder把这片共享内存传递到ContentResolver端,即查询端。

这样客户就能够通过Cursor来訪问这块共享内存中的数据集了。

那么CursorWindow是怎样实现的呢?

1.通过Create静态函数来创建

status_t CursorWindow::create(const String8& name, size_t size, CursorWindow** outCursorWindow) {
String8 ashmemName("CursorWindow: ");
ashmemName.append(name);//文件名称

status\_t result;  
int ashmemFd = ashmem\_create\_region(ashmemName.string(), size);  
if (ashmemFd < 0) {  
    result = -errno;  
} else {  
    result = ashmem\_set\_prot\_region(ashmemFd, PROT\_READ | PROT\_WRITE);  
    if (result >= 0) {  
        void\* data = ::mmap(NULL, size, PROT\_READ | PROT\_WRITE, MAP\_SHARED, ashmemFd, 0);//文件映射  
        if (data == MAP\_FAILED) {  
            result = -errno;  
        } else {  
            result = ashmem\_set\_prot\_region(ashmemFd, PROT\_READ);  
            if (result >= 0) {  
                CursorWindow\* window = new CursorWindow(name, ashmemFd,  
                        data, size, false /\*readOnly\*/);  
                result = window->clear();  
                if (!result) {  
                    LOG\_WINDOW("Created new CursorWindow: freeOffset=%d, "  
                            "numRows=%d, numColumns=%d, mSize=%d, mData=%p",  
                            window->mHeader->freeOffset,  
                            window->mHeader->numRows,  
                            window->mHeader->numColumns,  
                            window->mSize, window->mData);  
                    \*outCursorWindow = window;  
                    return OK;  
                }  
                delete window;  
            }  
        }  
        ::munmap(data, size);  
    }  
    ::close(ashmemFd);  
}  
\*outCursorWindow = NULL;  
return result;  

}

2.通过文件句柄来创建。这样的case应该是在client的创建出一个CursorWindow所採用。

status_t CursorWindow::createFromParcel(Parcel* parcel, CursorWindow** outCursorWindow) {
String8 name = parcel->readString8();

status\_t result;  
int ashmemFd = parcel->readFileDescriptor();  
if (ashmemFd == int(BAD\_TYPE)) {  
    result = BAD\_TYPE;  
} else {  
    ssize\_t size = ashmem\_get\_size\_region(ashmemFd);  
    if (size < 0) {  
        result = UNKNOWN\_ERROR;  
    } else {  
        int dupAshmemFd = ::dup(ashmemFd);  
        if (dupAshmemFd < 0) {  
            result = -errno;  
        } else {  
            void\* data = ::mmap(NULL, size, PROT\_READ, MAP\_SHARED, dupAshmemFd, 0);  
            if (data == MAP\_FAILED) {  
                result = -errno;  
            } else {  
                CursorWindow\* window = new CursorWindow(name, dupAshmemFd,  
                        data, size, true /\*readOnly\*/);  
                LOG\_WINDOW("Created CursorWindow from parcel: freeOffset=%d, "  
                        "numRows=%d, numColumns=%d, mSize=%d, mData=%p",  
                        window->mHeader->freeOffset,  
                        window->mHeader->numRows,  
                        window->mHeader->numColumns,  
                        window->mSize, window->mData);  
                \*outCursorWindow = window;  
                return OK;  
            }  
            ::close(dupAshmemFd);  
        }  
    }  
}  
\*outCursorWindow = NULL;  
return result;  

}

CursorWindow是怎样保存查询到的数据集的呢?

原理图例如以下:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvU2FpbGluZ3RoaW5r/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

没一行所相应的数据採用FieldSlot数组来表示。

图中黄色部分表示一行所相应的数据。假设列所相应的数据是long或者double。那么就直接保存在FieldSlot中,假设是Blob或者String,那么就在FieldSlot中保存数据的廉价量。

FiledSlot的定义例如以下:

struct FieldSlot {  
private:  
    int32\_t type;//列所相应的数据的类型  
    union {  
        double d;  
        int64\_t l;  
        struct {  
            uint32\_t offset;  
            uint32\_t size;  
        } buffer;  
    } data;//data的数据类型是union,当type所表示的是String或者Blob的时候。offset表示的就是保存真实数据的buffer的偏移量。size表示buffer的大小

    friend class CursorWindow;  
} \_\_attribute((packed));

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章