/// <summary> /// Process the records sequentially. This method tries /// to lock a record and moves to the next record if /// it fails to get the lock. /// </summary> public void DoWork() { EseInteropTestHelper.ThreadBeginThreadAffinity(); // We must be in a transaction for locking to work. using (var transaction = new Transaction(this.sesid)) { if (Api.TryMoveFirst(this.sesid, this.tableid)) { do { // Getting a lock in ESENT is instantaneous -- if // another thread has the record locked or has // updated this record, this call will fail. There // is no way to wait for the lock to be released. // (because ESENT uses Snapshot Isolation the other // session's lock will always be visible until this // transaction commits). if (Api.TryGetLock(this.sesid, this.tableid, GetLockGrbit.Write)) { // [Do something] EseInteropTestHelper.ThreadSleep(1); Api.JetDelete(this.sesid, this.tableid); this.RecordsProcessed++; } }while (Api.TryMoveNext(this.sesid, this.tableid)); } transaction.Commit(CommitTransactionGrbit.LazyFlush); } EseInteropTestHelper.ThreadEndThreadAffinity(); }
public void CreateAllErrorExceptions() { int i = 0; foreach (JET_err err in Enum.GetValues(typeof(JET_err))) { if (JET_err.Success != err) { EsentErrorException ex = EsentExceptionHelper.JetErrToException(err); Assert.IsNotNull(ex); Assert.AreEqual(err, ex.Error); Assert.IsNotNull(ex.Message); Assert.AreNotEqual(string.Empty, ex.Message); #if MANAGEDESENT_ON_CORECLR #else EsentErrorException deserialized = SerializeDeserialize(ex); Assert.AreEqual(err, deserialized.Error); Assert.AreEqual(ex.Message, deserialized.Message); #endif i++; } } EseInteropTestHelper.ConsoleWriteLine("Created {0} different error exceptions", i); }
public void HowDoIRetrieveAnAutoInc() { JET_SESID sesid = this.testSession; JET_DBID dbid = this.testDbid; JET_TABLEID tableid; JET_COLUMNDEF columndef = new JET_COLUMNDEF(); JET_COLUMNID autoincColumn; // First create the table. There is one autoinc column. Api.JetCreateTable(sesid, dbid, "table", 0, 100, out tableid); columndef.coltyp = JET_coltyp.Long; columndef.grbit = ColumndefGrbit.ColumnAutoincrement; Api.JetAddColumn(sesid, tableid, "data", columndef, null, 0, out autoincColumn); // Once the update is prepared the autoinc column can be retrieved. This // requires the RetrieveCopy option, which gets a value from the record // currently under construction. for (int i = 0; i < 10; i++) { using (var update = new Update(sesid, tableid, JET_prep.Insert)) { int?autoinc = Api.RetrieveColumnAsInt32( sesid, tableid, autoincColumn, RetrieveColumnGrbit.RetrieveCopy); EseInteropTestHelper.ConsoleWriteLine("{0}", autoinc); update.Save(); } } }
public void TestDeleteDirectoryWithRetryWhenDirectoryDoesNotExist() { string directory = EseInteropTestHelper.PathGetRandomFileName(); Assert.IsFalse(EseInteropTestHelper.DirectoryExists(directory)); Cleanup.DeleteDirectoryWithRetry(directory); }
public void TestDeleteFileWithRetryWhenFileDoesNotExist() { string file = EseInteropTestHelper.PathGetRandomFileName(); Assert.IsFalse(EseInteropTestHelper.FileExists(file)); Cleanup.DeleteFileWithRetry(file); }
public void TestJetCompactExceptionHandling() { var ex = new ArgumentNullException(); var test = new DatabaseFileTestHelper(EseInteropTestHelper.PathGetRandomFileName() + "-compactdatabase", true); test.TestCompactDatabaseCallbackExceptionHandling(ex); }
/// <summary> /// Perform an action and retry on I/O failure, with a 1 second /// sleep between retries. /// </summary> /// <param name="action">The action to perform.</param> private static void PerformActionWithRetry(Action action) { for (int attempt = 1; attempt <= MaxAttempts; ++attempt) { try { action(); return; } catch (UnauthorizedAccessException) { if (MaxAttempts == attempt) { throw; } } catch (IOException) { if (MaxAttempts == attempt) { throw; } } EseInteropTestHelper.ThreadSleep(TimeSpan.FromSeconds(1)); } }
public void VerifyJetVersionIsNotZero() { JET_INSTANCE instance; JET_SESID sesid; uint version; Api.JetCreateInstance(out instance, "JetGetVersion"); var parameters = new InstanceParameters(instance); parameters.Recovery = false; parameters.MaxTemporaryTables = 0; parameters.NoInformationEvent = true; Api.JetInit(ref instance); Api.JetBeginSession(instance, out sesid, string.Empty, string.Empty); #if MANAGEDESENT_ON_WSA // Not exposed in MSDK version = 0; #else Api.JetGetVersion(sesid, out version); #endif Api.JetTerm(instance); Assert.AreNotEqual(0, version); EseInteropTestHelper.ConsoleWriteLine("Version = 0x{0:X}", version); }
public void JetGetThreadStatsPerf() { if (!EsentVersion.SupportsVistaFeatures) { return; } // Call the method once to force JIT compilation JET_THREADSTATS threadstats; VistaApi.JetGetThreadStats(out threadstats); #if DEBUG const int N = 1000; #else const int N = 5000000; #endif var stopwatch = Stopwatch.StartNew(); for (int i = 0; i < N; ++i) { VistaApi.JetGetThreadStats(out threadstats); } stopwatch.Stop(); EseInteropTestHelper.ConsoleWriteLine( "Made {0:N0} calls to JetGetThreadStats in {1} ({2:N6} milliseconds/call)", N, stopwatch.Elapsed, (double)stopwatch.ElapsedMilliseconds / N); }
public void LazyCommitWithSmallerDuration() { if (!EsentVersion.SupportsWindows8Features) { return; } Api.JetBeginTransaction(this.sesid); this.InsertRecord(this.tableid, 2); this.InsertRecord(this.tableid, 1); this.InsertRecord(this.tableid, 3); JET_COMMIT_ID commitId1; Windows8Api.JetCommitTransaction2(this.sesid, CommitTransactionGrbit.LazyFlush, new TimeSpan(0, 0, 5), out commitId1); Api.JetBeginTransaction(this.sesid); this.InsertRecord(this.tableid, 4); this.InsertRecord(this.tableid, 5); JET_COMMIT_ID commitId2; Windows8Api.JetCommitTransaction2(this.sesid, CommitTransactionGrbit.LazyFlush, new TimeSpan(0, 0, 2), out commitId2); DateTime commitTime = DateTime.Now; Assert.IsTrue(commitId2 > commitId1); EseInteropTestHelper.ThreadSleep(2500); TimeSpan timeToFlush = this.lastCallbackTime - commitTime; Assert.IsTrue(commitId2 < this.lastCommitIdFlushed); Assert.IsTrue(timeToFlush.TotalMilliseconds < 2500); }
public void VerifyJetSetSessionContextAllowsThreadMigration() { using (var instance = new Instance("JetSetSessionContext")) { SetupHelper.SetLightweightConfiguration(instance); instance.Init(); using (var session = new Session(instance)) { // Without the calls to JetSetSessionContext/JetResetSessionContext // this will generate a session sharing violation. var context = new IntPtr(Any.Int32); var thread = new Thread(() => { EseInteropTestHelper.ThreadBeginThreadAffinity(); Api.JetSetSessionContext(session, context); Api.JetBeginTransaction(session); Api.JetResetSessionContext(session); EseInteropTestHelper.ThreadEndThreadAffinity(); }); thread.Start(); thread.Join(); Api.JetSetSessionContext(session, context); Api.JetCommitTransaction(session, CommitTransactionGrbit.None); Api.JetResetSessionContext(session); } } }
/// <summary> /// Run the test. /// </summary> public void RunTest() { #if !MANAGEDESENT_ON_WSA // The threading model in Windows Store Apps has changed. Int32ColumnValue columnValue = new Int32ColumnValue(); columnValue.Value = 0; Assert.AreEqual(0, columnValue.ValueAsObject); Thread[] threads = new Thread[Environment.ProcessorCount * 2]; for (int i = 0; i < threads.Length; ++i) { threads[i] = new Thread(this.ThreadProc); threads[i].Start(new Random(i)); this.activeThreads++; } GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); Stopwatch stopwatch = Stopwatch.StartNew(); this.startEvent.Set(); this.stopEvent.WaitOne(); stopwatch.Stop(); foreach (Thread t in threads) { t.Join(); } EseInteropTestHelper.ConsoleWriteLine("Performed {0:N0} operations on {1} threads in {2}", N, threads.Length, stopwatch.Elapsed); #endif // !MANAGEDESENT_ON_WSA }
public void TestJetThreadstatsToStringPerf() { var t = new JET_THREADSTATS { cPageReferenced = 10, cPageRead = 5, cPagePreread = 4, cPageDirtied = 3, cPageRedirtied = 2, cLogRecord = 1, cbLogRecord = 0, }; // Call the method once to make sure it is compiled. string ignored = t.ToString(); const int N = 100000; EsentStopwatch s = EsentStopwatch.StartNew(); for (int i = 0; i < N; ++i) { ignored = t.ToString(); } s.Stop(); double ms = Math.Max(1, s.Elapsed.Milliseconds); EseInteropTestHelper.ConsoleWriteLine("{0} calls in {1} ({2} ms/call)", N, s.Elapsed, ms / N); }
/// <summary> /// Compact the database. /// </summary> private void CompactDatabase() { string defraggedDatabase = Path.Combine(this.databaseDirectory, "defragged.edb"); using (var instance = this.CreateInstance()) { instance.Init(); using (var session = new Session(instance)) { // For JetCompact to work the database has to be attached, but not opened Api.JetAttachDatabase(session, this.database, AttachDatabaseGrbit.None); if (this.useStatusCallback) { this.statusCallbackWasCalled = false; Api.JetCompact(session, this.database, defraggedDatabase, this.StatusCallback, null, CompactGrbit.None); Assert.IsTrue( this.statusCallbackWasCalled, "expected the status callback to be called during compact"); } else { Api.JetCompact(session, this.database, defraggedDatabase, null, null, CompactGrbit.None); } } } Assert.IsTrue(EseInteropTestHelper.FileExists(defraggedDatabase)); Cleanup.DeleteFileWithRetry(this.database); File.Move(defraggedDatabase, this.database); }
/// <summary> /// Creates a new random directory in the current working directory. This /// should be used to ensure that each test runs in its own directory. /// </summary> /// <returns>The name of the directory.</returns> public static string CreateRandomDirectory() { string myDir = EseInteropTestHelper.PathGetRandomFileName() + @"\"; EseInteropTestHelper.DirectoryCreateDirectory(myDir); return(myDir); }
/// <summary> /// Verifies no instances are leaked. /// </summary> public static void CheckProcessForInstanceLeaks() { #if !MANAGEDESENT_ON_WSA // Not exposed in MSDK int numInstances; JET_INSTANCE_INFO[] instances; Api.JetGetInstanceInfo(out numInstances, out instances); if (numInstances != 0) { EseInteropTestHelper.ConsoleWriteLine("There are {0} instances remaining! They are:", numInstances); foreach (var instanceInfo in instances) { string databaseName = string.Empty; if (instanceInfo.szDatabaseFileName != null && instanceInfo.szDatabaseFileName.Count > 0) { databaseName = instanceInfo.szDatabaseFileName[0]; } EseInteropTestHelper.ConsoleWriteLine( " szInstanceName={0}, szDatabaseName={1}", instanceInfo.szInstanceName, databaseName); } } Assert.AreEqual(0, numInstances); #endif // !MANAGEDESENT_ON_WSA }
public void TestEnumerateZeroLengthColumn() { Api.JetBeginTransaction(this.sesid); Api.JetPrepareUpdate(this.sesid, this.tableid, JET_prep.Insert); Api.SetColumn(this.sesid, this.tableid, this.columnidDict["binary"], new byte[0]); Api.JetUpdate(this.sesid, this.tableid); Api.JetCommitTransaction(this.sesid, CommitTransactionGrbit.LazyFlush); Api.JetMove(this.sesid, this.tableid, JET_Move.First, MoveGrbit.None); int numValues; JET_ENUMCOLUMN[] values; JET_PFNREALLOC allocator = (context, pv, cb) => IntPtr.Zero == pv?EseInteropTestHelper.MarshalAllocHGlobal(new IntPtr(cb)) : EseInteropTestHelper.MarshalReAllocHGlobal(pv, new IntPtr(cb)); Api.JetEnumerateColumns( this.sesid, this.tableid, 0, null, out numValues, out values, allocator, IntPtr.Zero, 0, EnumerateColumnsGrbit.EnumerateCompressOutput); Assert.AreEqual(1, numValues); Assert.IsNotNull(values); Assert.AreEqual(this.columnidDict["binary"], values[0].columnid); Assert.AreEqual(JET_wrn.ColumnSingleValue, values[0].err); Assert.AreEqual(0, values[0].cbData); allocator(IntPtr.Zero, values[0].pvData, 0); // free the memory }
public void VerifyCallbackWrappersCollectsUnusedWrappers() { DateTime endTime = DateTime.Now + TimeSpan.FromSeconds(19); var callbackWrappers = new CallbackWrappers(); RunFullGarbageCollection(); long memoryAtStart = EseInteropTestHelper.GCGetTotalMemory(true); while (DateTime.Now < endTime) { for (int i = 0; i < 128; ++i) { CreateCallbackWrapper(callbackWrappers); } RunFullGarbageCollection(); callbackWrappers.Collect(); RunFullGarbageCollection(); } RunFullGarbageCollection(); long memoryAtEnd = EseInteropTestHelper.GCGetTotalMemory(true); GC.KeepAlive(callbackWrappers); long memory = memoryAtEnd - memoryAtStart; EseInteropTestHelper.ConsoleWriteLine("{0:N0} bytes used", memory); Assert.IsTrue(memory < 1024 * 1024, "Test used too much memory. JetCallbackWrapper objects weren't collected."); }
public void PrintVersion() { if (EsentVersion.SupportsServer2003Features) { EseInteropTestHelper.ConsoleWriteLine("SupportsServer2003Features"); } if (EsentVersion.SupportsVistaFeatures) { EseInteropTestHelper.ConsoleWriteLine("SupportsVistaFeatures"); } if (EsentVersion.SupportsWindows7Features) { EseInteropTestHelper.ConsoleWriteLine("SupportsWindows7Features"); } if (EsentVersion.SupportsUnicodePaths) { EseInteropTestHelper.ConsoleWriteLine("SupportsUnicodePaths"); } if (EsentVersion.SupportsLargeKeys) { EseInteropTestHelper.ConsoleWriteLine("SupportsLargeKeys"); } }
public void CreateResizeAndTrimDatabase() { if (!EsentVersion.SupportsWindows81Features) { return; } string dir = SetupHelper.CreateRandomDirectory(); JET_INSTANCE instance = SetupHelper.CreateNewInstance(dir); Api.JetSetSystemParameter(instance, JET_SESID.Nil, JET_param.MaxTemporaryTables, 0, null); InstanceParameters instanceParameters = new InstanceParameters(instance); instanceParameters.EnableShrinkDatabase = ShrinkDatabaseGrbit.On; Api.JetInit(ref instance); try { string database = Path.Combine(dir, "CreateAndResizeDatabase.db"); JET_SESID sesid; JET_DBID dbid; Api.JetBeginSession(instance, out sesid, string.Empty, string.Empty); Api.JetSetSystemParameter(instance, JET_SESID.Nil, JET_param.DbExtensionSize, 256, null); Api.JetCreateDatabase(sesid, database, string.Empty, out dbid, CreateDatabaseGrbit.None); Api.JetSetSystemParameter(instance, JET_SESID.Nil, JET_param.DbExtensionSize, 1, null); int databaseSpaceOwned; Api.JetGetDatabaseInfo(sesid, dbid, out databaseSpaceOwned, JET_DbInfo.SpaceOwned); // We have to take into account the reserved pages in the database as per the API to get the actual // space. databaseSpaceOwned += ReservedPages; int actualPages; Windows8Api.JetResizeDatabase(sesid, dbid, databaseSpaceOwned + 100, out actualPages, ResizeDatabaseGrbit.None); EseInteropTestHelper.ConsoleWriteLine("actualPages is {0}.", actualPages); Assert.IsTrue(actualPages >= databaseSpaceOwned + 100, "Database didn't grow enough!"); int actualPagesAfterTrim = 0; Windows8Api.JetResizeDatabase(sesid, dbid, 0, out actualPagesAfterTrim, ResizeDatabaseGrbit.None); EseInteropTestHelper.ConsoleWriteLine("actualPagesAfterTrim is {0}.", actualPagesAfterTrim); Assert.IsTrue(actualPagesAfterTrim < actualPages, "Database didn't shrink!"); int databaseSizeOnDiskInPages; Api.JetGetDatabaseInfo(sesid, dbid, out databaseSizeOnDiskInPages, Windows81DbInfo.FilesizeOnDisk); EseInteropTestHelper.ConsoleWriteLine("databaseSizeOnDiskInPages is {0}.", databaseSizeOnDiskInPages); Assert.AreEqual(actualPagesAfterTrim, databaseSizeOnDiskInPages); } finally { Api.JetTerm(instance); Cleanup.DeleteDirectoryWithRetry(dir); } }
/// <summary> /// Initializes a new instance of the <see cref="PerfTestWorker"/> class. /// </summary> public PerfTestWorker() { EseInteropTestHelper.ThreadBeginThreadAffinity(); this.data = new byte[DictionaryOpenCloseTest.DataSize]; this.persistentBlob = new PersistentBlob(this.data); this.RandomGenerator = new Random(); }
/// <summary> /// Perform and time the given action. /// </summary> /// <param name="name">The name of the action.</param> /// <param name="action">The operation to perform.</param> private static void TimeAction(string name, Action action) { var stopwatch = EsentStopwatch.StartNew(); action(); stopwatch.Stop(); EseInteropTestHelper.ConsoleWriteLine("{0}: {1} ({2})", name, stopwatch.Elapsed, stopwatch.ThreadStats); }
/// <summary> /// Called for the disposer and finalizer. /// </summary> /// <param name="isDisposing">True if called from dispose.</param> protected virtual void Dispose(bool isDisposing) { if (isDisposing) { this.session.Dispose(); } EseInteropTestHelper.ThreadEndThreadAffinity(); }
/// <summary> /// Delete a directory, retrying the operation if the delete fails. /// </summary> /// <param name="directory"> /// The directory to delete. /// </param> public static void DeleteDirectoryWithRetry(string directory) { PerformActionWithRetry( () => { if (EseInteropTestHelper.DirectoryExists(directory)) { EseInteropTestHelper.DirectoryDelete(directory, true); } }); }
public void AlternatePathRecoveryWithJetInit3() { if (!EsentVersion.SupportsUnicodePaths) { return; } var test = new DatabaseFileTestHelper(Path.Combine(this.directory, EseInteropTestHelper.PathGetRandomFileName())); test.TestJetInit3(); }
public void TestJetGetDatabaseInfoWithUnicodePath() { if (!EsentVersion.SupportsUnicodePaths) { return; } var test = new DatabaseFileTestHelper(Path.Combine(this.directory, EseInteropTestHelper.PathGetRandomFileName())); test.TestGetDatabaseInfo(); }
/// <summary> /// Prints a sorted list of the Jet apis in the given type. /// </summary> /// <param name="type">The type to inspect.</param> /// <returns>The number of APIs found in the type.</returns> private static int PrintJetApiNames(Type type) { int numApisFound = 0; foreach (string method in GetJetApiNames(type).OrderBy(x => x).Distinct()) { EseInteropTestHelper.ConsoleWriteLine("\t{0}", method); numApisFound++; } return(numApisFound); }
public void HowDoILockRecords() { JET_SESID sesid = this.testSession; JET_DBID dbid = this.testDbid; // First create the table JET_TABLEID tableid; Api.JetCreateTable(sesid, dbid, "table", 0, 100, out tableid); Api.JetCloseTable(sesid, tableid); Api.JetOpenTable(sesid, dbid, "table", null, 0, OpenTableGrbit.None, out tableid); // Insert a selection of records for (int i = 0; i < 30; i++) { using (var update = new Update(sesid, tableid, JET_prep.Insert)) { update.Save(); } } // Create workers var workers = new Worker[2]; var threads = new Thread[workers.Length]; for (int i = 0; i < workers.Length; ++i) { JET_SESID workerSesid; Api.JetDupSession(sesid, out workerSesid); JET_DBID workerDbid; Api.JetOpenDatabase(workerSesid, TestDatabase, null, out workerDbid, OpenDatabaseGrbit.None); JET_TABLEID workerTableid; Api.JetOpenTable(workerSesid, workerDbid, "table", null, 0, OpenTableGrbit.None, out workerTableid); workers[i] = new Worker(workerSesid, workerTableid); threads[i] = new Thread(workers[i].DoWork); } // Run the workers then wait for them foreach (Thread t in threads) { t.Start(); } foreach (Thread t in threads) { t.Join(); } for (int i = 0; i < workers.Length; ++i) { EseInteropTestHelper.ConsoleWriteLine("Worker {0} processed {1} records", i, workers[i].RecordsProcessed); } }
/// <summary> /// Initializes a new instance of the <see cref="PerfTestWorker"/> class. /// </summary> /// <param name="instance"> /// The instance to use. /// </param> /// <param name="database"> /// Path to the database. The database should already be created. /// </param> public PerfTestWorker(JET_INSTANCE instance, string database) { EseInteropTestHelper.ThreadBeginThreadAffinity(); this.instance = instance; this.database = database; this.session = new Session(this.instance); Api.JetOpenDatabase(this.session, this.database, string.Empty, out this.dbid, OpenDatabaseGrbit.None); this.table = new Table(this.session, this.dbid, SimplePerfTest.TableName, OpenTableGrbit.None); this.columnidKey = Api.GetTableColumnid(this.session, this.table, SimplePerfTest.KeyColumnName); this.columnidData = Api.GetTableColumnid(this.session, this.table, SimplePerfTest.DataColumnName); this.data = new byte[SimplePerfTest.DataSize]; this.dataBuf = new byte[SimplePerfTest.DataSize]; }
public void VerifyAllPublicClassesHaveToString() { Assembly assembly = EseInteropTestHelper.GetAssembly(typeof(Api)); var classes = FindPublicClassesWithoutToString(assembly); int classesWithoutToString = 0; foreach (Type @class in classes) { EseInteropTestHelper.ConsoleWriteLine("{0} does not override Object.ToString", @class); ++classesWithoutToString; } Assert.AreEqual(0, classesWithoutToString, "Some classes do not override Object.ToString()"); }