]> source.dussan.org Git - vaadin-framework.git/commitdiff
Table is not caching thousands of rows in vain (#13576)
authorSara Seppola <sara@vaadin.com>
Tue, 4 Nov 2014 09:44:45 +0000 (11:44 +0200)
committerVaadin Code Review <review@vaadin.com>
Wed, 12 Nov 2014 15:27:49 +0000 (15:27 +0000)
Change-Id: I6f6382dd3468db40c36e507b94f84ab1191e100f

client/src/com/vaadin/client/ui/VScrollTable.java
uitest/src/com/vaadin/tests/components/table/TableCacheMinimizingOnFetchRows.java [new file with mode: 0644]
uitest/src/com/vaadin/tests/components/table/TableCacheMinimizingOnFetchRowsTest.java [new file with mode: 0644]

index a382db573c2f57e0592315788b34ad270739b5b2..b07d2dc9c0dd2e7aa784f07b74a1151709640b20 100644 (file)
@@ -2600,11 +2600,12 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
 
         @Override
         public void run() {
+
             if (client.hasActiveRequest() || navKeyDown) {
                 // if client connection is busy, don't bother loading it more
                 VConsole.log("Postponed rowfetch");
                 schedule(250);
-            } else if (!updatedReqRows && allRenderedRowsAreNew()) {
+            } else if (allRenderedRowsAreNew() && !updatedReqRows) {
 
                 /*
                  * If all rows are new, there might have been a server-side call
@@ -2625,6 +2626,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
                 setReqRows(last - getReqFirstRow() + 1);
                 updatedReqRows = true;
                 schedule(250);
+
             } else {
 
                 int firstRendered = scrollBody.getFirstRendered();
@@ -2712,6 +2714,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
                     client.updateVariable(paintableId, "firstvisible",
                             firstRowInViewPort, false);
                 }
+
                 client.updateVariable(paintableId, "reqfirstrow", reqFirstRow,
                         false);
                 client.updateVariable(paintableId, "reqrows", reqRows, true);
@@ -4209,7 +4212,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
         }
 
         /**
-         * Returns the expand ration of the cell
+         * Returns the expand ratio of the cell
          * 
          * @return The expand ratio
          */
@@ -4697,10 +4700,12 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
         }
 
         public int getLastRendered() {
+
             return lastRendered;
         }
 
         public int getFirstRendered() {
+
             return firstRendered;
         }
 
@@ -4784,10 +4789,12 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
             } else if (firstIndex + rows == firstRendered) {
                 final VScrollTableRow[] rowArray = new VScrollTableRow[rows];
                 int i = rows;
+
                 while (it.hasNext()) {
                     i--;
                     rowArray[i] = prepareRow((UIDL) it.next());
                 }
+
                 for (i = 0; i < rows; i++) {
                     addRowBeforeFirstRendered(rowArray[i]);
                     firstRendered--;
@@ -4812,10 +4819,12 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
                 setLastRendered(lastRendered + 1);
                 setContainerHeight();
                 fixSpacers();
+
                 while (it.hasNext()) {
                     addRow(prepareRow((UIDL) it.next()));
                     setLastRendered(lastRendered + 1);
                 }
+
                 fixSpacers();
             }
 
@@ -4830,6 +4839,14 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
          * has changed since the last request.
          */
         protected void ensureCacheFilled() {
+
+            /**
+             * Fixes cache issue #13576 where unnecessary rows are fetched
+             */
+            if (isLazyScrollerActive()) {
+                return;
+            }
+
             int reactFirstRow = (int) (firstRowInViewPort - pageLength
                     * cache_react_rate);
             int reactLastRow = (int) (firstRowInViewPort + pageLength + pageLength
@@ -6137,7 +6154,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
                         touchStart = event;
                         Touch touch = event.getChangedTouches().get(0);
                         // save position to fields, touches in events are same
-                        // isntance during the operation.
+                        // instance during the operation.
                         touchStartX = touch.getClientX();
                         touchStartY = touch.getClientY();
                         /*
@@ -6445,8 +6462,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
                     startRow = focusedRow;
                     selectionRangeStart = focusedRow;
                     // If start row is null then we have a multipage selection
-                    // from
-                    // above
+                    // from above
                     if (startRow == null) {
                         startRow = (VScrollTableRow) scrollBody.iterator()
                                 .next();
@@ -7281,6 +7297,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
         }
         if (preLimit < firstRendered) {
             // need some rows to the beginning of the rendered area
+
             rowRequestHandler
                     .setReqFirstRow((int) (firstRowInViewPort - pageLength
                             * cache_rate));
@@ -7666,13 +7683,13 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
                             // viewport
                             selectLastItemInNextRender = true;
                             multiselectPending = shift;
-                            scrollByPagelenght(1);
+                            scrollByPagelength(1);
                         }
                     }
                 }
             } else {
                 /* No selections, go page down by scrolling */
-                scrollByPagelenght(1);
+                scrollByPagelength(1);
             }
             return true;
         }
@@ -7718,13 +7735,13 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
                             // viewport
                             selectFirstItemInNextRender = true;
                             multiselectPending = shift;
-                            scrollByPagelenght(-1);
+                            scrollByPagelength(-1);
                         }
                     }
                 }
             } else {
                 /* No selections, go page up by scrolling */
-                scrollByPagelenght(-1);
+                scrollByPagelength(-1);
             }
 
             return true;
@@ -7798,7 +7815,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
                 .getRowHeight());
     }
 
-    private void scrollByPagelenght(int i) {
+    private void scrollByPagelength(int i) {
         int pixels = i * scrollBodyPanel.getOffsetHeight();
         int newPixels = scrollBodyPanel.getScrollPosition() + pixels;
         if (newPixels < 0) {
diff --git a/uitest/src/com/vaadin/tests/components/table/TableCacheMinimizingOnFetchRows.java b/uitest/src/com/vaadin/tests/components/table/TableCacheMinimizingOnFetchRows.java
new file mode 100644 (file)
index 0000000..745f234
--- /dev/null
@@ -0,0 +1,92 @@
+package com.vaadin.tests.components.table;
+
+import java.io.Serializable;
+import java.util.List;
+
+import com.vaadin.data.util.BeanContainer;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUIWithLog;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Table;
+
+@SuppressWarnings("serial")
+public class TableCacheMinimizingOnFetchRows extends AbstractTestUIWithLog {
+
+    @Override
+    protected void setup(VaadinRequest request) {
+        getLayout().setMargin(true);
+
+        final Table table = new Table("Beans of All Sorts");
+
+        BeanContainer<String, Bean> beans = new BeanContainer<String, Bean>(
+                Bean.class) {
+            @Override
+            public List<String> getItemIds(int startIndex, int numberOfIds) {
+
+                // numberOfIds should be about 60 after scrolling down the table
+                log.log("requested " + numberOfIds + " rows");
+
+                return super.getItemIds(startIndex, numberOfIds);
+            }
+        };
+        beans.setBeanIdProperty("name");
+
+        for (int i = 0; i < 10000; i++) {
+            beans.addBean(new Bean("Common bean" + i, i));
+        }
+
+        table.setContainerDataSource(beans);
+        table.setPageLength(20);
+        table.setVisibleColumns(new Object[] { "name", "value" });
+        table.setWidth("800px");
+
+        Button button = new Button("scroll down");
+        button.addClickListener(new Button.ClickListener() {
+            @Override
+            public void buttonClick(ClickEvent event) {
+                table.setCurrentPageFirstItemIndex(table.size());
+            }
+        });
+
+        addComponent(table);
+        addComponent(button);
+    }
+
+    public class Bean implements Serializable {
+
+        String name;
+        int value;
+
+        public Bean(String name, int value) {
+            this.name = name;
+            this.value = value;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public void setName(String name) {
+            this.name = name;
+        }
+
+        public int getValue() {
+            return value;
+        }
+
+        public void setValue(int value) {
+            this.value = value;
+        }
+    }
+
+    @Override
+    protected String getTestDescription() {
+        return "Ensure that when scrolling from top to bottom in a big table with 10000 items, not all rows in the range are cached";
+    }
+
+    @Override
+    protected Integer getTicketNumber() {
+        return 13576;
+    }
+}
\ No newline at end of file
diff --git a/uitest/src/com/vaadin/tests/components/table/TableCacheMinimizingOnFetchRowsTest.java b/uitest/src/com/vaadin/tests/components/table/TableCacheMinimizingOnFetchRowsTest.java
new file mode 100644 (file)
index 0000000..edb0f38
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.table;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import org.junit.Test;
+import org.openqa.selenium.By;
+
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class TableCacheMinimizingOnFetchRowsTest extends MultiBrowserTest {
+
+    @Test
+    public void testCacheSize() throws InterruptedException {
+
+        openTestURL();
+
+        scrollToBottomOfTable();
+
+        // the row request might vary slightly with different browsers
+        String logtext1 = "requested 60 rows";
+        String logtext2 = "requested 61 rows";
+
+        assertThat("Requested cached rows did not match expected",
+                logContainsText(logtext1) || logContainsText(logtext2));
+
+    }
+
+    private void scrollToBottomOfTable() {
+        waitForElementPresent(By.className("v-button"));
+        $(ButtonElement.class).first().click();
+    }
+}