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.

Reply via email to