System.Data.SQLite

Check-in [8549eb3248]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add testing for the custom connection pool functionality.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | customPool
Files: files | file ages | folders
SHA1: 8549eb32489d051386173cdc2f9d2079c3ec1d52
User & Date: mistachkin 2013-02-16 02:17:09.846
Context
2013-02-18
21:31
Merge custom connection pool support to trunk. Pursuant to [393d954be0]. check-in: 90142c95cc user: mistachkin tags: trunk
2013-02-16
02:17
Add testing for the custom connection pool functionality. Closed-Leaf check-in: 8549eb3248 user: mistachkin tags: customPool
00:23
Add custom connection pool changes to the version history docs. Pursuant to [393d954be0]. check-in: abc8fb3a6f user: mistachkin tags: customPool
Changes
Unified Diff Ignore Whitespace Patch
Changes to System.Data.SQLite/SQLiteConnectionPool.cs.
1
2
3
4
5
6
7
8
9
10
11





12


















































































































































































































































13
14
15
16
17
18
19
/********************************************************
 * ADO.NET 2.0 Data Provider for SQLite Version 3.X
 * Written by Robert Simpson (robert@blackcastlesoft.com)
 * 
 * Released to the public domain, use at your own risk!
 ********************************************************/

namespace System.Data.SQLite
{
    using System;
    using System.Collections.Generic;





    using System.Threading;



















































































































































































































































    ///////////////////////////////////////////////////////////////////////////

    #region Public Connection Pool Interface
    /// <summary>
    /// This interface represents a custom connection pool implementation
    /// usable by System.Data.SQLite.











>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
/********************************************************
 * ADO.NET 2.0 Data Provider for SQLite Version 3.X
 * Written by Robert Simpson (robert@blackcastlesoft.com)
 * 
 * Released to the public domain, use at your own risk!
 ********************************************************/

namespace System.Data.SQLite
{
    using System;
    using System.Collections.Generic;

#if !PLATFORM_COMPACTFRAMEWORK && DEBUG
    using System.Text;
#endif

    using System.Threading;

    ///////////////////////////////////////////////////////////////////////////

    #region Null Connection Pool Class
#if !PLATFORM_COMPACTFRAMEWORK && DEBUG
    /// <summary>
    /// This class implements a connection pool where all methods of the
    /// <see cref="ISQLiteConnectionPool" /> interface are NOPs.  This class
    /// is used for testing purposes only.
    /// </summary>
    internal sealed class NullConnectionPool : ISQLiteConnectionPool
    {
        #region Private Data
        /// <summary>
        /// This field keeps track of all method calls made into the
        /// <see cref="ISQLiteConnectionPool" /> interface methods of this
        /// class.
        /// </summary>
        private StringBuilder log;

        ///////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Non-zero to dispose of database connection handles received via the
        /// <see cref="Add" /> method.
        /// </summary>
        private bool dispose;
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region Private Constructors
        /// <summary>
        /// Constructs a connection pool object where all methods of the
        /// <see cref="ISQLiteConnectionPool" /> interface are NOPs.  This
        /// class is used for testing purposes only.
        /// </summary>
        private NullConnectionPool()
        {
            log = new StringBuilder();
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region Public Constructors
        /// <summary>
        /// Constructs a connection pool object where all methods of the
        /// <see cref="ISQLiteConnectionPool" /> interface are NOPs.  This
        /// class is used for testing purposes only.
        /// </summary>
        /// <param name="dispose">
        /// Non-zero to dispose of database connection handles received via the
        /// <see cref="Add" /> method.
        /// </param>
        public NullConnectionPool(
            bool dispose
            )
            : this()
        {
            this.dispose = dispose;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region ISQLiteConnectionPool Members
        /// <summary>
        /// Counts the number of pool entries matching the specified file name.
        /// </summary>
        /// <param name="fileName">
        /// The file name to match or null to match all files.
        /// </param>
        /// <param name="counts">
        /// The pool entry counts for each matching file.
        /// </param>
        /// <param name="openCount">
        /// The total number of connections successfully opened from any pool.
        /// </param>
        /// <param name="closeCount">
        /// The total number of connections successfully closed from any pool.
        /// </param>
        /// <param name="totalCount">
        /// The total number of pool entries for all matching files.
        /// </param>
        public void GetCounts(
            string fileName,
            ref Dictionary<string, int> counts,
            ref int openCount,
            ref int closeCount,
            ref int totalCount
            )
        {
            if (log != null)
            {
                log.AppendFormat(
                    "GetCounts(\"{0}\", {1}, {2}, {3}, {4}){5}", fileName,
                    counts, openCount, closeCount, totalCount,
                    Environment.NewLine);
            }
        }

        ///////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Disposes of all pooled connections associated with the specified
        /// database file name.
        /// </summary>
        /// <param name="fileName">
        /// The database file name.
        /// </param>
        public void ClearPool(
            string fileName
            )
        {
            if (log != null)
            {
                log.AppendFormat(
                    "ClearPool(\"{0}\"){1}", fileName, Environment.NewLine);
            }
        }

        ///////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Disposes of all pooled connections.
        /// </summary>
        public void ClearAllPools()
        {
            if (log != null)
            {
                log.AppendFormat(
                    "ClearAllPools(){0}", Environment.NewLine);
            }
        }

        ///////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Adds a connection to the pool of those associated with the
        /// specified database file name.
        /// </summary>
        /// <param name="fileName">
        /// The database file name.
        /// </param>
        /// <param name="handle">
        /// The database connection handle.
        /// </param>
        /// <param name="version">
        /// The connection pool version at the point the database connection
        /// handle was received from the connection pool.  This is also the
        /// connection pool version that the database connection handle was
        /// created under.
        /// </param>
        public void Add(
            string fileName,
            object handle,
            int version
            )
        {
            if (log != null)
            {
                log.AppendFormat(
                    "Add(\"{0}\", {1}, {2}){3}", fileName, handle, version,
                    Environment.NewLine);
            }

            //
            // NOTE: If configured to do so, dispose of the received connection
            //       handle now.
            //
            if (dispose)
            {
                IDisposable disposable = handle as IDisposable;

                if (disposable != null)
                    disposable.Dispose();
            }
        }

        ///////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Removes a connection from the pool of those associated with the
        /// specified database file name with the intent of using it to
        /// interact with the database.
        /// </summary>
        /// <param name="fileName">
        /// The database file name.
        /// </param>
        /// <param name="maxPoolSize">
        /// The new maximum size of the connection pool for the specified
        /// database file name.
        /// </param>
        /// <param name="version">
        /// The connection pool version associated with the returned database
        /// connection handle, if any.
        /// </param>
        /// <returns>
        /// The database connection handle associated with the specified
        /// database file name or null if it cannot be obtained.
        /// </returns>
        public object Remove(
            string fileName,
            int maxPoolSize,
            out int version
            )
        {
            version = 0;

            if (log != null)
            {
                log.AppendFormat(
                    "Remove(\"{0}\", {1}, {2}){3}", fileName, maxPoolSize,
                    version, Environment.NewLine);
            }

            return null;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region System.Object Overrides
        /// <summary>
        /// Overrides the default <see cref="System.Object.ToString" /> method
        /// to provide a log of all methods called on the
        /// <see cref="ISQLiteConnectionPool" /> interface.
        /// </summary>
        /// <returns>
        /// A string containing a log of all method calls into the
        /// <see cref="ISQLiteConnectionPool" /> interface, along with their
        /// parameters, delimited by <see cref="Environment.NewLine" />.
        /// </returns>
        public override string ToString()
        {
            return (log != null) ? log.ToString() : String.Empty;
        }
        #endregion
    }
#endif
    #endregion

    ///////////////////////////////////////////////////////////////////////////

    #region Public Connection Pool Interface
    /// <summary>
    /// This interface represents a custom connection pool implementation
    /// usable by System.Data.SQLite.
95
96
97
98
99
100
101

102
103
104
105

106
107
108
109
110
111
112
        /// </returns>
        object Remove(string fileName, int maxPoolSize, out int version);
    }
    #endregion

    ///////////////////////////////////////////////////////////////////////////


    /// <summary>
    /// This default method implementations in this class should not be used by
    /// applications that make use of COM (either directly or indirectly) due to
    /// possible deadlocks that can occur during finalization of some COM objects.

    /// </summary>
    internal static class SQLiteConnectionPool
    {
        #region Private Pool Class
        /// <summary>
        /// Keeps track of connections made on a specified file.  The PoolVersion
        /// dictates whether old objects get returned to the pool or discarded







>


|
|
>







342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
        /// </returns>
        object Remove(string fileName, int maxPoolSize, out int version);
    }
    #endregion

    ///////////////////////////////////////////////////////////////////////////

    #region Connection Pool Subsystem & Default Implementation
    /// <summary>
    /// This default method implementations in this class should not be used by
    /// applications that make use of COM (either directly or indirectly) due
    /// to possible deadlocks that can occur during finalization of some COM
    /// objects.
    /// </summary>
    internal static class SQLiteConnectionPool
    {
        #region Private Pool Class
        /// <summary>
        /// Keeps track of connections made on a specified file.  The PoolVersion
        /// dictates whether old objects get returned to the pool or discarded
771
772
773
774
775
776
777

778
                    handle.Dispose();

                GC.KeepAlive(handle);
            }
        }
        #endregion
    }

}







>

1020
1021
1022
1023
1024
1025
1026
1027
1028
                    handle.Dispose();

                GC.KeepAlive(handle);
            }
        }
        #endregion
    }
    #endregion
}
Changes to Tests/common.eagle.
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
        # NOTE: Check the current build configuration.  This should normally
        #       be either "Debug" or "Release".
        #
        tputs $::test_channel \
            "---- checking for System.Data.SQLite build configuration... "

        set configuration [getBuildConfiguration]
        addConstraint [appendArgs buildConfiguration $configuration]
        tputs $::test_channel [appendArgs \" $configuration \"\n]

        #
        # NOTE: Try to setup an interrupt callback using the script debugger
        #       that will cancel all SQL queries in progress for all database
        #       connections known to this interpreter.
        #







|







1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
        # NOTE: Check the current build configuration.  This should normally
        #       be either "Debug" or "Release".
        #
        tputs $::test_channel \
            "---- checking for System.Data.SQLite build configuration... "

        set configuration [getBuildConfiguration]
        addConstraint [appendArgs buildConfiguration. $configuration]
        tputs $::test_channel [appendArgs \" $configuration \"\n]

        #
        # NOTE: Try to setup an interrupt callback using the script debugger
        #       that will cancel all SQL queries in progress for all database
        #       connections known to this interpreter.
        #
Added Tests/tkt-393d954be0.eagle.












































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
###############################################################################
#
# tkt-393d954be0.eagle --
#
# Written by Joe Mistachkin.
# Released to the public domain, use at your own risk!
#
###############################################################################

package require Eagle
package require Eagle.Library
package require Eagle.Test

runTestPrologue

###############################################################################

package require System.Data.SQLite.Test
runSQLiteTestPrologue

###############################################################################

runTest {test tkt-393d954be0-1.1 {custom connection pool} -body {
  set nullPool [object create -flags +NonPublic -alias \
      System.Data.SQLite.NullConnectionPool true]

  object invoke System.Data.SQLite.SQLiteConnection ConnectionPool $nullPool

  setupDb [set fileName tkt-393d954be0-1.1.db] "" "" "" "" "Pooling=True;"

  set exists(0) [file exists [file join [getDatabaseDirectory] [file tail \
      $fileName]]]

  cleanupDb $fileName

  set exists(1) [file exists [file join [getDatabaseDirectory] [file tail \
      $fileName]]]

  set counts null; set openCount 0; set closeCount 0; set totalCount 0
  object invoke -flags +NonPublic System.Data.SQLite.SQLiteConnectionPool \
      GetCounts $fileName counts openCount closeCount totalCount

  object invoke -flags +NonPublic System.Data.SQLite.SQLiteConnectionPool \
      ClearPool $fileName

  object invoke -flags +NonPublic System.Data.SQLite.SQLiteConnectionPool \
      ClearAllPools

  list $exists(0) $exists(1) $counts $openCount $closeCount $totalCount \
      [object invoke $nullPool ToString]
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain db fileName exists counts openCount closeCount totalCount \
      nullPool
} -constraints {eagle monoBug28 buildConfiguration.Debug command.sql\
compile.DATA SQLite System.Data.SQLite} -match regexp -result [string map \
[list \n \r\n] {^True False \{\} 0 0 0\
\{Remove\(".*?\\tkt-393d954be0-1\.1\.db",\
100, 0\)
Add\(".*?\\tkt-393d954be0-1\.1\.db", -?\d+, 0\)
GetCounts\("tkt-393d954be0-1\.1\.db", , 0, 0, 0\)
ClearPool\("tkt-393d954be0-1\.1\.db"\)
ClearAllPools\(\)
\}$}]}

###############################################################################

runSQLiteTestEpilogue
runTestEpilogue