flushInterval ist calculated wrong ---------------------------------- Key: IBATISNET-285 URL: https://issues.apache.org/jira/browse/IBATISNET-285 Project: iBatis for .NET Issue Type: Bug Components: DataMapper Affects Versions: DataMapper 1.6.1 Reporter: Stefan Hoehn
We noticed that if the flushInterval like in <cacheModels> <cacheModel id="NavigationCache" implementation="MEMORY" readOnly="false" serialize="true"> <!-- User bekommen Kopien aus dem Cache --> <flushInterval minutes="1"/> <property name="Type" value="STRONG"/> </cacheModel> </cacheModels> is provided it results in a completely wrong number. There are two bugs that lead to a wrong result. The first one is very minor because it decreases the given interval time by about ten milliseconds. The second one is more severe: It results in a somewhat twice the time of the cache interval given in the configuration. Bug #1: The negative default value is being added in FlushInterval.cs you find the following code: private long _interval = CacheModel.NO_FLUSH_INTERVAL; // equals -99999 //................ public void Initialize() { if (_milliseconds != 0) { _interval += (_milliseconds * TimeSpan.TicksPerMillisecond) ; } if (_seconds != 0) { _interval += (_seconds * TimeSpan.TicksPerSecond) ; } if (_minutes != 0) { _interval += (_minutes * TimeSpan.TicksPerMinute) ; } if (_hours != 0) { _interval += (_hours * TimeSpan.TicksPerHour) ; } if (_interval == 0) { _interval = CacheModel.NO_FLUSH_INTERVAL; } } The result in our case is -99999+600000000 = 599900001. Granted that the effect is only about 10 Milliseconds but still, it is wrong :-) Bug #2: FlushInterval.initialize() is called twice during initialization If you follow the Deserialization of the DomSqlMapBuilder in ConfigureSQLMap() you will find the following code,which calls CacheModelDeSerializer.Deserialize(): #region Load CacheModels if (_configScope.IsCacheModelsEnabled) { CacheModel cacheModel; foreach (XmlNode xmlNode in _configScope.SqlMapDocument.SelectNodes( ApplyMappingNamespacePrefix(XML_CACHE_MODEL), _configScope.XmlNamespaceManager)) { cacheModel = CacheModelDeSerializer.Deserialize(xmlNode, _configScope); cacheModel.Id = _configScope.ApplyNamespace(cacheModel.Id); // Attach ExecuteEventHandler foreach(XmlNode flushOn in xmlNode.SelectNodes( ApplyMappingNamespacePrefix(XML_FLUSH_ON_EXECUTE), _configScope.XmlNamespaceManager )) { string statementName = flushOn.Attributes["statement"].Value; if (_configScope.UseStatementNamespaces) { statementName = _configScope.ApplyNamespace(statementName); } // delay registering statements to cache model until all sqlMap files have been processed IList statementNames = (IList)_configScope.CacheModelFlushOnExecuteStatements[cacheModel.Id]; if (statementNames == null) { statementNames = new ArrayList(); } statementNames.Add(statementName); _configScope.CacheModelFlushOnExecuteStatements[cacheModel.Id] = statementNames; } // Get Properties foreach(XmlNode propertie in xmlNode.SelectNodes( ApplyMappingNamespacePrefix(XML_PROPERTY), _configScope.XmlNamespaceManager)) { string name = propertie.Attributes["name"].Value; string value = propertie.Attributes["value"].Value; cacheModel.AddProperty(name, value); } cacheModel.Initialize(); _configScope.SqlMapper.AddCache( cacheModel ); } } The issue is that CacheModelDeSerializer.Deserialize(xmlNode, _configScope); has the following implementation int count = node.ChildNodes.Count; for(int i=0;i<count;i++) { if (node.ChildNodes[i].LocalName=="flushInterval") { FlushInterval flush = new FlushInterval(); NameValueCollection props = NodeUtils.ParseAttributes(node.ChildNodes[i], configScope.Properties); flush.Hours = NodeUtils.GetIntAttribute(props, "hours", 0); flush.Milliseconds = NodeUtils.GetIntAttribute(props, "milliseconds", 0); flush.Minutes = NodeUtils.GetIntAttribute(props, "minutes", 0); flush.Seconds = NodeUtils.GetIntAttribute(props, "seconds", 0); flush.Initialize(); model.FlushInterval = flush; } } and therefore calls flush.Initialize() as soon as it find an property "flushInterval". So far so good as this results in getting the above number: 599900001 However, back again in ConfigureSQLMap further down it calls cacheModel.Initialize(); which in turn calls _flushInterval.Initialize(); again adding another 600000000 resulting in 1199900001, almost twice of what we wanted. The initialization-Method must no be called twice. -- This message is automatically generated by JIRA. - You can reply to this email to add a comment to the issue online.