Bug 92238 - [Viewers] Exception thrown in Virtual Table Sort using LazySortedCollection
Summary: [Viewers] Exception thrown in Virtual Table Sort using LazySortedCollection
Status: CLOSED WONTFIX
Alias: None
Product: Platform
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 3.1   Edit
Hardware: PC Windows XP
: P3 major with 6 votes (vote)
Target Milestone: ---   Edit
Assignee: Platform UI Triaged CLA
QA Contact:
URL:
Whiteboard: stalebug
Keywords: helpwanted
Depends on:
Blocks:
 
Reported: 2005-04-21 11:17 EDT by Chad Gustafson CLA
Modified: 2019-11-16 10:43 EST (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Chad Gustafson CLA 2005-04-21 11:17:13 EDT
The LazySortedCollection appears to be getting into a recursive infinite loop 
when the data being sorted is not distinct. For example I wrote a test case 
that sorts 30,000 dates. When all the dates are unique the sort works fine. 
When all of the dates are one of three values, today, yesterday, or tomorrow 
then the background sort dies after 30 million comparisons. The following line 
gets printed to the console repeatedly.

at org.eclipse.jface.viewers.deferred.LazySortedCollection.getChildren
(LazySortedCollection.java:1450)

I ran this this test on a windows XP box running M5 Version: 3.1.0
Build id: I20050219-1500. I also reran the test on M6 Version: 3.1.0


Here is the source code for the test:

 

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.deferred.AbstractConcurrentModel;
import org.eclipse.jface.viewers.deferred.DeferredContentProvider;
import org.eclipse.jface.viewers.deferred.IConcurrentModelListener;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;

/**
 * 
 * @author cgustafson
 *
 */

public class TestVirtualTable {

            

            static int num = 0;

            

            public TestVirtualTable(Composite parent){

                        createContents(parent);

            }

 

            private void createContents(Composite parent){

                        parent.setLayout(new GridLayout());

                        

                        Table table = new Table(parent,SWT.VIRTUAL | 
SWT.V_SCROLL);

                        table.setHeaderVisible(true);

                        table.setLinesVisible(true);

                        

                        GridData gd = new GridData();

                        gd.grabExcessVerticalSpace = true;

                        gd.verticalAlignment = SWT.FILL;

                        gd.grabExcessHorizontalSpace = true;

                        gd.horizontalAlignment = SWT.FILL;

                        gd.heightHint = 500;

                        table.setLayoutData(gd);

                        

                        TableColumn column = new TableColumn(table, SWT.LEFT);

column.setText("Date");

column.setWidth(50);

                        

                        TableViewer tableViewer = new TableViewer(table);

            tableViewer.setColumnProperties(new
String[]{"Date"});

            tableViewer.setContentProvider(new
TestContentProvider(new TestComparator(true)));

            tableViewer.setLabelProvider(new TestLabelProvider());

        

                        int size = 30000;

                        Date data[] = new Date[size];

                        

                        Calendar cal =
Calendar.getInstance();

                        Date today = cal.getTime();

                       
cal.add(Calendar.DAY_OF_MONTH,-1);

                        Date yesterday = cal.getTime();

                       
cal.add(Calendar.DAY_OF_MONTH,1);

                        Date tomorrow = cal.getTime();

 

                        /*

                         * Fails test case

                         */

                        for (int i=0;i < size;i++){

                                    data[i] = yesterday;

                                    i++;

                                    data[i] = today;

                                    i++;

                                    data[i] = tomorrow;

                        }

            

                        

                        /*

                         * Passes test case

                         */

            /*

                        for (int i=0;i < size;i++){

                                   
cal.add(Calendar.DAY_OF_MONTH,1);

                                    data[i] = cal.getTime();

                        }

                        */

                        

 

                        TestModel model = new TestModel();

                        model.set(data);

                        tableViewer.setInput(model);

                        tableViewer.refresh();

            }

            

            class TestContentProvider extends DeferredContentProvider{

                                                

                        public void dispose() {

                        }

                        

                        public
TestContentProvider(Comparator sorter){

                                    super(sorter);

                        }

            }

            

            class TestLabelProvider implements ITableLabelProvider{

                        

                        private List listeners = new ArrayList();

                

                public String getColumnText(Object element, int columnIndex){

                                    return element.toString();

                }

                

                public Image getColumnImage(Object element, int columnIndex){

                    return null;

                }

                        

                public void dispose(){

                }

                        

                public void
removeListener(ILabelProviderListener listener){

                    listeners.remove(listener);

                }

                        

                public boolean isLabelProperty(Object element, String property)
{

                    return false;

                }

                        

                public void
addListener(ILabelProviderListener listener){

                    listeners.add(listener);

                }

            }

            

            class TestComparator implements Comparator{

                        

                        boolean ascending;

                        

                        TestComparator(boolean ascending){

                                    this.ascending = ascending;

                                    num = 0;

                        }

                        

                        public int compare(Object o1,
Object o2) {                                          
     

                                    Date lhs = (Date) o1;

                                    Date rhs = (Date) o2;

                                    

                                    num++;

                                    if ((num % 1000) == 0){

                                               
System.out.println("Make the " + num + " comparison.
Comapring " + lhs + " to " + rhs );

                                    }

                                    

                                    int answer;

                    if (ascending){

                                                answer = lhs.compareTo(rhs);

                    }

                    else{

                                                answer = rhs.compareTo(lhs);

                    }

                                                

                                    if ((num % 1000) == 0){

                                               
System.out.println("Answer = " + answer);

                                    }

                                    return answer;

                        }           

            }

            

            public class TestModel extends AbstractConcurrentModel {

                                        

                        private ArrayList data = new ArrayList();

                        

                        public Object[] getElements() {

                                    return data.toArray();

                        }

                                                

                        /**

                         * Sets the contents to the given array of elements

                         * 

                         * @param newContents new contents of this set

                         */

                        public void set(Object[]
newContents) {

                                    data.clear();

                                    

                                    for (int i = 0;i<newContents.length;i++){

                                               
data.add(newContents[i]);

                                    }

                                    

                                   
IConcurrentModelListener[] listeners = getListeners();

                                    for (int i = 0; i < listeners.length; i++) 
{

                                               
IConcurrentModelListener listener = listeners[i];

                                               
listener.setContents(getElements());

                                    }

                        }

                        

                        /**

                         * Empties the set

                         */

                        public void clear() {

                            Object[] removed = getElements();

                            data.clear();

                            fireRemove(removed);

                        }

                                                

                        public void
requestUpdate(IConcurrentModelListener listener) {

                           
listener.setContents(getElements());

                        }

                        

                        public int size(){

                                    return data.size();

                        }

            }

            

            

            public static void main(String[] args){

                        System.out.println("Starting table");

                        Display display = new Display();

                        Shell shell = new Shell(display);

                        shell.setText("Testing Stuff");

                        

                        TestVirtualTable table = new TestVirtualTable(shell);

                        

                        shell.pack();

                        shell.open();

                        

                        while (!shell.isDisposed()){

                                    if
(!display.readAndDispatch()){

                                               
display.sleep();

                                    }

                        }

                        

                        display.dispose();

            }

}
Comment 1 Boris Bokowski CLA 2005-11-09 11:55:41 EST
The tree in LazySortedCollection degenerates and we get O(n) recursive calls. 
Unfortunately, for 3.2, we probably don't have the resources to work on this.

Help in the area of deferred viewers would be very much appreciated.
Comment 2 Boris Bokowski CLA 2009-11-26 09:53:15 EST
Hitesh is now responsible for watching bugs in the [Viewers] component area.
Comment 3 Eclipse Genie CLA 2019-11-16 10:43:46 EST
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet.

If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

--
The automated Eclipse Genie.