標籤:圖例 long 部分 封裝 text ntp let desc set
我們通過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是怎樣儲存查詢到的資料集的呢?
原理圖例如以下:
沒一行所相應的資料採用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));
Android native CursorWindow資料儲存原理