1.0.12 Infinite loop in DateAxis.refreshTicksHorizontal(...)

A free public discussion forum for the JFreeChart class library.

1.0.12 Infinite loop in DateAxis.refreshTicksHorizontal(...)

Postby skunk » Sat Jan 10, 2009 4:59 pm

While attempting to upgrade to JFreeChart 1.0.12 I came across the following problem with some new code added to refreshTicksHorizontal() in class org.jfree.chart.axis.DateAxis
Code: Select all
1620   
1621            while (tickDate.before(upperDate)) {
1622                // could add a flag to make the following correction optional...
1623                tickDate = correctTickDateForPosition(tickDate, unit,
1624                        this.tickMarkPosition);
1625   
1626                long lowestTickTime = tickDate.getTime();
1627                long distance = unit.addToDate(tickDate, this.timeZone).getTime()
1628                        - lowestTickTime;
1629                for(int minorTick = 1; minorTick < getMinorTickCount();
1630                        minorTick++) {
1631                    long minorTickTime = lowestTickTime - distance
1632                            * minorTick / getMinorTickCount();
1633                    if (minorTickTime > 0 && getRange().contains(minorTickTime)
1634                            && (!isHiddenValue(minorTickTime))) {
1635                        result.add(new DateTick(TickType.MINOR,
1636                                new Date(minorTickTime), "", TextAnchor.TOP_CENTER,
1637                                TextAnchor.CENTER, 0.0));
1638                    }
1639                }
1640   
1641                if (!isHiddenValue(tickDate.getTime())) {
1642                    // work out the value, label and position

At least in my code, the loop starting at line 1621 never completes in the case when a weekdays only segmented timeline is applied and the tickUnit is daily or larger because the tickDate is continually adjusted backwards.

The only way I was able to correct this issue was to move the block of code from lines 1622-1639 that "corrects" the tickDate out of the enclosing loop -- essentially moving line 1621 to line 1640.
skunk
 
Posts: 1087
Joined: Thu Jun 02, 2005 10:14 pm
Location: Brisbane, Australia

Postby david.gilbert » Sun Jan 11, 2009 9:15 pm

Thanks for the report. I'll look at this during the week...the first thing I'd like to do is reproduce this with a JUnit test so that after it is fixed it doesn't get broken again. Anyway, I've opened a bug report at SourceForge:

https://sourceforge.net/tracker2/?func= ... tid=115494
David Gilbert
JFreeChart Project Leader

:idea: Read my blog
:idea: Ask your company to buy the JFreeChart Developer Guide
:idea: Check out other products sold by my company Object Refinery Limited
david.gilbert
JFreeChart Project Leader
 
Posts: 11367
Joined: Fri Mar 14, 2003 10:29 am

1.0.12 Infinite loop in DateAxis.refreshTicksHorizontal(...)

Postby chalky » Sun Feb 22, 2009 6:03 pm

I've also encountered this problem. Here's a couple of things that I've noticed.
  1. When the date range is a year or less, the code never goes into an infinite loop. When the date range is greater than 1 year and a few months, it always goes into an infinite loop. Here's a test that can be added to org.jfree.chart.axis.junit.DateAxisTests to demonstrate this.
    Code: Select all
    public void testBug2499965AxisRange() {

        DateAxis axis = new DateAxis();
        axis.setTimeline(SegmentedTimeline.newMondayThroughFridayTimeline());
        axis.setTickMarkPosition(DateTickMarkPosition.MIDDLE);
        axis.setDateFormatOverride(new SimpleDateFormat("dd MMM yy"));

        Year y2006 = new Year(2006);
        Year y2007 = new Year(2007);

        Date d0 = new Date(y2006.getFirstMillisecond());
        Date d1 = new Date(y2007.getFirstMillisecond());
        Date d2 = new Date(y2007.getLastMillisecond());
           
        BufferedImage image = new BufferedImage(1920, 1200, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = image.createGraphics();
        Rectangle2D area = new Rectangle2D.Double(0.0, 0.0, 1920, 1200);

        // Firstly test that everything's ok when the client specifies the tick unit
        axis.setRange(d0, d1);
           
        // This call to refreshTicks successfully returns
        axis.refreshTicks(g2, new AxisState(), area, RectangleEdge.BOTTOM);
                   
        // This call to refreshTicks goes into an infinite loop       
        axis.setRange(d0, d2);
        System.out.println("About to call refreshTicks() with a 2 year date range");
        axis.refreshTicks(g2, new AxisState(), area, RectangleEdge.BOTTOM);
    }   

  2. When the axis's date range is more than a year, this bug can be suppressed by setting autoTickUnitSelection to false. Again here's the test code.
    Code: Select all
    public void testBug2499965AutoTickUnitSelection() {

        DateAxis axis = new DateAxis();
        axis.setTimeline(SegmentedTimeline.newMondayThroughFridayTimeline());
        axis.setTickMarkPosition(DateTickMarkPosition.MIDDLE);
        axis.setDateFormatOverride(new SimpleDateFormat("dd MMM yy"));

        Year y2006 = new Year(2006);
        Year y2007 = new Year(2007);

        Date d0 = new Date(y2006.getFirstMillisecond());
        Date d2 = new Date(y2007.getLastMillisecond());
           
        BufferedImage image = new BufferedImage(1920, 1200, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = image.createGraphics();
        Rectangle2D area = new Rectangle2D.Double(0.0, 0.0, 1920, 1200);

        // Firstly test that everything's ok when the client specifies the tick unit
        axis.setRange(d0, d2);
        axis.setAutoTickUnitSelection(false);
        axis.setTickUnit(new DateTickUnit(DateTickUnit.MONTH, 1));
           
        // This call to refreshTicks successfully returns
        axis.refreshTicks(g2, new AxisState(), area, RectangleEdge.BOTTOM);
                   
        // This call to refreshTicks goes into an infinite loop       
        axis.setAutoTickUnitSelection(true);
        System.out.println("About to call refreshTicks() with autoTickUnitSelection = true");
        axis.refreshTicks(g2, new AxisState(), area, RectangleEdge.BOTTOM);


Hope this helps
Chris
chalky
 
Posts: 1
Joined: Sun Feb 22, 2009 4:19 pm

Postby skunk » Sun Feb 22, 2009 8:58 pm

Thank you very much for the test case. This should ensure that an appropriate fix can be added soon.
skunk
 
Posts: 1087
Joined: Thu Jun 02, 2005 10:14 pm
Location: Brisbane, Australia

Re: 1.0.12 Infinite loop in DateAxis.refreshTicksHorizontal(...)

Postby david.gilbert » Fri Feb 27, 2009 6:32 pm

I started on a fairly ambitious reworking of the date tick unit mechanism, that I hope will resolve this bug...but I've stalled at the moment. I will get back into this next week. Thanks for the JUnit tests though, they're very useful.

I want to release JFreeChart 1.0.13 in March (actually, I had hoped for February, but it will have to be March now) and this bug is one that has to be fixed before the release goes out.
David Gilbert
JFreeChart Project Leader

:idea: Read my blog
:idea: Ask your company to buy the JFreeChart Developer Guide
:idea: Check out other products sold by my company Object Refinery Limited
david.gilbert
JFreeChart Project Leader
 
Posts: 11367
Joined: Fri Mar 14, 2003 10:29 am

Re: 1.0.12 Infinite loop in DateAxis.refreshTicksHorizontal(...)

Postby shaunkalley » Mon May 18, 2009 7:46 pm

This issue is still present in 1.0.13.
shaunkalley
 
Posts: 2
Joined: Mon May 18, 2009 7:44 pm

Re: 1.0.12 Infinite loop in DateAxis.refreshTicksHorizontal(...)

Postby skunk » Mon May 18, 2009 8:17 pm

Yup
skunk
 
Posts: 1087
Joined: Thu Jun 02, 2005 10:14 pm
Location: Brisbane, Australia

Re: 1.0.12 Infinite loop in DateAxis.refreshTicksHorizontal(...)

Postby david.gilbert » Fri May 22, 2009 8:28 am

Sorry for this one. I was aware that I hadn't fixed it as promised, but a paying customer needed an "official" JFreeChart release for another bug fix, so I went ahead and made the 1.0.13 release anyway. The fix I was working on involves some bigger changes to the date tick unit mechanism that will fix some other bugs too.
David Gilbert
JFreeChart Project Leader

:idea: Read my blog
:idea: Ask your company to buy the JFreeChart Developer Guide
:idea: Check out other products sold by my company Object Refinery Limited
david.gilbert
JFreeChart Project Leader
 
Posts: 11367
Joined: Fri Mar 14, 2003 10:29 am

Re: 1.0.12 Infinite loop in DateAxis.refreshTicksHorizontal(...)

Postby dude » Mon May 25, 2009 10:31 am

Are these bigger changes already available in subversion? I'd like to try them out as I'm getting bitten by this bug. I don't need an "official" release, but as a paying customer I'd like to have access to a better solution than the workarounds described earlier in this post.
dude
 
Posts: 1
Joined: Mon May 25, 2009 10:05 am

Re: 1.0.12 Infinite loop in DateAxis.refreshTicksHorizontal(...)

Postby ssingh » Mon Sep 07, 2009 6:12 pm

Hi,

I am facing the same problem, I am using the current version 1.0.13
The chart hungs up for dataset around one year or more, but works fine for lesser data.

Please let me know if there is a solution in place already for this.

Also, I used this workaround " dateAxis.setAutoTickUnitSelection(false); " , but it was showing grid lines for each data entry.
I used , dateAxis.setTickUnit(new DateTickUnit(DateTickUnitType.MONTH, 1)); , but it doesnt show tick labels for months for which weekend falls on the 1st of the Month.

Please help with the workaround , if the solution is not in place already.

Code: Select all

final CombinedDomainXYPlot plot = new CombinedDomainXYPlot(dateAxis);
      dateAxis.setTimeline(SegmentedTimeline.newMondayThroughFridayTimeline());
      dateAxis.setAutoTickUnitSelection(false);
      dateAxis.setTickUnit(new DateTickUnit(DateTickUnitType.MONTH, 1));
   

Thanks
--
ssingh
 
Posts: 2
Joined: Sun Sep 06, 2009 1:42 pm

Re: 1.0.12 Infinite loop in DateAxis.refreshTicksHorizontal(...)

Postby OlivierPisano » Thu Nov 05, 2009 9:42 am

Hi, I am currently facing this problem with version 1.0.13 too.
I tried to switch back to 1.0.11 but it didn't help much. Does somebody know about the version this bug first occurred ?

Mr Gilbert, is it worth spending time trying to figure how to circumvent the bug or is a release including a fix for it to be expected soon ?

Regards,

Olivier.
OlivierPisano
 
Posts: 1
Joined: Thu Nov 05, 2009 9:23 am

Re: 1.0.12 Infinite loop in DateAxis.refreshTicksHorizontal(...)

Postby davesnowdon » Tue Oct 19, 2010 12:58 pm

I've also just encountered the bug. Any news on a fix?

Dave, this is the first time I've posted to the forums so I'd like take the opportunity to thank you for all your work on JFreeChart. I bought the developer guide a couple of months ago but am only now finding the time to really get started with JFreeChart.

cheers

Dave
davesnowdon
 
Posts: 9
Joined: Tue Jul 06, 2010 7:10 pm

Re: 1.0.12 Infinite loop in DateAxis.refreshTicksHorizontal(...)

Postby sw3170 » Tue Dec 21, 2010 4:38 pm

I'm having this problem too. ....err....
However unlike some mentioned above, I'm running into this problem with date range of only 6 months. Here's where my problem is

In skunk's original posted code, line 1623
tickDate = correctTickDateForPosition(tickDate, unit,
this.tickMarkPosition);

It keeps changing tickDate back to its old value, hence creates an endless loop.
sw3170
 
Posts: 3
Joined: Tue Dec 21, 2010 3:40 pm

Re: 1.0.12 Infinite loop in DateAxis.refreshTicksHorizontal(...)

Postby davesnowdon » Wed Mar 23, 2011 12:52 pm

sw3170 wrote:I'm having this problem too. ....err....
However unlike some mentioned above, I'm running into this problem with date range of only 6 months. Here's where my problem is

In skunk's original posted code, line 1623
tickDate = correctTickDateForPosition(tickDate, unit,
this.tickMarkPosition);

It keeps changing tickDate back to its old value, hence creates an endless loop.


The fix I posted in this thread appears to solve this problem too:
viewtopic.php?f=3&t=38026

Dave
davesnowdon
 
Posts: 9
Joined: Tue Jul 06, 2010 7:10 pm

Re: 1.0.12 Infinite loop in DateAxis.refreshTicksHorizontal(

Postby avarvit » Mon May 21, 2012 3:21 pm

I just run into the same bug in 1.0.13. It seems to have stayed unresolved in 1.0.14 (have not debugged, but my server still hangs). I have debugged 1.0.13 and came up with the following information and bugfix.

The bug shows up when using a segmented timeline or a timeline with exceptions. It may show up in other cases as well, but I have not been able to reproduce it without a segmented timeline.

In my case, the bug is triggered because, when the TickUnit, instead of DAY, is MONTH or YEAR, correctTickDateForPosition() is called and it may return a prior day to that of tickDate (its argument). Then further down, isHiddenValue() is checked. In the (rare) case that isHiddenValue returns true, the code jumps to line ~1817 (it's my patched source, so it may differ a bit from the official 1.0.13), where rollDate() is called. Now check this. April 1st was on a Sunday. It just so happens that rollDate() returns April 2. Then correctTickDateForPosition() resets this to April 1st. Then isHiddenValue() returns false for that, hence rollDate() is called again. And so forth, ad infinitum.

Here how the above example works:

Code: Select all
    protected List refreshTicksHorizontal(Graphics2D g2,
                Rectangle2D dataArea, RectangleEdge edge) {
        ...
        while (tickDate.before(upperDate)) {
            // could add a flag to make the following correction optional...
            tickDate = correctTickDateForPosition(tickDate, unit,
                    this.tickMarkPosition);            // <---------- this returns April 1st 2012
            ...
            if (!isHiddenValue(tickDate.getTime())) {    // <----- isHiddenValue(April 1st) is on a Sunday, hence we get true
            ... (code that never gets executed
            }
            else { // control jumps here
                tickDate = unit.rollDate(tickDate, this.timeZone); // <------------ this returns April 2nd again
                continue; // this jumps over, completing the infinite loop between April 1st and 2nd!
            }

I have been able to remedy the situation by means of this patch (the lines after //avarvit are mine) in correctTickDateForPosition:
Code: Select all
            case (DateTickUnit.MONTH) :
                result = calculateDateForPosition(new Month(time,
                        this.timeZone, this.locale), position);
               // avarvit
               if (result.getTime() < time.getTime()) result = time;
                break;
            case(DateTickUnit.YEAR) :
                result = calculateDateForPosition(new Year(time,
                        this.timeZone, this.locale), position);
               // avarvit
               if (result.getTime() < time.getTime()) result = time;
                break;

Perhaps this is not the most correct of all possible fixes (e.g., one might need to test for isHiddenValue() inside correctTickDateForPosition()), however I think it will offer some insight. After the fix, my chart displays a tick for April 2nd instead of April 1st and no infinite loop occurs. I hope this helps!
avarvit
 
Posts: 3
Joined: Mon May 21, 2012 3:07 pm

Next

Return to JFreeChart - General

Who is online

Users browsing this forum: Bing [Bot], Google [Bot], Yahoo [Bot] and 17 guests