System.Data.SQLite
Check-in [7d50138407]
Not logged in

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

Overview
Comment:Attempt to limit the number of times GetSettingValue is called from the SQLiteConnection class. Pursuant to ticket [25d53b48f6].
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 7d50138407b6992b2ff54d13a0e3998eef29207d
User & Date: mistachkin 2016-07-01 22:58:33
Original Comment: Attempt to limit the number of times GetSettingsValue is called from the SQLiteConnection class. Pursuant to ticket [25d53b48f6].
References
2016-07-01
22:59 Ticket [25d53b48f6] Surprsing amount of time spent in UnsafeNativeMethods.GetSettingsValue status still Pending with 4 other changes artifact: 106586f05e user: mistachkin
Context
2016-07-01
23:18
Update version history docs. check-in: b21adfaffa user: mistachkin tags: trunk
22:58
Attempt to limit the number of times GetSettingValue is called from the SQLiteConnection class. Pursuant to ticket [25d53b48f6]. check-in: 7d50138407 user: mistachkin tags: trunk
21:30
Pedantic: update the XML configuration file with the new settings as well, despite the fact that they cannot be effectively set from there. check-in: 8571817993 user: mistachkin tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to System.Data.SQLite/SQLiteConnection.cs.

  1406   1406       private static event SQLiteConnectionEventHandler _handlers;
  1407   1407   
  1408   1408       /// <summary>
  1409   1409       /// The extra connection flags to be used for all opened connections.
  1410   1410       /// </summary>
  1411   1411       private static SQLiteConnectionFlags _sharedFlags;
  1412   1412   
         1413  +    /// <summary>
         1414  +    /// The <see cref="SQLiteConnection" /> instance (for this thread) that
         1415  +    /// had the most recent call to <see cref="SQLiteConnection.Open" />.
         1416  +    /// </summary>
         1417  +#if !PLATFORM_COMPACTFRAMEWORK
         1418  +    [ThreadStatic()]
         1419  +#endif
         1420  +    private static SQLiteConnection _lastConnectionInOpen;
         1421  +
  1413   1422   #if SQLITE_STANDARD && !PLATFORM_COMPACTFRAMEWORK
  1414   1423       /// <summary>
  1415   1424       /// Used to hold the active library version number of SQLite.
  1416   1425       /// </summary>
  1417   1426       private static int _versionNumber;
  1418   1427   #endif
  1419   1428       #endregion
................................................................................
  2023   2032       /// the value of <paramref name="default" /> is stored here.
  2024   2033       /// </param>
  2025   2034       /// <returns>
  2026   2035       /// Non-zero if the cached setting was found; otherwise, zero.
  2027   2036       /// </returns>
  2028   2037       internal bool TryGetCachedSetting(
  2029   2038           string name,     /* in */
  2030         -        string @default, /* in */
         2039  +        object @default, /* in */
  2031   2040           out object value /* out */
  2032   2041           )
  2033   2042       {
  2034   2043           if ((name == null) || (_cachedSettings == null))
  2035   2044           {
  2036   2045               value = @default;
  2037   2046               return false;
................................................................................
  2451   2460       /// within the connection string.
  2452   2461       /// </returns>
  2453   2462       internal static SortedList<string, string> ParseConnectionString(
  2454   2463           string connectionString,
  2455   2464           bool parseViaFramework,
  2456   2465           bool allowNameOnly
  2457   2466           )
         2467  +    {
         2468  +        return ParseConnectionString(
         2469  +            null, connectionString, parseViaFramework, allowNameOnly);
         2470  +    }
         2471  +
         2472  +    ///////////////////////////////////////////////////////////////////////////////////////////////
         2473  +
         2474  +    /// <summary>
         2475  +    /// Parses a connection string into component parts using the custom
         2476  +    /// connection string parser.  An exception may be thrown if the syntax
         2477  +    /// of the connection string is incorrect.
         2478  +    /// </summary>
         2479  +    /// <param name="connection">
         2480  +    /// The connection that will be using the parsed connection string.
         2481  +    /// </param>
         2482  +    /// <param name="connectionString">
         2483  +    /// The connection string to parse.
         2484  +    /// </param>
         2485  +    /// <param name="parseViaFramework">
         2486  +    /// Non-zero to parse the connection string using the algorithm provided
         2487  +    /// by the framework itself.  This is not applicable when running on the
         2488  +    /// .NET Compact Framework.
         2489  +    /// </param>
         2490  +    /// <param name="allowNameOnly">
         2491  +    /// Non-zero if names are allowed without values.
         2492  +    /// </param>
         2493  +    /// <returns>
         2494  +    /// The list of key/value pairs corresponding to the parameters specified
         2495  +    /// within the connection string.
         2496  +    /// </returns>
         2497  +    private static SortedList<string, string> ParseConnectionString(
         2498  +        SQLiteConnection connection,
         2499  +        string connectionString,
         2500  +        bool parseViaFramework,
         2501  +        bool allowNameOnly
         2502  +        )
  2458   2503       {
  2459   2504           return parseViaFramework ?
  2460         -            ParseConnectionStringViaFramework(connectionString, false) :
  2461         -            ParseConnectionString(connectionString, allowNameOnly);
         2505  +            ParseConnectionStringViaFramework(connection, connectionString, false) :
         2506  +            ParseConnectionString(connection, connectionString, allowNameOnly);
  2462   2507       }
  2463   2508   
  2464   2509       ///////////////////////////////////////////////////////////////////////////////////////////////
  2465   2510   
  2466   2511       private void SetupSQLiteBase(SortedList<string, string> opts)
  2467   2512       {
  2468   2513           object enumValue;
................................................................................
  2967   3012         else if (path.StartsWith ("file:", StringComparison.OrdinalIgnoreCase))
  2968   3013               return path.Substring (5);
  2969   3014         else if (path.StartsWith ("/", StringComparison.OrdinalIgnoreCase))
  2970   3015               return path;
  2971   3016         else
  2972   3017               throw new InvalidOperationException ("Invalid connection string: invalid URI");
  2973   3018       }
         3019  +
         3020  +    /// <summary>
         3021  +    /// Determines if the legacy connection string parser should be used.
         3022  +    /// </summary>
         3023  +    /// <param name="connection">
         3024  +    /// The connection that will be using the parsed connection string.
         3025  +    /// </param>
         3026  +    /// <returns>
         3027  +    /// Non-zero if the legacy connection string parser should be used.
         3028  +    /// </returns>
         3029  +    private static bool ShouldUseLegacyConnectionStringParser(
         3030  +        SQLiteConnection connection
         3031  +        )
         3032  +    {
         3033  +        string name = "No_SQLiteConnectionNewParser";
         3034  +        object value; /* NOT USED */
         3035  +
         3036  +        if ((connection != null) &&
         3037  +            connection.TryGetCachedSetting(name, null, out value))
         3038  +        {
         3039  +            return true;
         3040  +        }
         3041  +
         3042  +        if ((connection == null) &&
         3043  +            TryGetLastCachedSetting(name, null, out value))
         3044  +        {
         3045  +            return true;
         3046  +        }
         3047  +
         3048  +        return (UnsafeNativeMethods.GetSettingValue(name, null) != null);
         3049  +    }
         3050  +
         3051  +    /// <summary>
         3052  +    /// Parses a connection string into component parts using the custom
         3053  +    /// connection string parser.  An exception may be thrown if the syntax
         3054  +    /// of the connection string is incorrect.
         3055  +    /// </summary>
         3056  +    /// <param name="connectionString">
         3057  +    /// The connection string to parse.
         3058  +    /// </param>
         3059  +    /// <param name="allowNameOnly">
         3060  +    /// Non-zero if names are allowed without values.
         3061  +    /// </param>
         3062  +    /// <returns>
         3063  +    /// The list of key/value pairs corresponding to the parameters specified
         3064  +    /// within the connection string.
         3065  +    /// </returns>
         3066  +    private static SortedList<string, string> ParseConnectionString(
         3067  +        string connectionString,
         3068  +        bool allowNameOnly
         3069  +        )
         3070  +    {
         3071  +        return ParseConnectionString(null, connectionString, allowNameOnly);
         3072  +    }
  2974   3073   
  2975   3074       /// <summary>
  2976   3075       /// Parses a connection string into component parts using the custom
  2977   3076       /// connection string parser.  An exception may be thrown if the syntax
  2978   3077       /// of the connection string is incorrect.
  2979   3078       /// </summary>
         3079  +    /// <param name="connection">
         3080  +    /// The connection that will be using the parsed connection string.
         3081  +    /// </param>
  2980   3082       /// <param name="connectionString">
  2981   3083       /// The connection string to parse.
  2982   3084       /// </param>
  2983   3085       /// <param name="allowNameOnly">
  2984   3086       /// Non-zero if names are allowed without values.
  2985   3087       /// </param>
  2986   3088       /// <returns>
  2987   3089       /// The list of key/value pairs corresponding to the parameters specified
  2988   3090       /// within the connection string.
  2989   3091       /// </returns>
  2990   3092       private static SortedList<string, string> ParseConnectionString(
         3093  +        SQLiteConnection connection,
  2991   3094           string connectionString,
  2992   3095           bool allowNameOnly
  2993   3096           )
  2994   3097       {
  2995   3098         string s = connectionString;
  2996   3099         int n;
  2997   3100         SortedList<string, string> ls = new SortedList<string, string>(StringComparer.OrdinalIgnoreCase);
  2998   3101   
  2999   3102         // First split into semi-colon delimited values.
  3000   3103         string error = null;
  3001   3104         string[] arParts;
  3002   3105   
  3003         -      if (UnsafeNativeMethods.GetSettingValue("No_SQLiteConnectionNewParser", null) != null)
         3106  +      if (ShouldUseLegacyConnectionStringParser(connection))
  3004   3107             arParts = SQLiteConvert.Split(s, ';');
  3005   3108         else
  3006   3109             arParts = SQLiteConvert.NewSplit(s, ';', true, ref error);
  3007   3110   
  3008   3111         if (arParts == null)
  3009   3112         {
  3010   3113             throw new ArgumentException(HelperMethods.StringFormat(
................................................................................
  3041   3144       /// Parses a connection string using the built-in (i.e. framework provided)
  3042   3145       /// connection string parser class and returns the key/value pairs.  An
  3043   3146       /// exception may be thrown if the connection string is invalid or cannot be
  3044   3147       /// parsed.  When compiled for the .NET Compact Framework, the custom
  3045   3148       /// connection string parser is always used instead because the framework
  3046   3149       /// provided one is unavailable there.
  3047   3150       /// </summary>
         3151  +    /// <param name="connection">
         3152  +    /// The connection that will be using the parsed connection string.
         3153  +    /// </param>
  3048   3154       /// <param name="connectionString">
  3049   3155       /// The connection string to parse.
  3050   3156       /// </param>
  3051   3157       /// <param name="strict">
  3052   3158       /// Non-zero to throw an exception if any connection string values are not of
  3053   3159       /// the <see cref="String" /> type.  This is not applicable when running on
  3054   3160       /// the .NET Compact Framework.
  3055   3161       /// </param>
  3056   3162       /// <returns>The list of key/value pairs.</returns>
  3057   3163       private static SortedList<string, string> ParseConnectionStringViaFramework(
         3164  +        SQLiteConnection connection,
  3058   3165           string connectionString,
  3059   3166           bool strict
  3060   3167           )
  3061   3168       {
  3062   3169   #if !PLATFORM_COMPACTFRAMEWORK
  3063   3170           DbConnectionStringBuilder connectionStringBuilder
  3064   3171               = new DbConnectionStringBuilder();
................................................................................
  3094   3201           return result;
  3095   3202   #else
  3096   3203           //
  3097   3204           // NOTE: On the .NET Compact Framework, always use our custom connection
  3098   3205           //       string parser as the built-in (i.e. framework provided) one is
  3099   3206           //       unavailable.
  3100   3207           //
  3101         -        return ParseConnectionString(connectionString, false);
         3208  +        return ParseConnectionString(connection, connectionString, false);
  3102   3209   #endif
  3103   3210       }
  3104   3211   
  3105   3212   #if !PLATFORM_COMPACTFRAMEWORK
  3106   3213       /// <summary>
  3107   3214       /// Manual distributed transaction enlistment support
  3108   3215       /// </summary>
................................................................................
  3494   3601       /// <summary>
  3495   3602       /// Opens the connection using the parameters found in the <see cref="ConnectionString" />.
  3496   3603       /// </summary>
  3497   3604       public override void Open()
  3498   3605       {
  3499   3606         CheckDisposed();
  3500   3607   
         3608  +      _lastConnectionInOpen = this; /* THREAD-SAFE: per-thread datum. */
         3609  +
  3501   3610         OnChanged(this, new ConnectionEventArgs(
  3502   3611             SQLiteConnectionEventType.Opening, null, null, null, null, null,
  3503   3612             null, null));
  3504   3613   
  3505   3614         if (_connectionState != ConnectionState.Closed)
  3506   3615           throw new InvalidOperationException();
  3507   3616   
  3508   3617         Close();
  3509   3618   
  3510   3619         SortedList<string, string> opts = ParseConnectionString(
  3511         -          _connectionString, _parseViaFramework, false);
         3620  +          this, _connectionString, _parseViaFramework, false);
  3512   3621   
  3513   3622         OnChanged(this, new ConnectionEventArgs(
  3514   3623             SQLiteConnectionEventType.ConnectionString, null, null, null, null,
  3515   3624             null, _connectionString, new object[] { opts }));
  3516   3625   
  3517   3626         object enumValue;
  3518   3627   
................................................................................
  4395   4504               }
  4396   4505               else
  4397   4506               {
  4398   4507                   return null;
  4399   4508               }
  4400   4509           }
  4401   4510       }
         4511  +
         4512  +    /// <summary>
         4513  +    /// Queries and returns the value of the specified setting, using the
         4514  +    /// cached setting names and values for the last connection that used
         4515  +    /// by the <see cref="SQLiteConnection.Open" /> method, when available.
         4516  +    /// </summary>
         4517  +    /// <param name="name">
         4518  +    /// The name of the setting.
         4519  +    /// </param>
         4520  +    /// <param name="default">
         4521  +    /// The value to be returned if the setting has not been set explicitly
         4522  +    /// or cannot be determined.
         4523  +    /// </param>
         4524  +    /// <param name="value">
         4525  +    /// The value of the cached setting is stored here if found; otherwise,
         4526  +    /// the value of <paramref name="default" /> is stored here.
         4527  +    /// </param>
         4528  +    /// <returns>
         4529  +    /// Non-zero if the cached setting was found; otherwise, zero.
         4530  +    /// </returns>
         4531  +    private static bool TryGetLastCachedSetting(
         4532  +        string name,
         4533  +        object @default,
         4534  +        out object value
         4535  +        )
         4536  +    {
         4537  +        if (_lastConnectionInOpen == null)
         4538  +        {
         4539  +            value = @default;
         4540  +            return false;
         4541  +        }
         4542  +
         4543  +        return _lastConnectionInOpen.TryGetCachedSetting(
         4544  +            name, @default, out value);
         4545  +    }
  4402   4546   
  4403   4547       /// <summary>
  4404   4548       /// The default connection flags to be used for all opened connections
  4405   4549       /// when they are not present in the connection string.
  4406   4550       /// </summary>
  4407   4551       public static SQLiteConnectionFlags DefaultFlags
  4408   4552       {
  4409   4553           get
  4410   4554           {
  4411         -            object enumValue;
         4555  +            string name = "DefaultFlags_SQLiteConnection";
         4556  +            object value;
  4412   4557   
  4413         -            enumValue = TryParseEnum(typeof(SQLiteConnectionFlags),
  4414         -                UnsafeNativeMethods.GetSettingValue(
  4415         -                    "DefaultFlags_SQLiteConnection", null), true);
         4558  +            if (!TryGetLastCachedSetting(name, null, out value))
         4559  +                value = UnsafeNativeMethods.GetSettingValue(name, null);
         4560  +
         4561  +            if (value == null)
         4562  +                return FallbackDefaultFlags;
         4563  +
         4564  +            object enumValue = TryParseEnum(
         4565  +                typeof(SQLiteConnectionFlags), value.ToString(), true);
  4416   4566   
  4417   4567               if (enumValue is SQLiteConnectionFlags)
  4418   4568                   return (SQLiteConnectionFlags)enumValue;
  4419   4569   
  4420   4570               return FallbackDefaultFlags;
  4421   4571           }
  4422   4572       }