You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by km...@apache.org on 2009/02/12 17:40:16 UTC
svn commit: r743798 - in /db/derby/code/branches/10.2/java:
engine/org/apache/derby/impl/store/raw/data/
testing/org/apache/derbyTesting/functionTests/master/
testing/org/apache/derbyTesting/functionTests/suites/
testing/org/apache/derbyTesting/functio...
Author: kmarsden
Date: Thu Feb 12 16:40:16 2009
New Revision: 743798
URL: http://svn.apache.org/viewvc?rev=743798&view=rev
Log:
DERBY-4050 Multithreaded clob update causes growth in table that does not get reclaimed
merge 743023 from trunk. Rework test to run in old harness.
Added:
db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/ClobReclamationTest.out (with props)
db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/store/ClobReclamationTest.java (with props)
db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/store/ClobReclamationTest_derby.properties (with props)
Modified:
db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/store/raw/data/ReclaimSpaceHelper.java
db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/suites/storemore.runall
Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/store/raw/data/ReclaimSpaceHelper.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/store/raw/data/ReclaimSpaceHelper.java?rev=743798&r1=743797&r2=743798&view=diff
==============================================================================
--- db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/store/raw/data/ReclaimSpaceHelper.java (original)
+++ db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/store/raw/data/ReclaimSpaceHelper.java Thu Feb 12 16:40:16 2009
@@ -259,9 +259,28 @@
}
if (work.incrAttempts() < 3) // retry this for serveral times
+ {
return Serviceable.REQUEUE;
+ }
else
+ {
+ // If code gets here, the space will be lost forever, and
+ // can only be reclaimed by a full offline compress of the
+ // table/index.
+
+ if (SanityManager.DEBUG)
+ {
+ if (SanityManager.DEBUG_ON(DaemonService.DaemonTrace))
+ {
+ SanityManager.DEBUG(
+ DaemonService.DaemonTrace,
+ " gave up after 3 tries to get container lock " +
+ work);
+ }
+ }
+
return Serviceable.DONE;
+ }
}
// At this point, container is opened with IX lock.
@@ -281,8 +300,8 @@
return Serviceable.DONE;
}
- // We are reclaiming row space or long column. First get an xlock on the
- // head row piece.
+ // We are reclaiming row space or long column.
+ // First get an xlock on the head row piece.
RecordHandle headRecord = work.getHeadRowHandle();
if (!container_rlock.lockRecordForWrite(
@@ -291,9 +310,27 @@
// cannot get the row lock, retry
tran.abort();
if (work.incrAttempts() < 3)
+ {
return Serviceable.REQUEUE;
+ }
else
+ {
+ // If code gets here, the space will be lost forever, and
+ // can only be reclaimed by a full offline compress of the
+ // table/index.
+
+ if (SanityManager.DEBUG)
+ {
+ if (SanityManager.DEBUG_ON(DaemonService.DaemonTrace))
+ {
+ SanityManager.DEBUG(
+ DaemonService.DaemonTrace,
+ " gave up after 3 tries to get row lock " +
+ work);
+ }
+ }
return Serviceable.DONE;
+ }
}
// The exclusive lock on the head row has been gotten.
@@ -332,19 +369,33 @@
// operation.
//
long headPageId = ((PageKey)headRecord.getPageId()).getPageNumber();
+ //DERBY-4050 - we wait for the page so we don't have to retry.
+ // prior to the 4050 fix, we called getPageNoWait and just
+ // retried 3 times. This left unreclaimed space if we were
+ // not successful after three tries.
StoredPage headRowPage =
- (StoredPage)containerHdl.getPageNoWait(headPageId);
-
+ (StoredPage)containerHdl.getPage(headPageId);
if (headRowPage == null)
{
- // Cannot get page no wait, try again later.
+ // It is not clear why headRowPage would be null,
+ // but logging the failure in case it happens.
+ // If code gets here, the space will be lost forever, and
+ // can only be reclaimed by a full offline compress of the
+ // table/index.
+
+ if (SanityManager.DEBUG)
+ {
+ if (SanityManager.DEBUG_ON(DaemonService.DaemonTrace))
+ {
+ SanityManager.DEBUG(
+ DaemonService.DaemonTrace,
+ "gave up because hadRowPage was null" +
+ work);
+ }
+ }
tran.abort();
- if (work.incrAttempts() < 3)
- return Serviceable.REQUEUE;
- else
- return Serviceable.DONE;
+ return Serviceable.DONE;
}
-
try
{
headRowPage.removeOrphanedColumnChain(work, containerHdl);
Added: db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/ClobReclamationTest.out
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/ClobReclamationTest.out?rev=743798&view=auto
==============================================================================
--- db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/ClobReclamationTest.out (added)
+++ db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/ClobReclamationTest.out Thu Feb 12 16:40:16 2009
@@ -0,0 +1 @@
+PASS: NUMALLOCATEDPAGES =5
Propchange: db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/ClobReclamationTest.out
------------------------------------------------------------------------------
svn:eol-style = native
Modified: db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/suites/storemore.runall
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/suites/storemore.runall?rev=743798&r1=743797&r2=743798&view=diff
==============================================================================
--- db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/suites/storemore.runall (original)
+++ db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/suites/storemore.runall Thu Feb 12 16:40:16 2009
@@ -36,3 +36,4 @@
store/BackupPathTests.java
store/LogDeviceTest.java
store/BootAllTest.junit
+store/ClobReclamationTest
\ No newline at end of file
Added: db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/store/ClobReclamationTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/store/ClobReclamationTest.java?rev=743798&view=auto
==============================================================================
--- db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/store/ClobReclamationTest.java (added)
+++ db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/store/ClobReclamationTest.java Thu Feb 12 16:40:16 2009
@@ -0,0 +1,125 @@
+/*
+ *
+ * Derby - Class org.apache.derbyTesting.functionTests.tests.store.ClobReclamationTest
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.derbyTesting.functionTests.tests.store;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import org.apache.derby.tools.ij;
+import org.apache.derbyTesting.functionTests.util.Formatters;
+
+
+
+/**
+ * Verify that space gets reclaimed for multi-threaded Clob updates
+ *
+ */
+public class ClobReclamationTest {
+
+ // Need to adjust NUM_THREADS and expectedNumAllocated.
+ // For 2 threads expectedNumAllocated is 5
+ // For 100 threads expectedNumAllocated is 201
+ private static final int NUM_THREADS = 2;
+
+ private static final int expectedNumAllocated = 5;
+
+
+ /**
+ * Two threads simultaneously updating a table. Thread 1 updates row 1 with
+ * a long value (>32K) Thread 2 updates row with a short clob ("hello");
+ * NUMALLOCATEDPAGES should be only 3 after each does 500 updates
+ *
+ * @throws SQLException
+ * @throws InterruptedException
+ */
+ public static void testMultiThreadedUpdate(Connection conn) throws SQLException,
+ InterruptedException {
+
+ final String updateString = Formatters.repeatChar("a",33000);
+ Thread[] threads = new Thread[NUM_THREADS];
+ for (int i = 0; i < NUM_THREADS; i++) {
+ final int key = i + 1;
+ threads[i] = new Thread() {
+ public void run() {
+ try {
+ Connection conn = ij.startJBMS();
+ ClobReclamationTest.fiveHundredUpdates(conn,
+ updateString, key);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ };
+ }
+ for (int i = 0; i < NUM_THREADS; i++) {
+ threads[i].start();
+ }
+ for (int i = 0; i < NUM_THREADS; i++) {
+ threads[i].join();
+ }
+
+ Statement s = conn.createStatement();
+ // Check the space table
+ // Should not have grown.
+ ResultSet rs = s.executeQuery("SELECT NUMALLOCATEDPAGES FROM "
+ + " new org.apache.derby.diag.SpaceTable('APP','CLOBTAB') t"
+ + " WHERE CONGLOMERATENAME = 'CLOBTAB'");
+ rs.next();
+ int numAllocated = rs.getInt(1);
+ if (numAllocated == expectedNumAllocated)
+ System.out.println("PASS: NUMALLOCATEDPAGES =" + numAllocated);
+ else
+ System.out.println("FAIL: NUMALLOCATEDPAGES =" + numAllocated);
+
+ }
+
+ private static void fiveHundredUpdates(Connection conn,
+ String updateString, int key) throws SQLException {
+ PreparedStatement ps = conn
+ .prepareStatement("UPDATE CLOBTAB SET C = ? WHERE I = ?");
+ for (int i = 0; i < 500; i++) {
+ ps.setString(1, updateString);
+ ps.setInt(2, key);
+ ps.executeUpdate();
+ }
+ }
+
+ public static void main(String[] argv) throws SQLException, IllegalAccessException, ClassNotFoundException, InstantiationException, InterruptedException, IOException {
+ ij.getPropertyArg(argv);
+ Connection conn = ij.startJBMS();
+ Statement s = conn.createStatement();
+ s
+ .executeUpdate("CREATE TABLE CLOBTAB (I INT PRIMARY KEY NOT NULL, c CLOB)");
+ PreparedStatement ps = conn
+ .prepareStatement("INSERT INTO CLOBTAB VALUES(?,?)");
+ String insertString = "hello";
+ for (int i = 1; i <= NUM_THREADS; i++) {
+ ps.setInt(1, i);
+ ps.setString(2, insertString);
+ ps.executeUpdate();
+ }
+ testMultiThreadedUpdate(conn);
+
+ }
+}
\ No newline at end of file
Propchange: db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/store/ClobReclamationTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/store/ClobReclamationTest_derby.properties
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/store/ClobReclamationTest_derby.properties?rev=743798&view=auto
==============================================================================
--- db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/store/ClobReclamationTest_derby.properties (added)
+++ db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/store/ClobReclamationTest_derby.properties Thu Feb 12 16:40:16 2009
@@ -0,0 +1 @@
+derby.debug.true=DaemonTrace
\ No newline at end of file
Propchange: db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/store/ClobReclamationTest_derby.properties
------------------------------------------------------------------------------
svn:eol-style = native