19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifndef _ANDROID__DATABASE_WINDOW_H
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define _ANDROID__DATABASE_WINDOW_H
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <cutils/log.h>
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stddef.h>
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdint.h>
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
24d1f74d0e3352987467f12a65b8685b60b057d9adMathias Agopian#include <binder/IMemory.h>
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/RefBase.h>
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <jni.h>
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define DEFAULT_WINDOW_SIZE 4096
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define MAX_WINDOW_SIZE (1024 * 1024)
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define WINDOW_ALLOCATION_SIZE 4096
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define ROW_SLOT_CHUNK_NUM_ROWS 16
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// Row slots are allocated in chunks of ROW_SLOT_CHUNK_NUM_ROWS,
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// with an offset after the rows that points to the next chunk
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define ROW_SLOT_CHUNK_SIZE ((ROW_SLOT_CHUNK_NUM_ROWS * sizeof(row_slot_t)) + sizeof(uint32_t))
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if LOG_NDEBUG
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define IF_LOG_WINDOW() if (false)
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_WINDOW(...)
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define IF_LOG_WINDOW() IF_LOG(LOG_DEBUG, "CursorWindow")
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_WINDOW(...) LOG(LOG_DEBUG, "CursorWindow", __VA_ARGS__)
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// When defined to true strings are stored as UTF8, otherwise they're UTF16
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define WINDOW_STORAGE_UTF8 1
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// When defined to true numberic values are stored inline in the field_slot_t, otherwise they're allocated in the window
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define WINDOW_STORAGE_INLINE_NUMERICS 1
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android {
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projecttypedef struct
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint32_t numRows;
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint32_t numColumns;
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} window_header_t;
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projecttypedef struct
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint32_t offset;
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} row_slot_t;
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projecttypedef struct
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint8_t type;
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    union {
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        double d;
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int64_t l;
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        struct {
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            uint32_t offset;
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            uint32_t size;
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } buffer;
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } data;
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} __attribute__((packed)) field_slot_t;
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define FIELD_TYPE_INTEGER 1
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define FIELD_TYPE_FLOAT 2
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define FIELD_TYPE_STRING 3
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define FIELD_TYPE_BLOB 4
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define FIELD_TYPE_NULL 5
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This class stores a set of rows from a database in a buffer. The begining of the
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * window has first chunk of row_slot_ts, which are offsets to the row directory, followed by
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * an offset to the next chunk in a linked-list of additional chunk of row_slot_ts in case
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the pre-allocated chunk isn't big enough to refer to all rows. Each row directory has a
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * field_slot_t per column, which has the size, offset, and type of the data for that field.
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Note that the data types come from sqlite3.h.
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass CursorWindow
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic:
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        CursorWindow(size_t maxSize);
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        CursorWindow(){}
104d1f74d0e3352987467f12a65b8685b60b057d9adMathias Agopian    bool                setMemory(const sp<IMemory>&);
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ~CursorWindow();
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool                initBuffer(bool localOnly);
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp<IMemory>         getMemory() {return mMemory;}
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t              size() {return mSize;}
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint8_t *           data() {return mData;}
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint32_t            getNumRows() {return mHeader->numRows;}
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint32_t            getNumColumns() {return mHeader->numColumns;}
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void                freeLastRow() {
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (mHeader->numRows > 0) {
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                mHeader->numRows--;
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool                setNumColumns(uint32_t numColumns)
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            {
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                uint32_t cur = mHeader->numColumns;
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                if (cur > 0 && cur != numColumns) {
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    LOGE("Trying to go from %d columns to %d", cur, numColumns);
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    return false;
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                }
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                mHeader->numColumns = numColumns;
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                return true;
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int32_t             freeSpace();
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void                clear();
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        /**
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                         * Allocate a row slot and its directory. The returned
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                         * pointer points to the begining of the row's directory
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                         * or NULL if there wasn't room. The directory is
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                         * initialied with NULL entries for each field.
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                         */
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    field_slot_t *      allocRow();
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        /**
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                         * Allocate a portion of the window. Returns the offset
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                         * of the allocation, or 0 if there isn't enough space.
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                         * If aligned is true, the allocation gets 4 byte alignment.
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                         */
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint32_t            alloc(size_t size, bool aligned = false);
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint32_t            read_field_slot(int row, int column, field_slot_t * slot);
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        /**
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                         * Copy data into the window at the given offset.
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                         */
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void                copyIn(uint32_t offset, uint8_t const * data, size_t size);
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void                copyIn(uint32_t offset, int64_t data);
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void                copyIn(uint32_t offset, double data);
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void                copyOut(uint32_t offset, uint8_t * data, size_t size);
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int64_t             copyOutLong(uint32_t offset);
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    double              copyOutDouble(uint32_t offset);
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool                putLong(unsigned int row, unsigned int col, int64_t value);
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool                putDouble(unsigned int row, unsigned int col, double value);
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool                putNull(unsigned int row, unsigned int col);
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool                getLong(unsigned int row, unsigned int col, int64_t * valueOut);
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool                getDouble(unsigned int row, unsigned int col, double * valueOut);
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool                getNull(unsigned int row, unsigned int col, bool * valueOut);
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint8_t *           offsetToPtr(uint32_t offset) {return mData + offset;}
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    row_slot_t *        allocRowSlot();
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    row_slot_t *        getRowSlot(int row);
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        /**
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                         * return NULL if Failed to find rowSlot or
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                         * Invalid rowSlot
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                         */
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    field_slot_t *      getFieldSlotWithCheck(int row, int column);
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    field_slot_t *      getFieldSlot(int row, int column)
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            {
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                int fieldDirOffset = getRowSlot(row)->offset;
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                return ((field_slot_t *)offsetToPtr(fieldDirOffset)) + column;
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectprivate:
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint8_t * mData;
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t mSize;
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t mMaxSize;
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    window_header_t * mHeader;
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp<IMemory> mMemory;
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Offset of the lowest unused data byte in the array.
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint32_t mFreeOffset;
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; // namespace android
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
203