public static Node ParentFinder(Btree B, Node n1, Node n2) { Node result = B.head; Node current = n1; Node moving = n2; if (n1 == B.head || n2 == B.head) { return(result); } while (current != moving) { if (B.head == moving) { current = current.getParent(); moving = n2; } else { moving = moving.getParent(); } if (current == moving) { result = moving; } } return(result); }
public void OpenClose() { Utility.WrapNativeSyncInvokeInMTA(() => { Uri owner = new Uri("fabric://test/btree"); LogHelper.Log("Begin construct btree"); Btree <int, int, Int32KeyBitConverter, Int32ValueBitConverter> tree = new Btree <int, int, Int32KeyBitConverter, Int32ValueBitConverter>(); LogHelper.Log("End construct btree"); // // Key configuration // LogHelper.Log("Start create key description"); KeyComparisonDescription keyDescription = new KeyComparisonDescription(); keyDescription.CultureInfo = Globalization.CultureInfo.InvariantCulture; keyDescription.IsFixedLengthKey = true; keyDescription.KeyDataType = (int)DataType.Int32; keyDescription.MaximumKeySizeInBytes = sizeof(int); LogHelper.Log("End create key description"); // // Storage configuration // LogHelper.Log("Start create storage description"); BtreeStorageConfigurationDescription storageDescription = new BtreeStorageConfigurationDescription(); storageDescription.IsVolatile = true; storageDescription.MaximumMemoryInMB = 1024; storageDescription.MaximumPageSizeInKB = 4; storageDescription.MaximumStorageInMB = 0; storageDescription.RetriesBeforeTimeout = 100; storageDescription.StoreDataInline = true; LogHelper.Log("End create key description"); // // Btree configuration // LogHelper.Log("Start create btree description"); BtreeConfigurationDescription btreeConfig = new BtreeConfigurationDescription(); btreeConfig.KeyComparison = keyDescription; btreeConfig.StorageConfiguration = storageDescription; btreeConfig.PartitionId = Guid.NewGuid(); btreeConfig.ReplicaId = 130083631515748206; LogHelper.Log("End create btree description"); // // Open the btree // LogHelper.Log("Begin open btree"); tree.OpenAsync(btreeConfig, false, CancellationToken.None).Wait(); LogHelper.Log("End open btree"); // // Close the btree // LogHelper.Log("Begin close btree"); tree.CloseAsync(true, CancellationToken.None).Wait(); LogHelper.Log("End close btree"); }, "OpenClose"); }
public object this[object key] { get { object val; TryGetValue(key, out val); return(val); } set { if (index == null) { int size = values.Count; int i = binarySearch(key); if (i >= 0) { values[i] = value; } else { if (size == BtreeTreshold) { index = Storage.CreateIndex(Btree.mapKeyType(type), true); object[] keys = (object[])this.keys; for (i = 0; i < size; i++) { index[keys[i]] = values[i]; } index[key] = value; this.keys = null; this.values = null; Modify(); } else { object[] oldKeys = (object[])keys; i = ~i; if (size >= oldKeys.Length) { object[] newKeys = new IComparable[size + 1 > oldKeys.Length * 2 ? size + 1 : oldKeys.Length * 2]; Array.Copy(oldKeys, 0, newKeys, 0, i); Array.Copy(oldKeys, i, newKeys, i + 1, size - i); keys = newKeys; newKeys[i] = key; } else { Array.Copy(oldKeys, i, oldKeys, i + 1, size - i); oldKeys[i] = key; } values.Insert(i, value); } } } else { index[key] = value; } } }
/// <summary> /// Add a File object to the Set /// </summary> /// <param name="f"></param> /// <param name="f"> </param> /// <returns></returns> public IFile Add(IFile f) { if (this.Btree.File.Server.ReadOnly) { throw new InvalidOperationException("Object Server is in read only mode."); } if (f == null) { throw new ArgumentNullException("f"); } return(Locker.Invoke(() => { if (!Btree.Contains(f.Name)) { if (f.Server == null) { f.Server = this.Btree.File.Server; } if (!f.IsOpen) { f.Open(); } if (f.IsDirty) { f.Flush(); } Btree.Add(f.Name, f); //Btree.Flush(); return f; } throw new ArgumentException(string.Format("File object with Name '{0}' is already in FileSet", f.Name)); })); }
internal void exportMultiFieldIndex(int oid, byte[] data) { Btree btree = new Btree(data, ObjectHeader.Sizeof); storage.assignOid(btree, oid); writer.Write(" <Perst.Impl.BtreeMultiFieldIndex id=\"" + oid + "\" unique=\"" + (btree.unique ? '1' : '0') + "\" class="); int offs = exportString(data, Btree.Sizeof); int nFields = Bytes.unpack4(data, offs); offs += 4; for (int i = 0; i < nFields; i++) { writer.Write(" field" + i + "="); offs = exportString(data, offs); } writer.Write(">\n"); int nTypes = Bytes.unpack4(data, offs); offs += 4; compoundKeyTypes = new ClassDescriptor.FieldType[nTypes]; for (int i = 0; i < nTypes; i++) { compoundKeyTypes[i] = (ClassDescriptor.FieldType)Bytes.unpack4(data, offs); offs += 4; } btree.export(this); compoundKeyTypes = null; writer.Write(" </Perst.Impl.BtreeMultiFieldIndex>\n"); }
/* ** Find and return the schema associated with a BTree. Create ** a new one if necessary. */ static Schema sqlite3SchemaGet(sqlite3 db, Btree pBt) { Schema p; if (pBt != null) { p = sqlite3BtreeSchema(pBt, -1, (dxFreeSchema)sqlite3SchemaClear);//Schema.Length, sqlite3SchemaFree); } else { p = new Schema(); // (Schema *)sqlite3DbMallocZero(0, sizeof(Schema)); } if (p == null) { //// db.mallocFailed = 1; } else if (0 == p.file_format) { sqlite3HashInit(p.tblHash); sqlite3HashInit(p.idxHash); sqlite3HashInit(p.trigHash); sqlite3HashInit(p.fkeyHash); p.enc = SQLITE_UTF8; } return(p); }
/// <summary> /// Close the FileSet /// </summary> public void Close() { Locker.Invoke(() => { if (Btree.IsOpen && Btree.RootNode != null) { foreach (MruItem o in Btree.MruManager.Values) { for (int i = 0; i < ((BTreeNodeOnDisk)o.Value).Count; i++) { object f = ((BTreeNodeOnDisk)o.Value).Slots[i].Value.Data; if (f is File) { ((File)f).Close(); } } } for (int i = 0; i < Btree.RootNode.Count; i++) { if (Btree.RootNode.Slots[i].Value.Data is File) { ((File)Btree.RootNode.Slots[i].Value.Data).Close(); } } Btree.Close(); } //DiskBuffer.ClearData(); }); }
/// <summary> /// Add a File object to the Set /// </summary> /// <param name="name">Name of File Object</param> /// <param name="filename"></param> /// <param name="profile">Contains configuration data for this File</param> /// <returns></returns> public IFile Add(string name, string filename = null, Profile profile = null) { if (this.Btree.File.Server.ReadOnly) { throw new InvalidOperationException("Object Server is in read only mode."); } if (string.IsNullOrEmpty(name)) { throw new ArgumentNullException("name"); } if (string.IsNullOrEmpty(filename)) { filename = string.Format("{0}{1}.{2}", this.Btree.File.Server.Path, name, ObjectServer.DefaultFileExtension); } return(Locker.Invoke(() => { if (Btree.Contains(name)) { throw new ArgumentException(string.Format("File object with Name '{0}' is already in FileSet", name)); } IFile f = null; if (Btree.Transaction != null) { f = ((Transaction.TransactionBase)Btree.Transaction).CreateFile(Btree.File.Server, name, filename); } else { f = new File(Btree.File.Server, name, filename); } ((File)f).Profile = profile == null ? new Profile(Btree.File.Profile) : profile; return Add(f); })); }
/* ** Enter a mutex on the given BTree object. ** ** If the object is not sharable, then no mutex is ever required ** and this routine is a no-op. The underlying mutex is non-recursive. ** But we keep a reference count in Btree.wantToLock so the behavior ** of this interface is recursive. ** ** To avoid deadlocks, multiple Btrees are locked in the same order ** by all database connections. The p->pNext is a list of other ** Btrees belonging to the same database connection as the p Btree ** which need to be locked after p. If we cannot get a lock on ** p, then first unlock all of the others on p->pNext, then wait ** for the lock to become available on p, then relock all of the ** subsequent Btrees that desire a lock. */ void sqlite3BtreeEnter(Btree *p) { Btree *pLater; /* Some basic sanity checking on the Btree. The list of Btrees ** connected by pNext and pPrev should be in sorted order by ** Btree.pBt value. All elements of the list should belong to ** the same connection. Only shared Btrees are on the list. */ assert( p->pNext==0 || p->pNext->pBt>p->pBt ); assert( p->pPrev==0 || p->pPrev->pBt<p->pBt ); assert( p->pNext==0 || p->pNext->db==p->db ); assert( p->pPrev==0 || p->pPrev->db==p->db ); assert( p->sharable || (p->pNext==0 && p->pPrev==0) ); /* Check for locking consistency */ assert( !p->locked || p->wantToLock>0 ); assert( p->sharable || p->wantToLock==0 ); /* We should already hold a lock on the database connection */ assert( sqlite3_mutex_held(p->db->mutex) ); /* Unless the database is sharable and unlocked, then BtShared.db ** should already be set correctly. */ assert( (p->locked==0 && p->sharable) || p->pBt->db==p->db ); if( !p->sharable ) return; p->wantToLock++; if( p->locked ) return; /* In most cases, we should be able to acquire the lock we ** want without having to go throught the ascending lock ** procedure that follows. Just be sure not to block. */ if( sqlite3_mutex_try(p->pBt->mutex)==SQLITE_OK ){ p->pBt->db = p->db; p->locked = 1; return; } /* To avoid deadlock, first release all locks with a larger ** BtShared address. Then acquire our lock. Then reacquire ** the other BtShared locks that we used to hold in ascending ** order. */ for(pLater=p->pNext; pLater; pLater=pLater->pNext){ assert( pLater->sharable ); assert( pLater->pNext==0 || pLater->pNext->pBt>pLater->pBt ); assert( !pLater->locked || pLater->wantToLock>0 ); if( pLater->locked ){ unlockBtreeMutex(pLater); } } lockBtreeMutex(p); for(pLater=p->pNext; pLater; pLater=pLater->pNext){ if( pLater->wantToLock ){ lockBtreeMutex(pLater); } } }
/// <summary> /// Serialize /// </summary> /// <param name="parent"></param> /// <param name="writer"></param> public void Pack(IInternalPersistent parent, System.IO.BinaryWriter writer) { if (IsDirty) { Flush(); } Btree.Pack(parent, writer); }
/// <summary> /// Removes the element with the specified key from the <see cref="T:System.Collections.Generic.IDictionary`2"/>. /// </summary> /// <returns> /// true if the element is successfully removed; otherwise, false. This method also returns false if <paramref name="key"/> was not found in the original <see cref="T:System.Collections.Generic.IDictionary`2"/>. /// </returns> /// <param name="key">The key of the element to remove. /// </param><exception cref="T:System.ArgumentNullException"><paramref name="key"/> is null. /// </exception><exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.IDictionary`2"/> is read-only. /// </exception> public bool Remove(TKey key) { Locker.Lock(); var r = Btree.Remove(key); Locker.Unlock(); return(r); }
public bool Search(TKey key, bool goToFirstInstance) { Locker.Lock(); bool r = Btree.Search(key, goToFirstInstance); Locker.Unlock(); return(r); }
/// <summary> /// Creates a new object that is a copy of the current instance. /// </summary> /// <returns> /// A new object that is a copy of this instance. /// </returns> /// <filterpriority>2</filterpriority> public object Clone() { Locker.Lock(); var r = Btree.Clone(); Locker.Unlock(); return(r); }
/* ** Release the BtShared mutex associated with B-Tree handle p and ** clear the p->locked boolean. */ static void unlockBtreeMutex(Btree *p){ assert( p->locked==1 ); assert( sqlite3_mutex_held(p->pBt->mutex) ); assert( sqlite3_mutex_held(p->db->mutex) ); assert( p->db==p->pBt->db ); sqlite3_mutex_leave(p->pBt->mutex); p->locked = 0; }
/// <summary> /// Constructor de la clase Usuario para asignar valores a sus atributos /// </summary> /// <param name="nombre">Nombre del usuario</param> /// <param name="apellido">Apellido del usuario</param> /// <param name="edad">Edad del ususario</param> /// <param name="username">Username del usuario</param> /// <param name="password">Password del usuario</param> public Usuario(string nombre, string apellido, int edad, string username, string password) { Nombre = nombre; Apellido = apellido; Edad = edad; Username = username; Password = password; WatchList = new Btree <Producto>(5, comparer.CompareByName); }
/// <summary> /// MoveLast makes the last entry in the Collection current. /// </summary> public bool MoveLast() { Locker.Lock(); var r = this.SortOrder == SortOrderType.Ascending ? Btree.MoveLast() : MoveFirst(); Locker.Unlock(); return(r); }
internal void exportSet(int oid, byte[] data) { Btree btree = new Btree(data, ObjectHeader.Sizeof); storage.assignOid(btree, oid); writer.Write(" <Perst.Impl.PersistentSet id=\"" + oid + "\">\n"); btree.export(this); writer.Write(" </Perst.Impl.PersistentSet>\n"); }
internal void exportIndex(int oid, byte[] data) { Btree btree = new Btree(data, ObjectHeader.Sizeof); storage.assignOid(btree, oid); writer.Write(" <Perst.Impl.Btree id=\"" + oid + "\" unique=\"" + (btree.unique?'1':'0') + "\" type=\"" + btree.type + "\">\n"); btree.export(this); writer.Write(" </Perst.Impl.Btree>\n"); }
/// <summary> /// Save the changes on the File set /// </summary> public void Flush() { if (this.Btree.File.Server.ReadOnly) { throw new InvalidOperationException("Object Server is in read only mode."); } //btree.IsDirty = true; Btree.Flush(); }
/// <summary> /// MovePrevious makes the previous entry current. /// </summary> public bool MovePrevious() { Locker.Lock(); var r = this.SortOrder == SortOrderType.Ascending ? Btree.MovePrevious() : Btree.MoveNext(); Locker.Unlock(); return(r); }
/* ** 2007 August 27 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file contains code used to implement mutexes on Btree objects. ** This code really belongs in btree.c. But btree.c is getting too ** big and we want to break it down some. This packaged seemed like ** a good breakout. ************************************************************************* ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart ** C#-SQLite is an independent reimplementation of the SQLite software library ** ** SQLITE_SOURCE_ID: 2011-05-19 13:26:54 ed1da510a239ea767a01dc332b667119fa3c908e ** ************************************************************************* */ //#include "btreeInt.h" #if !SQLITE_OMIT_SHARED_CACHE #if SQLITE_THREADSAFE /* ** Obtain the BtShared mutex associated with B-Tree handle p. Also, ** set BtShared.db to the database handle associated with p and the ** p->locked boolean to true. */ static void lockBtreeMutex(Btree *p){ assert( p->locked==0 ); assert( sqlite3_mutex_notheld(p->pBt->mutex) ); assert( sqlite3_mutex_held(p->db->mutex) ); sqlite3_mutex_enter(p->pBt->mutex); p->pBt->db = p->db; p->locked = 1; }
public override IBTreeNode GetParent() { if (_parent != null) { return(_parent); } _parent = Btree.GetPersister().LoadNodeById(_parentOid); return(_parent); }
/// <summary> /// Constructor de la clase Usuario /// </summary> public Usuario() { Nombre = default(string); Apellido = default(string); Edad = default(int); Username = default(string); Password = default(string); Administrador = false; WatchList = new Btree <Producto>(5, comparer.CompareByName); }
public static RC AnalysisLoad(Context ctx, int db) { Debug.Assert(db >= 0 && db < ctx.DBs.length); Debug.Assert(ctx.DBs[db].Bt != null); // Clear any prior statistics Debug.Assert(Btree.SchemaMutexHeld(ctx, db, null)); for (HashElem i = ctx.DBs[db].Schema.IndexHash.First; i != null; i = i.Next) { Index idx = (Index)i.Data; sqlite3DefaultRowEst(idx); sqlite3DeleteIndexSamples(ctx, idx); idx.Samples.data = null; } // Check to make sure the sqlite_stat1 table exists AnalysisInfo sInfo = new AnalysisInfo(); sInfo.Ctx = ctx; sInfo.Database = ctx.DBs[db].Name; if (sqlite3FindTable(ctx, "sqlite_stat1", sInfo.Database) == null) { return(RC.ERROR); } // Load new statistics out of the sqlite_stat1 table string sql = C._mtagprintf(ctx, "SELECT tbl, idx, stat FROM %Q.sqlite_stat1", sInfo.Database); if (sql == null) { rc = RC.NOMEM; } else { rc = Vdbe.Exec(ctx, sql, AnalysisLoader, sInfo, 0); C._tagfree(ctx, ref sql); } // Load the statistics from the sqlite_stat3 table. #if ENABLE_STAT3 if (rc == RC_OK) { bool lookasideEnabled = ctx.Lookaside.Enabled; ctx.Lookaside.Enabled = false; rc = LoadStat3(ctx, sInfo.Database); ctx.Lookaside.Enabled = lookasideEnabled; } #endif if (rc == RC.NOMEM) { db.MallocFailed = true; } return(rc); }
/// <summary> /// Open the File Set /// </summary> public void Open() { if (Btree is SortedDictionaryOnDisk) { ((SortedDictionaryOnDisk)Btree).BTreeAlgorithm.Open(); } else { Btree.Open(); } }
static void OpenStatTable(Parse parse, int db, int statCur, string where_, string whereType) { int[] roots = new int[] { 0, 0 }; byte[] createTbls = new byte[] { 0, 0 }; Context ctx = parse.Ctx; Vdbe v = parse.GetVdbe(); if (v == null) { return; } Debug.Assert(Btree.HoldsAllMutexes(ctx)); Debug.Assert(v.Ctx == ctx); Context.DB dbObj = ctx.DBs[db]; for (int i = 0; i < _tables.Length; i++) { string tableName = _tables[i].Name; Table stat; if ((stat = Parse.FindTable(ctx, tableName, dbObj.Name)) == null) { // The sqlite_stat[12] table does not exist. Create it. Note that a side-effect of the CREATE TABLE statement is to leave the rootpage // of the new table in register pParse.regRoot. This is important because the OpenWrite opcode below will be needing it. parse.NestedParse("CREATE TABLE %Q.%s(%s)", dbObj.Name, tableName, _tables[i].Cols); roots[i] = parse.RegRoot; createTbls[i] = Vdbe::OPFLAG_P2ISREG; } else { // The table already exists. If zWhere is not NULL, delete all entries associated with the table zWhere. If zWhere is NULL, delete the // entire contents of the table. roots[i] = stat.Id; sqlite3TableLock(parse, db, roots[i], 1, tableName); if (where_ == null) { parse.NestedParse("DELETE FROM %Q.%s WHERE %s=%Q", dbObj.Name, tableName, whereType, where_); } else { v.AddOp2(OP.Clear, roots[i], db); // The sqlite_stat[12] table already exists. Delete all rows. } } } // Open the sqlite_stat[12] tables for writing. for (int i = 0; i < _tables.Length; i++) { v.AddOp3(OP.OpenWrite, statCur + i, roots[i], db); v.ChangeP4(-1, 3, Vdbe.P4T.INT32); v.ChangeP5(createTbls[i]); } }
/* ** Check schema cookies in all databases. If any cookie is out ** of date set pParse->rc to SQLITE_SCHEMA. If all schema cookies ** make no changes to pParse->rc. */ static void schemaIsValid(Parse pParse) { sqlite3 db = pParse.db; int iDb; int rc; u32 cookie = 0; Debug.Assert(pParse.checkSchema != 0); Debug.Assert(sqlite3_mutex_held(db.mutex)); for (iDb = 0; iDb < db.nDb; iDb++) { int openedTransaction = 0; /* True if a transaction is opened */ Btree pBt = db.aDb[iDb].pBt; /* Btree database to read cookie from */ if (pBt == null) { continue; } /* If there is not already a read-only (or read-write) transaction opened ** on the b-tree database, open one now. If a transaction is opened, it ** will be closed immediately after reading the meta-value. */ if (!sqlite3BtreeIsInReadTrans(pBt)) { rc = sqlite3BtreeBeginTrans(pBt, 0); //if ( rc == SQLITE_NOMEM || rc == SQLITE_IOERR_NOMEM ) //{ // db.mallocFailed = 1; //} if (rc != SQLITE_OK) { return; } openedTransaction = 1; } /* Read the schema cookie from the database. If it does not match the ** value stored as part of the in-memory schema representation, ** set Parse.rc to SQLITE_SCHEMA. */ sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, ref cookie); Debug.Assert(sqlite3SchemaMutexHeld(db, iDb, null)); if (cookie != db.aDb[iDb].pSchema.schema_cookie) { sqlite3ResetInternalSchema(db, iDb); pParse.rc = SQLITE_SCHEMA; } /* Close the transaction, if one was opened. */ if (openedTransaction != 0) { sqlite3BtreeCommit(pBt); } } }
static void sqlite3BtreeEnterAll(sqlite3 db) { int i; for (i = 0; i < db.nDb; i++) { Btree p = db.aDb[i].pBt; if (p != null) { p.pBt.db = p.db; } } }
/// <summary> /// Save the changes on the File set /// </summary> public void Flush() { // if disposed then don't flush... if (Btree == null) { return; } if (this.Btree.File.Server.ReadOnly) { throw new InvalidOperationException("Object Server is in read only mode."); } Locker.Invoke(() => { Btree.Flush(); }); }
/* ** Usage: btree_open FILENAME NCACHE FLAGS ** ** Open a new database */ static int btree_open( object NotUsed, Tcl_Interp interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ TclObject[] argv /* Text of each argument */ ) { Btree pBt = null; int rc; int nCache = 0; int flags = 0; string zBuf = ""; if (argc != 4) { TCL.Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0].ToString(), " FILENAME NCACHE FLAGS\"", ""); return(TCL.TCL_ERROR); } if (TCL.Tcl_GetInt(interp, argv[2], ref nCache)) { return(TCL.TCL_ERROR); } if (TCL.Tcl_GetInt(interp, argv[3], ref flags)) { return(TCL.TCL_ERROR); } nRefSqlite3++; if (nRefSqlite3 == 1) { sDb.pVfs = sqlite3_vfs_find(null); sDb.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE); sqlite3_mutex_enter(sDb.mutex); } rc = sqlite3BtreeOpen(argv[1].ToString(), sDb, ref pBt, flags, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB); if (rc != SQLITE_OK) { TCL.Tcl_AppendResult(interp, errorName(rc), null); return(TCL.TCL_ERROR); } sqlite3BtreeSetCacheSize(pBt, nCache); sqlite3_snprintf(100, ref zBuf, "->%p", pBt); if (TCL.Tcl_CreateCommandPointer(interp, zBuf, pBt)) { return(TCL.TCL_ERROR); } else { TCL.Tcl_AppendResult(interp, zBuf, null); } return(TCL.TCL_OK); }
internal void exportFieldIndex(int oid, byte[] data) { Btree btree = new Btree(data, ObjectHeader.Sizeof); storage.assignOid(btree, oid); writer.Write(" <Perst.Impl.BtreeFieldIndex id=\"" + oid + "\" unique=\"" + (btree.unique?'1':'0') + "\" class="); int offs = exportString(data, Btree.Sizeof); writer.Write(" field="); offs = exportString(data, offs); writer.Write(" autoinc=\"" + Bytes.unpack8(data, offs) + "\">\n"); btree.export(this); writer.Write(" </Perst.Impl.BtreeFieldIndex>\n"); }
/// <summary> /// Open the File Set /// </summary> public void Open() { Locker.Invoke(() => { if (Btree is SortedDictionaryOnDisk) { ((SortedDictionaryOnDisk)Btree).BTreeAlgorithm.Open(); } else { Btree.Open(); } }); }
static void Main() { var obj = new Btree(); var rnd = new System.Random(1); var init = Enumerable.Range(0, 15).OrderBy(x => rnd.Next()).ToArray(); foreach (var i in init) { obj.Insert(i); } obj.root = obj.buildtree(obj.root); obj.Print(); }
private void Mark() { int bitmapSize = (int) (SupportClass.URShift(header.root[currIndex].size, (dbAllocationQuantumBits + 5))) + 1; bool existsNotMarkedObjects; long pos; int i, j; if (listener != null) { listener.GcStarted(); } greyBitmap = new int[bitmapSize]; blackBitmap = new int[bitmapSize]; int rootOid = header.root[currIndex].rootObject; if (rootOid != 0) { MarkOid(rootOid); do { existsNotMarkedObjects = false; for (i = 0; i < bitmapSize; i++) { if (greyBitmap[i] != 0) { existsNotMarkedObjects = true; for (j = 0; j < 32; j++) { if ((greyBitmap[i] & (1 << j)) != 0) { pos = (((long) i << 5) + j) << dbAllocationQuantumBits; greyBitmap[i] &= ~ (1 << j); blackBitmap[i] |= 1 << j; int offs = (int) pos & (Page.pageSize - 1); Page pg = pool.GetPage(pos - offs); int typeOid = ObjectHeader.GetType(pg.data, offs); if (typeOid != 0) { ClassDescriptor desc = FindClassDescriptor(typeOid); if (typeof(Btree).IsAssignableFrom(desc.cls)) { Btree btree = new Btree(pg.data, ObjectHeader.Sizeof + offs); btree.AssignOid(this, 0, false); btree.MarkTree(); } else if (desc.hasReferences) { MarkObject(pool.Get(pos), ObjectHeader.Sizeof, desc); } } pool.Unfix(pg); } } } } } while (existsNotMarkedObjects); } }
static void btreeIntegrity(Btree p) { }
/* ** This routine is called to create a connection to a database BTree ** driver. If zFilename is the name of a file, then that file is ** opened and used. If zFilename is the magic name ":memory:" then ** the database is stored in memory (and is thus forgotten as soon as ** the connection is closed.) If zFilename is NULL then the database ** is a "virtual" database for transient use only and is deleted as ** soon as the connection is closed. ** ** A virtual database can be either a disk file (that is automatically ** deleted when the file is closed) or it an be held entirely in memory. ** The sqlite3TempInMemory() function is used to determine which. */ static int sqlite3BtreeFactory( sqlite3 db, /* Main database when opening aux otherwise 0 */ string zFilename, /* Name of the file containing the BTree database */ bool omitJournal, /* if TRUE then do not journal this file */ int nCache, /* How many pages in the page cache */ int vfsFlags, /* Flags passed through to vfsOpen */ ref Btree ppBtree /* Pointer to new Btree object written here */ ) { int btFlags = 0; int rc; Debug.Assert( sqlite3_mutex_held( db.mutex ) ); //Debug.Assert( ppBtree != null); if ( omitJournal ) { btFlags |= BTREE_OMIT_JOURNAL; } if ( ( db.flags & SQLITE_NoReadlock ) != 0 ) { btFlags |= BTREE_NO_READLOCK; } #if !SQLITE_OMIT_MEMORYDB if ( String.IsNullOrEmpty( zFilename ) && sqlite3TempInMemory( db ) ) { zFilename = ":memory:"; } #endif // * SQLITE_OMIT_MEMORYDB */ if ( ( vfsFlags & SQLITE_OPEN_MAIN_DB ) != 0 && ( zFilename == null ) ) {// || *zFilename==0) ){ vfsFlags = ( vfsFlags & ~SQLITE_OPEN_MAIN_DB ) | SQLITE_OPEN_TEMP_DB; } rc = sqlite3BtreeOpen( zFilename, db, ref ppBtree, btFlags, vfsFlags ); /* If the B-Tree was successfully opened, set the pager-cache size to the ** default value. Except, if the call to BtreeOpen() returned a handle ** open on an existing shared pager-cache, do not change the pager-cache ** size. */ if ( rc == SQLITE_OK && null == sqlite3BtreeSchema( ppBtree, 0, null ) ) { sqlite3BtreeSetCacheSize( ppBtree, nCache ); } return rc; }
//# define sqlite3BtreeHoldsMutex(X) 1 static bool sqlite3BtreeHoldsMutex( Btree X ) { return true; }
//# define sqlite3BtreeSharable(X) 0 static bool sqlite3BtreeSharable( Btree X ) { return false; }
//int sqlite3BtreeCursor( // Btree*, /* BTree containing table to open */ // int iTable, /* Index of root page */ // int wrFlag, /* 1 for writing. 0 for read-only */ // struct KeyInfo*, /* First argument to compare function */ // BtCursor pCursor /* Space to write cursor structure */ //); //int sqlite3BtreeCursorSize(void); //void sqlite3BtreeCursorZero(BtCursor); //int sqlite3BtreeCloseCursor(BtCursor); //int sqlite3BtreeMovetoUnpacked( // BtCursor*, // UnpackedRecord pUnKey, // i64 intKey, // int bias, // int pRes //); //int sqlite3BtreeCursorHasMoved(BtCursor*, int); //int sqlite3BtreeDelete(BtCursor); //int sqlite3BtreeInsert(BtCursor*, const void pKey, i64 nKey, // const void pData, int nData, // int nZero, int bias, int seekResult); //int sqlite3BtreeFirst(BtCursor*, int pRes); //int sqlite3BtreeLast(BtCursor*, int pRes); //int sqlite3BtreeNext(BtCursor*, int pRes); //int sqlite3BtreeEof(BtCursor); //int sqlite3BtreePrevious(BtCursor*, int pRes); //int sqlite3BtreeKeySize(BtCursor*, i64 pSize); //int sqlite3BtreeKey(BtCursor*, u32 offset, u32 amt, void); //const void *sqlite3BtreeKeyFetch(BtCursor*, int pAmt); //const void *sqlite3BtreeDataFetch(BtCursor*, int pAmt); //int sqlite3BtreeDataSize(BtCursor*, u32 pSize); //int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void); //void sqlite3BtreeSetCachedRowid(BtCursor*, sqlite3_int64); //sqlite3_int64 sqlite3BtreeGetCachedRowid(BtCursor); //char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int); //struct Pager *sqlite3BtreePager(Btree); //int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void); //void sqlite3BtreeCacheOverflow(BtCursor ); //void sqlite3BtreeClearCursor(BtCursor ); //int sqlite3BtreeSetVersion(Btree *pBt, int iVersion); //#if !NDEBUG //int sqlite3BtreeCursorIsValid(BtCursor); //#endif //#if !SQLITE_OMIT_BTREECOUNT //int sqlite3BtreeCount(BtCursor *, i64 ); //#endif //#if SQLITE_TEST //int sqlite3BtreeCursorInfo(BtCursor*, int*, int); //void sqlite3BtreeCursorList(Btree); //#endif #if !SQLITE_OMIT_WAL //int sqlite3BtreeCheckpoint(Btree*, int, int *, int ); #endif /* ** If we are not using shared cache, then there is no need to ** use mutexes to access the BtShared structures. So make the ** Enter and Leave procedures no-ops. */ #if !SQLITE_OMIT_SHARED_CACHE //void sqlite3BtreeEnter(Btree); //void sqlite3BtreeEnterAll(sqlite3); #else //# define sqlite3BtreeEnter(X) static void sqlite3BtreeEnter( Btree bt ) { }
/* ** Exit the recursive mutex on a Btree. */ void sqlite3BtreeLeave(Btree *p){ if( p->sharable ){ assert( p->wantToLock>0 ); p->wantToLock--; if( p->wantToLock==0 ){ unlockBtreeMutex(p); } } }
/* ** Return true if a particular Btree requires a lock. Return FALSE if ** no lock is ever required since it is not sharable. */ int sqlite3BtreeSharable(Btree *p){ return p->sharable; }
static void sqlite3BtreeEnter( Btree p ) { p.pBt.db = p.db; }
/* ** Query to see if Btree handle p may obtain a lock of type eLock ** (READ_LOCK or WRITE_LOCK) on the table with root-page iTab. Return ** SQLITE_OK if the lock may be obtained (by calling ** setSharedCacheTableLock()), or SQLITE_LOCKED if not. */ static int querySharedCacheTableLock(Btree p, Pgno iTab, u8 eLock){ BtShared pBt = p.pBt; BtLock pIter; Debug.Assert( sqlite3BtreeHoldsMutex(p) ); Debug.Assert( eLock==READ_LOCK || eLock==WRITE_LOCK ); Debug.Assert( p.db!=null ); Debug.Assert( !(p.db.flags&SQLITE_ReadUncommitted)||eLock==WRITE_LOCK||iTab==1 ); /* If requesting a write-lock, then the Btree must have an open write ** transaction on this file. And, obviously, for this to be so there ** must be an open write transaction on the file itself. */ Debug.Assert( eLock==READ_LOCK || (p==pBt.pWriter && p.inTrans==TRANS_WRITE) ); Debug.Assert( eLock==READ_LOCK || pBt.inTransaction==TRANS_WRITE ); /* This routine is a no-op if the shared-cache is not enabled */ if( !p.sharable ){ return SQLITE_OK; } /* If some other connection is holding an exclusive lock, the ** requested lock may not be obtained. */ if( pBt.pWriter!=p && pBt.isExclusive ){ sqlite3ConnectionBlocked(p.db, pBt.pWriter.db); return SQLITE_LOCKED_SHAREDCACHE; } for(pIter=pBt.pLock; pIter; pIter=pIter.pNext){ /* The condition (pIter.eLock!=eLock) in the following if(...) ** statement is a simplification of: ** ** (eLock==WRITE_LOCK || pIter.eLock==WRITE_LOCK) ** ** since we know that if eLock==WRITE_LOCK, then no other connection ** may hold a WRITE_LOCK on any table in this file (since there can ** only be a single writer). */ Debug.Assert( pIter.eLock==READ_LOCK || pIter.eLock==WRITE_LOCK ); Debug.Assert( eLock==READ_LOCK || pIter.pBtree==p || pIter.eLock==READ_LOCK); if( pIter.pBtree!=p && pIter.iTable==iTab && pIter.eLock!=eLock ){ sqlite3ConnectionBlocked(p.db, pIter.pBtree.db); if( eLock==WRITE_LOCK ){ Debug.Assert( p==pBt.pWriter ); pBt.isPending = 1; } return SQLITE_LOCKED_SHAREDCACHE; } } return SQLITE_OK; }
/* ** Add a new Btree pointer to a BtreeMutexArray. ** if the pointer can possibly be shared with ** another database connection. ** ** The pointers are kept in sorted order by pBtree->pBt. That ** way when we go to enter all the mutexes, we can enter them ** in order without every having to backup and retry and without ** worrying about deadlock. ** ** The number of shared btrees will always be small (usually 0 or 1) ** so an insertion sort is an adequate algorithm here. */ void sqlite3BtreeMutexArrayInsert(BtreeMutexArray *pArray, Btree *pBtree) { int i, j; BtShared *pBt; if( pBtree==0 || pBtree->sharable==0 ) return; #if !NDEBUG { for(i=0; i<pArray->nMutex; i++){ assert( pArray->aBtree[i]!=pBtree ); } } #endif assert( pArray->nMutex>=0 ); assert( pArray->nMutex<ArraySize(pArray->aBtree)-1 ); pBt = pBtree->pBt; for(i=0; i<pArray->nMutex; i++){ assert( pArray->aBtree[i]!=pBtree ); if( pArray->aBtree[i]->pBt>pBt ){ for(j=pArray->nMutex; j>i; j--){ pArray->aBtree[j] = pArray->aBtree[j-1]; } pArray->aBtree[i] = pBtree; pArray->nMutex++; return; } } pArray->aBtree[pArray->nMutex++] = pBtree; }
/* ** Add a lock on the table with root-page iTable to the shared-btree used ** by Btree handle p. Parameter eLock must be either READ_LOCK or ** WRITE_LOCK. ** ** This function assumes the following: ** ** (a) The specified Btree object p is connected to a sharable ** database (one with the BtShared.sharable flag set), and ** ** (b) No other Btree objects hold a lock that conflicts ** with the requested lock (i.e. querySharedCacheTableLock() has ** already been called and returned SQLITE_OK). ** ** SQLITE_OK is returned if the lock is added successfully. SQLITE_NOMEM ** is returned if a malloc attempt fails. */ static int setSharedCacheTableLock(Btree p, Pgno iTable, u8 eLock){ BtShared pBt = p.pBt; BtLock pLock = 0; BtLock pIter; Debug.Assert( sqlite3BtreeHoldsMutex(p) ); Debug.Assert( eLock==READ_LOCK || eLock==WRITE_LOCK ); Debug.Assert( p.db!=null ); /* A connection with the read-uncommitted flag set will never try to ** obtain a read-lock using this function. The only read-lock obtained ** by a connection in read-uncommitted mode is on the sqlite_master ** table, and that lock is obtained in BtreeBeginTrans(). */ Debug.Assert( 0==(p.db.flags&SQLITE_ReadUncommitted) || eLock==WRITE_LOCK ); /* This function should only be called on a sharable b-tree after it ** has been determined that no other b-tree holds a conflicting lock. */ Debug.Assert( p.sharable ); Debug.Assert( SQLITE_OK==querySharedCacheTableLock(p, iTable, eLock) ); /* First search the list for an existing lock on this table. */ for(pIter=pBt.pLock; pIter; pIter=pIter.pNext){ if( pIter.iTable==iTable && pIter.pBtree==p ){ pLock = pIter; break; } } /* If the above search did not find a BtLock struct associating Btree p ** with table iTable, allocate one and link it into the list. */ if( !pLock ){ pLock = (BtLock *)sqlite3MallocZero(sizeof(BtLock)); if( !pLock ){ return SQLITE_NOMEM; } pLock.iTable = iTable; pLock.pBtree = p; pLock.pNext = pBt.pLock; pBt.pLock = pLock; } /* Set the BtLock.eLock variable to the maximum of the current lock ** and the requested lock. This means if a write-lock was already held ** and a read-lock requested, we don't incorrectly downgrade the lock. */ Debug.Assert( WRITE_LOCK>READ_LOCK ); if( eLock>pLock.eLock ){ pLock.eLock = eLock; } return SQLITE_OK; }
/* ** Release all the table locks (locks obtained via calls to ** the setSharedCacheTableLock() procedure) held by Btree object p. ** ** This function assumes that Btree p has an open read or write ** transaction. If it does not, then the BtShared.isPending variable ** may be incorrectly cleared. */ static void clearAllSharedCacheTableLocks(Btree p){ BtShared pBt = p.pBt; BtLock **ppIter = &pBt.pLock; Debug.Assert( sqlite3BtreeHoldsMutex(p) ); Debug.Assert( p.sharable || 0==*ppIter ); Debug.Assert( p.inTrans>0 ); while( ppIter ){ BtLock pLock = ppIter; Debug.Assert( pBt.isExclusive==null || pBt.pWriter==pLock.pBtree ); Debug.Assert( pLock.pBtree.inTrans>=pLock.eLock ); if( pLock.pBtree==p ){ ppIter = pLock.pNext; //Debug.Assert( pLock.iTable!=1 || pLock==&p.lock ); if( pLock.iTable!=1 ){ pLock=null;//sqlite3_free(ref pLock); } }else{ ppIter = &pLock.pNext; } } Debug.Assert( pBt.isPending==null || pBt.pWriter ); if( pBt.pWriter==p ){ pBt.pWriter = 0; pBt.isExclusive = 0; pBt.isPending = 0; }else if( pBt.nTransaction==2 ){ /* This function is called when Btree p is concluding its ** transaction. If there currently exists a writer, and p is not ** that writer, then the number of locks held by connections other ** than the writer must be about to drop to zero. In this case ** set the isPending flag to 0. ** ** If there is not currently a writer, then BtShared.isPending must ** be zero already. So this next line is harmless in that case. */ pBt.isPending = 0; } }
/* ** This function changes all write-locks held by Btree p into read-locks. */ static void downgradeAllSharedCacheTableLocks(Btree p){ BtShared pBt = p.pBt; if( pBt.pWriter==p ){ BtLock pLock; pBt.pWriter = 0; pBt.isExclusive = 0; pBt.isPending = 0; for(pLock=pBt.pLock; pLock; pLock=pLock.pNext){ Debug.Assert( pLock.eLock==READ_LOCK || pLock.pBtree==p ); pLock.eLock = READ_LOCK; } } }
/* ** This function is called before modifying the contents of a table ** to invalidate any incrblob cursors that are open on the ** row or one of the rows being modified. ** ** If argument isClearTable is true, then the entire contents of the ** table is about to be deleted. In this case invalidate all incrblob ** cursors open on any row within the table with root-page pgnoRoot. ** ** Otherwise, if argument isClearTable is false, then the row with ** rowid iRow is being replaced or deleted. In this case invalidate ** only those incrblob cursors open on that specific row. */ static void invalidateIncrblobCursors( Btree pBtree, /* The database file to check */ i64 iRow, /* The rowid that might be changing */ int isClearTable /* True if all rows are being deleted */ ){ BtCursor p; BtShared pBt = pBtree.pBt; Debug.Assert( sqlite3BtreeHoldsMutex(pBtree) ); for(p=pBt.pCursor; p!=null; p=p.pNext){ if( p.isIncrblobHandle && (isClearTable || p.info.nKey==iRow) ){ p.eState = CURSOR_INVALID; } } }
/* ** Return true if the BtShared mutex is held on the btree, or if the ** B-Tree is not marked as sharable. ** ** This routine is used only from within assert() statements. */ int sqlite3BtreeHoldsMutex(Btree *p){ assert( p->sharable==0 || p->locked==0 || p->wantToLock>0 ); assert( p->sharable==0 || p->locked==0 || p->db==p->pBt->db ); assert( p->sharable==0 || p->locked==0 || sqlite3_mutex_held(p->pBt->mutex) ); assert( p->sharable==0 || p->locked==0 || sqlite3_mutex_held(p->db->mutex) ); return (p->sharable==0 || p->locked); }
private int Sweep() { int nDeallocated = 0; long pos; gcDone = true; for (int i = dbFirstUserId, j = committedIndexSize; i < j; i++) { pos = GetGCPos(i); if (pos != 0 && ((int) pos & (dbPageObjectFlag | dbFreeHandleFlag)) == 0) { int bit = (int) (SupportClass.URShift(pos, dbAllocationQuantumBits)); if ((blackBitmap[SupportClass.URShift(bit, 5)] & (1 << (bit & 31))) == 0) { // object is not accessible if (GetPos(i) != pos) { throw new StorageError(StorageError.INVALID_OID); } int offs = (int) pos & (Page.pageSize - 1); Page pg = pool.GetPage(pos - offs); int typeOid = ObjectHeader.GetType(pg.data, offs); if (typeOid != 0) { ClassDescriptor desc = FindClassDescriptor(typeOid); nDeallocated += 1; if (typeof(Btree).IsAssignableFrom(desc.cls)) { Btree btree = new Btree(pg.data, ObjectHeader.Sizeof + offs); pool.Unfix(pg); btree.AssignOid(this, i, false); btree.Deallocate(); } else { int size = ObjectHeader.GetSize(pg.data, offs); pool.Unfix(pg); FreeId(i); objectCache.Remove(i); CloneBitmap(pos, size); } if (listener != null) { listener.DeallocateObject(desc.cls, i); } } } } } greyBitmap = null; blackBitmap = null; allocatedDelta = 0; gcActive = false; if (listener != null) listener.GcCompleted(nDeallocated); return nDeallocated; }
/* ** The following are special cases for mutex enter routines for use ** in single threaded applications that use shared cache. Except for ** these two routines, all mutex operations are no-ops in that case and ** are null #defines in btree.h. ** ** If shared cache is disabled, then all btree mutex routines, including ** the ones below, are no-ops and are null #defines in btree.h. */ void sqlite3BtreeEnter(Btree *p){ p->pBt->db = p->db; }
public virtual Index CreateIndex(Type keyType, bool unique) { lock (this) { if (!opened) throw new StorageError(StorageError.STORAGE_NOT_OPENED); Index index; if (alternativeBtree) index = new AltBtree(keyType, unique); else index = new Btree(keyType, unique); index.AssignOid(this, 0, false); return index; } }
//# define sqlite3BtreeMutexArrayInsert(X,Y) static void sqlite3BtreeMutexArrayInsert( BtreeMutexArray X, Btree Y ) { }
//UPGRADE_TODO: Class 'java.util.HashMap' was converted to 'System.Collections.Hashtable' which has a different behavior. public virtual Hashtable GetMemoryDump() { lock (this) { lock (objectCache) { if (!opened) { throw new StorageError(StorageError.STORAGE_NOT_OPENED); } int bitmapSize = (int) (SupportClass.URShift(header.root[currIndex].size, (dbAllocationQuantumBits + 5))) + 1; bool existsNotMarkedObjects; long pos; int i, j; // mark greyBitmap = new int[bitmapSize]; blackBitmap = new int[bitmapSize]; int rootOid = header.root[currIndex].rootObject; //UPGRADE_TODO: Class 'java.util.HashMap' was converted to 'System.Collections.Hashtable' which has a different behavior. Hashtable map = new Hashtable(); if (rootOid != 0) { MemoryUsage indexUsage = new MemoryUsage(typeof(Index)); MemoryUsage fieldIndexUsage = new MemoryUsage(typeof(FieldIndex)); MemoryUsage classUsage = new MemoryUsage(typeof(Type)); MarkOid(rootOid); do { existsNotMarkedObjects = false; for (i = 0; i < bitmapSize; i++) { if (greyBitmap[i] != 0) { existsNotMarkedObjects = true; for (j = 0; j < 32; j++) { if ((greyBitmap[i] & (1 << j)) != 0) { pos = (((long) i << 5) + j) << dbAllocationQuantumBits; greyBitmap[i] &= ~ (1 << j); blackBitmap[i] |= 1 << j; int offs = (int) pos & (Page.pageSize - 1); Page pg = pool.GetPage(pos - offs); int typeOid = ObjectHeader.GetType(pg.data, offs); int objSize = ObjectHeader.GetSize(pg.data, offs); int alignedSize = (objSize + dbAllocationQuantum - 1) & ~ (dbAllocationQuantum - 1); if (typeOid != 0) { MarkOid(typeOid); ClassDescriptor desc = FindClassDescriptor(typeOid); if (typeof(Btree).IsAssignableFrom(desc.cls)) { Btree btree = new Btree(pg.data, ObjectHeader.Sizeof + offs); btree.AssignOid(this, 0, false); int nPages = btree.MarkTree(); if (typeof(FieldIndex).IsAssignableFrom(desc.cls)) { fieldIndexUsage.nInstances += 1; fieldIndexUsage.totalSize += (long) nPages * Page.pageSize + objSize; fieldIndexUsage.allocatedSize += (long) nPages * Page.pageSize + alignedSize; } else { indexUsage.nInstances += 1; indexUsage.totalSize += (long) nPages * Page.pageSize + objSize; indexUsage.allocatedSize += (long) nPages * Page.pageSize + alignedSize; } } else { //UPGRADE_TODO: Method 'java.util.HashMap.get' was converted to 'System.Collections.Hashtable.Item' which has a different behavior. MemoryUsage usage = (MemoryUsage) map[desc.cls]; if (usage == null) { usage = new MemoryUsage(desc.cls); map[desc.cls] = usage; } usage.nInstances += 1; usage.totalSize += objSize; usage.allocatedSize += alignedSize; if (desc.hasReferences) { MarkObject(pool.Get(pos), ObjectHeader.Sizeof, desc); } } } else { classUsage.nInstances += 1; classUsage.totalSize += objSize; classUsage.allocatedSize += alignedSize; } pool.Unfix(pg); } } } } } while (existsNotMarkedObjects); if (indexUsage.nInstances != 0) { map[typeof(Index)] = indexUsage; } if (fieldIndexUsage.nInstances != 0) { map[typeof(FieldIndex)] = fieldIndexUsage; } if (classUsage.nInstances != 0) { map[typeof(Type)] = classUsage; } MemoryUsage system = new MemoryUsage(typeof(Storage)); system.totalSize += header.root[0].indexSize * 8L; system.totalSize += header.root[1].indexSize * 8L; system.totalSize += (long) (header.root[currIndex].bitmapEnd - dbBitmapId) * Page.pageSize; system.totalSize += Page.pageSize; // root page if (header.root[currIndex].bitmapExtent != 0) system.allocatedSize = GetBitmapUsedSpace(dbBitmapId, dbBitmapId + dbBitmapPages) + GetBitmapUsedSpace(header.root[currIndex].bitmapExtent, header.root[currIndex].bitmapExtent + header.root[currIndex].bitmapEnd - dbBitmapId); else system.allocatedSize = GetBitmapUsedSpace(dbBitmapId, header.root[currIndex].bitmapEnd); system.nInstances = header.root[currIndex].indexSize; map[typeof(Storage)] = system; } return map; } } }
//int sqlite3BtreeSharable(Btree); //void sqlite3BtreeLeave(Btree); //void sqlite3BtreeEnterCursor(BtCursor); //void sqlite3BtreeLeaveCursor(BtCursor); //void sqlite3BtreeLeaveAll(sqlite3); #if !NDEBUG /* These routines are used inside Debug.Assert() statements only. */ int sqlite3BtreeHoldsMutex(Btree);
/* ** Find and return the schema associated with a BTree. Create ** a new one if necessary. */ static Schema sqlite3SchemaGet( sqlite3 db, Btree pBt ) { Schema p; if ( pBt != null ) { p = sqlite3BtreeSchema( pBt, -1, (dxFreeSchema)sqlite3SchemaClear );//Schema.Length, sqlite3SchemaFree); } else { p = new Schema(); // (Schema *)sqlite3DbMallocZero(0, sizeof(Schema)); } if ( p == null ) { //// db.mallocFailed = 1; } else if ( 0 == p.file_format ) { sqlite3HashInit( p.tblHash ); sqlite3HashInit( p.idxHash ); sqlite3HashInit( p.trigHash ); sqlite3HashInit( p.fkeyHash ); p.enc = SQLITE_UTF8; } return p; }
//# define sqlite3BtreeLeave(X) static void sqlite3BtreeLeave( Btree X ) { }
/* A bunch of Debug.Assert() statements to check the transaction state variables ** of handle p (type Btree*) are internally consistent. */ #if DEBUG //#define btreeIntegrity(p) \ // Debug.Assert( p.pBt.inTransaction!=TRANS_NONE || p.pBt.nTransaction==0 ); \ // Debug.Assert( p.pBt.inTransaction>=p.inTrans ); static void btreeIntegrity( Btree p ) { Debug.Assert( p.pBt.inTransaction != TRANS_NONE || p.pBt.nTransaction == 0 ); Debug.Assert( p.pBt.inTransaction >= p.inTrans ); }
/* ** Copy the complete content of pBtFrom into pBtTo. A transaction ** must be active for both files. ** ** The size of file pTo may be reduced by this operation. If anything ** goes wrong, the transaction on pTo is rolled back. If successful, the ** transaction is committed before returning. */ static int sqlite3BtreeCopyFile( Btree pTo, Btree pFrom ) { int rc; sqlite3_backup b; sqlite3BtreeEnter( pTo ); sqlite3BtreeEnter( pFrom ); /* Set up an sqlite3_backup object. sqlite3_backup.pDestDb must be set ** to 0. This is used by the implementations of sqlite3_backup_step() ** and sqlite3_backup_finish() to detect that they are being called ** from this function, not directly by the user. */ b = new sqlite3_backup();// memset( &b, 0, sizeof( b ) ); b.pSrcDb = pFrom.db; b.pSrc = pFrom; b.pDest = pTo; b.iNext = 1; /* 0x7FFFFFFF is the hard limit for the number of pages in a database ** file. By passing this as the number of pages to copy to ** sqlite3_backup_step(), we can guarantee that the copy finishes ** within a single call (unless an error occurs). The Debug.Assert() statement ** checks this assumption - (p.rc) should be set to either SQLITE_DONE ** or an error code. */ sqlite3_backup_step( b, 0x7FFFFFFF ); Debug.Assert( b.rc != SQLITE_OK ); rc = sqlite3_backup_finish( b ); if ( rc == SQLITE_OK ) { pTo.pBt.pageSizeFixed = false; } sqlite3BtreeLeave( pFrom ); sqlite3BtreeLeave( pTo ); return rc; }
//#define invalidateIncrblobCursors(x,y,z) static void invalidateIncrblobCursors( Btree x, i64 y, int z ) { }