bool DbMultipleKeyDataBuilder::append( void *kbuf, size_t klen, void *dbuf, size_t dlen) { DB_MULTIPLE_KEY_WRITE_NEXT(p_, dbt_.get_DBT(), kbuf, klen, dbuf, dlen); return (p_ != 0); }
int store_writev(struct store_req_vec *vec, int nr) { DBT db_key; int ret; size_t buf_size = 0; static char *buf; void *opaque; int i; for (i = 0; i < nr; i++) buf_size += strlen(vec[i].key) + vec[i].data_len + 256; buf = malloc(buf_size); memset(&db_key, 0, sizeof(db_key)); db_key.ulen = buf_size; db_key.data = buf; db_key.flags = DB_DBT_USERMEM; DB_MULTIPLE_WRITE_INIT(opaque, &db_key); for (i = 0; i < nr; i++) DB_MULTIPLE_KEY_WRITE_NEXT(opaque, &db_key, vec[i].key, strlen(vec[i].key) + 1, vec[i].data, vec[i].data_len); ret = dbp->put(dbp, NULL, &db_key, NULL, DB_MULTIPLE_KEY); if (ret != 0) { switch (ret) { default: dbp->err(dbp, ret, "DB->put"); return ACRD_ERR_UNKNOWN; } } free(buf); return ACRD_SUCCESS; }
/* * Use Bulk Get/Put to copy the given number of pages worth of * records from the source database to the destination database, * this function should be called until all tables are copied, at * which point it will return SQLITE_DONE. Both Btrees need to * have transactions before calling this function. * p->pSrc - Source Btree * p->tables - Contains a list of iTables to copy, gotten using * btreeGetTables(). * p->currentTable - Index in tables of the current table being copied. * p->srcCur - Cursor on the current source table being copied. * p->pDest - Destiniation Btree. * p->destCur - BtCursor on the destination table being copied into. * pages - Number of pages worth of data to copy. */ static int btreeCopyPages(sqlite3_backup *p, int *pages) { DB *dbp; DBT dataOut, dataIn; char bufOut[MULTI_BUFSIZE], bufIn[MULTI_BUFSIZE]; int ret, rc, copied, srcIsDupIndex; void *in, *out, *app; ret = 0; rc = SQLITE_OK; dbp = NULL; copied = 0; memset(&dataOut, 0, sizeof(dataOut)); memset(&dataIn, 0, sizeof(dataIn)); dataOut.flags = DB_DBT_USERMEM; dataIn.flags = DB_DBT_USERMEM; dataOut.data = bufOut; dataOut.ulen = sizeof(bufOut); dataIn.data = bufIn; dataIn.ulen = sizeof(bufIn); while (*pages < 0 || *pages > copied) { /* No tables left to copy */ if (p->tables[p->currentTable] == -1) { u32 val; /* * Update the schema file format and largest rootpage * in the meta data. Other meta data values should * not be changed. */ sqlite3BtreeGetMeta(p->pSrc, 1, &val); if (p->pSrc->db->errCode == SQLITE_BUSY) { rc = SQLITE_BUSY; goto err; } rc = sqlite3BtreeUpdateMeta(p->pDest, 1, val); if (rc != SQLITE_OK) goto err; sqlite3BtreeGetMeta(p->pSrc, 3, &val); if (p->pSrc->db->errCode == SQLITE_BUSY) { rc = SQLITE_BUSY; goto err; } rc = sqlite3BtreeUpdateMeta(p->pDest, 3, val); if (rc != SQLITE_OK) goto err; ret = SQLITE_DONE; goto err; } /* If not currently copying a table, get the next table. */ if (!p->srcCur) { rc = btreeGetUserTable(p->pSrc, p->srcTxn, &dbp, p->tables[p->currentTable]); if (rc != SQLITE_OK) goto err; assert(dbp); memset(&p->destCur, 0, sizeof(p->destCur)); /* * Open a cursor on the destination table, this will * create the table and allow the Btree to manage the * DB object. */ sqlite3BtreeCursor(p->pDest, p->tables[p->currentTable], 1, dbp->app_private, &p->destCur); if ((rc = p->destCur.error) != SQLITE_OK) { app = dbp->app_private; dbp->close(dbp, DB_NOSYNC); if (app) sqlite3DbFree(p->pSrcDb, app); goto err; } /* Open a cursor on the source table. */ if ((ret = dbp->cursor(dbp, p->srcTxn, &p->srcCur, 0)) != 0) goto err; dbp = 0; } srcIsDupIndex = isDupIndex((p->tables[p->currentTable] & 1) ? BTREE_INTKEY : 0, p->pSrc->pBt->dbStorage, p->srcCur->dbp->app_private, p->srcCur->dbp); /* * Copy the current table until the given number of * pages is copied, or the entire table has been copied. */ while (*pages < 0 || *pages > copied) { DBT key, data; memset(&key, 0, sizeof(key)); memset(&data, 0, sizeof(data)); /* Do a Bulk Get from the source table. */ ret = p->srcCur->get(p->srcCur, &key, &dataOut, DB_NEXT | DB_MULTIPLE_KEY); if (ret == DB_NOTFOUND) break; if (ret != 0) goto err; /* Copy the records into the Bulk buffer. */ DB_MULTIPLE_INIT(out, &dataOut); DB_MULTIPLE_WRITE_INIT(in, &dataIn); DB_MULTIPLE_KEY_NEXT(out, &dataOut, key.data, key.size, data.data, data.size); while (out) { /* * Have to translate the index formats if they * are not the same. */ if (p->destCur.isDupIndex != srcIsDupIndex) { if (srcIsDupIndex) { p->destCur.key = key; p->destCur.data = data; if (!btreeCreateIndexKey( &p->destCur)) { rc = SQLITE_NOMEM; goto err; } DB_MULTIPLE_KEY_WRITE_NEXT(in, &dataIn, p->destCur.index.data, p->destCur.index.size, p->destCur.data.data, 0); } else { /* Copy the key into the cursor * index since spliting the key * requires changing the * internal memory. */ if (!allocateCursorIndex( &p->destCur, key.size)) { rc = SQLITE_NOMEM; goto err; } memcpy(p->destCur.index.data, key.data, key.size); p->destCur.index.size = key.size; p->destCur.key.data = p->destCur.index.data; p->destCur.key.size = p->destCur.index.size; splitIndexKey(&p->destCur); DB_MULTIPLE_KEY_WRITE_NEXT( in, &dataIn, p->destCur.key.data, p->destCur.key.size, p->destCur.data.data, p->destCur.data.size); } } else DB_MULTIPLE_KEY_WRITE_NEXT(in, &dataIn, key.data, key.size, data.data, data.size); DB_MULTIPLE_KEY_NEXT(out, &dataOut, key.data, key.size, data.data, data.size); } /* Insert into the destination table. */ dbp = p->destCur.cached_db->dbp; if ((ret = dbp->put(dbp, p->pDest->savepoint_txn, &dataIn, 0, DB_MULTIPLE_KEY)) != 0) goto err; dbp = NULL; copied += MULTI_BUFSIZE/SQLITE_DEFAULT_PAGE_SIZE; } /* * Done copying the current table, time to look for a new * table to copy. */ if (ret == DB_NOTFOUND) { ret = 0; rc = sqlite3BtreeCloseCursor(&p->destCur); if (p->srcCur) { app = p->srcCur->dbp->app_private; dbp = p->srcCur->dbp; p->srcCur->close(p->srcCur); ret = dbp->close(dbp, DB_NOSYNC); if (app) sqlite3DbFree(p->pSrcDb, app); } p->srcCur = NULL; if (ret != 0 || rc != SQLITE_OK) goto err; p->currentTable += 1; } } goto done; err: if (ret == SQLITE_DONE) return ret; done: return MAP_ERR(rc, ret); }