System.Data.SQLite

Check-in [4a6b21aeef]
Login

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

Overview
Comment:Reform how the connection pool treats its connection handles.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | tkt-996d13cd87
Files: files | file ages | folders
SHA1: 4a6b21aeef89059e58c0b5323e46958f8ce754cd
User & Date: mistachkin 2012-04-28 12:21:57.251
Context
2012-04-29
03:23
Revise handling of CriticalHandle derived classes to make them more thread-safe. check-in: feda13301a user: mistachkin tags: tkt-996d13cd87
2012-04-28
12:21
Reform how the connection pool treats its connection handles. check-in: 4a6b21aeef user: mistachkin tags: tkt-996d13cd87
09:50
First attempt to reproduce the possible issue described in ticket [996d13cd87]. check-in: adad8e2f33 user: mistachkin tags: tkt-996d13cd87
Changes
Unified Diff Ignore Whitespace Patch
Changes to System.Data.SQLite/SQLiteConnectionPool.cs.
69
70
71
72
73
74
75



76
77
78
79
80
81
82
83

84
85
86
87
88
89
90
        // We found a pool for this file, so use its version number
        version = queue.PoolVersion;
        queue.MaxPoolSize = maxPoolSize;

        ResizePool(queue, false);

        // Try and get a pooled connection from the queue



        while (queue.Queue.Count > 0)
        {
          WeakReference cnn = queue.Queue.Dequeue();
          SQLiteConnectionHandle hdl = cnn.Target as SQLiteConnectionHandle;
          if (hdl != null)
          {
            return hdl;
          }

        }
        return null;
      }
    }

    /// <summary>
    /// Clears out all pooled connections and rev's up the default pool version to force all old active objects







>
>
>
|

|

|



>







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
        // We found a pool for this file, so use its version number
        version = queue.PoolVersion;
        queue.MaxPoolSize = maxPoolSize;

        ResizePool(queue, false);

        // Try and get a pooled connection from the queue
        Queue<WeakReference> poolQueue = queue.Queue;
        if (poolQueue == null) return null;

        while (poolQueue.Count > 0)
        {
          WeakReference cnn = poolQueue.Dequeue();
          SQLiteConnectionHandle hdl = cnn.Target as SQLiteConnectionHandle;
          if ((hdl != null) && !hdl.IsClosed)
          {
            return hdl;
          }
          GC.KeepAlive(hdl);
        }
        return null;
      }
    }

    /// <summary>
    /// Clears out all pooled connections and rev's up the default pool version to force all old active objects
100
101
102
103
104
105
106

107
108
109
110
111
112
113
          {
            WeakReference cnn = pair.Value.Queue.Dequeue();
            SQLiteConnectionHandle hdl = cnn.Target as SQLiteConnectionHandle;
            if (hdl != null)
            {
              hdl.Dispose();
            }

          }
          
          // Keep track of the highest revision so we can go one higher when we're finished
          if (_poolVersion <= pair.Value.PoolVersion)
            _poolVersion = pair.Value.PoolVersion + 1;
        }
        // All pools are cleared and we have a new highest version number to force all old version active items to get discarded







>







104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
          {
            WeakReference cnn = pair.Value.Queue.Dequeue();
            SQLiteConnectionHandle hdl = cnn.Target as SQLiteConnectionHandle;
            if (hdl != null)
            {
              hdl.Dispose();
            }
            GC.KeepAlive(hdl);
          }
          
          // Keep track of the highest revision so we can go one higher when we're finished
          if (_poolVersion <= pair.Value.PoolVersion)
            _poolVersion = pair.Value.PoolVersion + 1;
        }
        // All pools are cleared and we have a new highest version number to force all old version active items to get discarded
127
128
129
130
131
132
133




134
135
136
137
138
139
140
141

142
143
144
145
146
147
148
    {
      lock (_connections)
      {
        Pool queue;
        if (_connections.TryGetValue(fileName, out queue) == true)
        {
          queue.PoolVersion++;




          while (queue.Queue.Count > 0)
          {
            WeakReference cnn = queue.Queue.Dequeue();
            SQLiteConnectionHandle hdl = cnn.Target as SQLiteConnectionHandle;
            if (hdl != null)
            {
              hdl.Dispose();
            }

          }
        }
      }
    }

    /// <summary>
    /// Return a connection to the pool for someone else to use.







>
>
>
>
|

|





>







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
    {
      lock (_connections)
      {
        Pool queue;
        if (_connections.TryGetValue(fileName, out queue) == true)
        {
          queue.PoolVersion++;

          Queue<WeakReference> poolQueue = queue.Queue;
          if (poolQueue == null) return;

          while (poolQueue.Count > 0)
          {
            WeakReference cnn = poolQueue.Dequeue();
            SQLiteConnectionHandle hdl = cnn.Target as SQLiteConnectionHandle;
            if (hdl != null)
            {
              hdl.Dispose();
            }
            GC.KeepAlive(hdl);
          }
        }
      }
    }

    /// <summary>
    /// Return a connection to the pool for someone else to use.
158
159
160
161
162
163
164




165
166
167
168
169
170
171
172
      lock (_connections)
      {
        // If the queue doesn't exist in the pool, then it must've been cleared sometime after the connection was created.
        Pool queue;
        if (_connections.TryGetValue(fileName, out queue) == true && version == queue.PoolVersion)
        {
          ResizePool(queue, true);




          queue.Queue.Enqueue(new WeakReference(hdl, false));
          GC.KeepAlive(hdl);
        }
        else
        {
          hdl.Close();
        }
      }







>
>
>
>
|







168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
      lock (_connections)
      {
        // If the queue doesn't exist in the pool, then it must've been cleared sometime after the connection was created.
        Pool queue;
        if (_connections.TryGetValue(fileName, out queue) == true && version == queue.PoolVersion)
        {
          ResizePool(queue, true);

          Queue<WeakReference> poolQueue = queue.Queue;
          if (poolQueue == null) return;

          poolQueue.Enqueue(new WeakReference(hdl, false));
          GC.KeepAlive(hdl);
        }
        else
        {
          hdl.Close();
        }
      }
181
182
183
184
185
186
187



188
189
190
191
192
193
194
195

196
197
198
199
    /// to take one more than it needs from the pool</param>
    private static void ResizePool(Pool queue, bool forAdding)
    {
      int target = queue.MaxPoolSize;

      if (forAdding && target > 0) target--;




      while (queue.Queue.Count > target)
      {
        WeakReference cnn = queue.Queue.Dequeue();
        SQLiteConnectionHandle hdl = cnn.Target as SQLiteConnectionHandle;
        if (hdl != null)
        {
          hdl.Dispose();
        }

      }
    }
  }
}







>
>
>
|

|





>




195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
    /// to take one more than it needs from the pool</param>
    private static void ResizePool(Pool queue, bool forAdding)
    {
      int target = queue.MaxPoolSize;

      if (forAdding && target > 0) target--;

      Queue<WeakReference> poolQueue = queue.Queue;
      if (poolQueue == null) return;

      while (poolQueue.Count > target)
      {
        WeakReference cnn = poolQueue.Dequeue();
        SQLiteConnectionHandle hdl = cnn.Target as SQLiteConnectionHandle;
        if (hdl != null)
        {
          hdl.Dispose();
        }
        GC.KeepAlive(hdl);
      }
    }
  }
}
Changes to System.Data.SQLite/UnsafeNativeMethods.cs.
1381
1382
1383
1384
1385
1386
1387

1388
1389
1390
1391
1392
1393
1394
    }

    protected override bool ReleaseHandle()
    {
      try
      {
        SQLiteBase.CloseConnection(this);


#if DEBUG && !NET_COMPACT_20
        try
        {
          Trace.WriteLine(String.Format(
              "CloseConnection: {0}", handle));
        }







>







1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
    }

    protected override bool ReleaseHandle()
    {
      try
      {
        SQLiteBase.CloseConnection(this);
        SetHandle(IntPtr.Zero);

#if DEBUG && !NET_COMPACT_20
        try
        {
          Trace.WriteLine(String.Format(
              "CloseConnection: {0}", handle));
        }
1464
1465
1466
1467
1468
1469
1470

1471
1472
1473
1474
1475
1476
1477
    }

    protected override bool ReleaseHandle()
    {
      try
      {
        SQLiteBase.FinalizeStatement(this);


#if DEBUG && !NET_COMPACT_20
        try
        {
          Trace.WriteLine(String.Format(
              "FinalizeStatement: {0}", handle));
        }







>







1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
    }

    protected override bool ReleaseHandle()
    {
      try
      {
        SQLiteBase.FinalizeStatement(this);
        SetHandle(IntPtr.Zero);

#if DEBUG && !NET_COMPACT_20
        try
        {
          Trace.WriteLine(String.Format(
              "FinalizeStatement: {0}", handle));
        }
1547
1548
1549
1550
1551
1552
1553

1554
1555
1556
1557
1558
1559
1560
      }

      protected override bool ReleaseHandle()
      {
          try
          {
              SQLiteBase.FinishBackup(this);


#if DEBUG && !NET_COMPACT_20
              try
              {
                  Trace.WriteLine(String.Format(
                      "FinishBackup: {0}", handle));
              }







>







1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
      }

      protected override bool ReleaseHandle()
      {
          try
          {
              SQLiteBase.FinishBackup(this);
              SetHandle(IntPtr.Zero);

#if DEBUG && !NET_COMPACT_20
              try
              {
                  Trace.WriteLine(String.Format(
                      "FinishBackup: {0}", handle));
              }