Return-Path: Delivered-To: apmail-incubator-isis-commits-archive@minotaur.apache.org Received: (qmail 62412 invoked from network); 6 Apr 2011 17:47:26 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 6 Apr 2011 17:47:26 -0000 Received: (qmail 27330 invoked by uid 500); 6 Apr 2011 17:47:26 -0000 Delivered-To: apmail-incubator-isis-commits-archive@incubator.apache.org Received: (qmail 27315 invoked by uid 500); 6 Apr 2011 17:47:26 -0000 Mailing-List: contact isis-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: isis-dev@incubator.apache.org Delivered-To: mailing list isis-commits@incubator.apache.org Received: (qmail 27308 invoked by uid 99); 6 Apr 2011 17:47:26 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 06 Apr 2011 17:47:26 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 06 Apr 2011 17:47:24 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 2F5AE238890A; Wed, 6 Apr 2011 17:47:04 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1089546 - in /incubator/isis/trunk/runtimes/dflt: objectstores/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/file/server/ objectstores/nosql/src/test/java/org/apache/isis/runtimes/dflt/objectstores/nosql/ objectstore... Date: Wed, 06 Apr 2011 17:47:04 -0000 To: isis-commits@incubator.apache.org From: rmatthews@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20110406174704.2F5AE238890A@eris.apache.org> Author: rmatthews Date: Wed Apr 6 17:47:03 2011 New Revision: 1089546 URL: http://svn.apache.org/viewvc?rev=1089546&view=rev Log: File server store is now more resilient to partial writes. Modified: incubator/isis/trunk/runtimes/dflt/objectstores/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/file/server/FileServerProcessor.java incubator/isis/trunk/runtimes/dflt/objectstores/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/file/server/ServerConnection.java incubator/isis/trunk/runtimes/dflt/objectstores/nosql/src/test/java/org/apache/isis/runtimes/dflt/objectstores/nosql/DestroyObjectCommandImplementationTest.java incubator/isis/trunk/runtimes/dflt/objectstores/nosql/src/test/java/org/apache/isis/runtimes/dflt/objectstores/nosql/file/server/FileServerTest.java incubator/isis/trunk/runtimes/dflt/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/persistence/PersistenceSessionAbstract.java incubator/isis/trunk/runtimes/dflt/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/persistence/oidgenerator/simple/SerialOid.java Modified: incubator/isis/trunk/runtimes/dflt/objectstores/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/file/server/FileServerProcessor.java URL: http://svn.apache.org/viewvc/incubator/isis/trunk/runtimes/dflt/objectstores/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/file/server/FileServerProcessor.java?rev=1089546&r1=1089545&r2=1089546&view=diff ============================================================================== --- incubator/isis/trunk/runtimes/dflt/objectstores/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/file/server/FileServerProcessor.java (original) +++ incubator/isis/trunk/runtimes/dflt/objectstores/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/file/server/FileServerProcessor.java Wed Apr 6 17:47:03 2011 @@ -59,6 +59,7 @@ public class FileServerProcessor { public void process(ServerConnection connection) { try { if (acceptNewRequests) { + connection.readCommand(); char command = connection.getCommand(); switch (command) { case 'L': @@ -111,6 +112,7 @@ public class FileServerProcessor { private void list(ServerConnection connection) { try { + connection.endCommand(); String type = connection.getRequest(); int limit = connection.getRequestAsInt(); if (limit == 0) { @@ -154,6 +156,7 @@ public class FileServerProcessor { String type = null; String id = null; try { + connection.endCommand(); type = connection.getRequest(); id = connection.getRequest(); DataReader reader = findInstance(type, id, connection); @@ -163,10 +166,12 @@ public class FileServerProcessor { connection.ok(); readInstance(reader, connection); } - locks.release(id, getTransactionId()); } catch (IOException e) { throw new NoSqlStoreException(Util.READ_ERROR + " for " + type + "/" + id, e); + } finally { + locks.release(id, getTransactionId()); } + } @@ -212,7 +217,7 @@ public class FileServerProcessor { private List getWriteRequests(ServerConnection connection) throws IOException { ArrayList files = new ArrayList(); - while(connection.readHeader()) { + while(connection.readWriteHeaders()) { char command = connection.getCommand(); String type = connection.getRequest(); String id = connection.getRequest(); @@ -223,6 +228,7 @@ public class FileServerProcessor { String buf = connection.getData(); files.add(new FileContent(command, id, currentVersion, newVersion, type, buf)); } +// connection.endCommand(); return files; } @@ -236,9 +242,9 @@ public class FileServerProcessor { DataReader dataReader = new DataReader(item.type, item.id); String version = dataReader.getVersion(); if (!version.equals(item.currentVersion)) { - String data = dataReader.getData(); + //String data = dataReader.getData(); dataReader.close(); - return data; + return "mismatch between FileContent version (" + item.currentVersion + ") and DataReader version (" + version + ")"; } dataReader.close(); } @@ -258,6 +264,7 @@ public class FileServerProcessor { } private void status(ServerConnection connection) throws IOException { + connection.endCommand(); String request = connection.getRequest(); if (request.equals("contains-data")) { connection.response(Util.isPopulated()); @@ -268,6 +275,7 @@ public class FileServerProcessor { } private void service(ServerConnection connection) { + connection.endCommand(); String name = connection.getRequest(); File file = Util.serviceFile(name); if (file.exists()) { @@ -297,6 +305,7 @@ public class FileServerProcessor { } private void saveService(ServerConnection connection) throws IOException { + connection.endCommand(); String name = connection.getRequest(); String key = connection.getRequest(); @@ -322,6 +331,7 @@ public class FileServerProcessor { private void nextSerialBatch(ServerConnection connection) throws IOException { // TODO lock file first + connection.endCommand(); String name = connection.getRequest(); int batchSize = connection.getRequestAsInt(); @@ -348,6 +358,7 @@ public class FileServerProcessor { } private void hasInstances(ServerConnection connection) throws IOException { + connection.endCommand(); String type = connection.getRequest(); File[] listFiles = listFiles(type); boolean hasInstances = listFiles != null && listFiles.length > 0; Modified: incubator/isis/trunk/runtimes/dflt/objectstores/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/file/server/ServerConnection.java URL: http://svn.apache.org/viewvc/incubator/isis/trunk/runtimes/dflt/objectstores/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/file/server/ServerConnection.java?rev=1089546&r1=1089545&r2=1089546&view=diff ============================================================================== --- incubator/isis/trunk/runtimes/dflt/objectstores/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/file/server/ServerConnection.java (original) +++ incubator/isis/trunk/runtimes/dflt/objectstores/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/file/server/ServerConnection.java Wed Apr 6 17:47:03 2011 @@ -48,7 +48,10 @@ public class ServerConnection { inputStream = Util.trace(input, true); this.reader = new BufferedReader(new InputStreamReader(inputStream, Util.ENCODING)); this.writer = new PrintWriter(new OutputStreamWriter(outputStream, Util.ENCODING)); - readHeader(); + } + + public void readCommand() { + readHeaders(); } private void logFailure() { @@ -61,15 +64,19 @@ public class ServerConnection { LOG.debug("(complete " + outputStream + ")"); } - boolean readHeader() { + boolean readHeaders() { try { - String header = reader.readLine(); - LOG.debug("request: " + header); - if (header == null || header.length() == 0) { + String line = reader.readLine(); + LOG.debug("header: " + line); + if (line == null) { + logFailure(); + throw new RemotingException("stream ended prematurely while reading header, aborting request"); + } + if (line.length() == 0) { return false; } else { - command = header.charAt(0); - headers = header.substring(1).split(" "); + command = line.charAt(0); + headers = line.substring(1).split(" "); this.header = 0; return true; } @@ -79,6 +86,15 @@ public class ServerConnection { } } + public boolean readWriteHeaders() { + boolean readHeaders = readHeaders(); + if (readHeaders && headers.length != 4) { + logFailure(); + throw new RemotingException("invalid header string, aborting request"); + } + return readHeaders; + } + public String getRequest() { return headers[header++]; } @@ -91,6 +107,23 @@ public class ServerConnection { return command; } + public void endCommand() { + try { + String line = reader.readLine(); + if (line == null) { + logFailure(); + throw new RemotingException("stream ended prematurely while reading end of command, aborting request"); + } + if (line.length() > 0) { + logFailure(); + throw new RemotingException("command didn't end with an empty blank line, aborting request"); + } + } catch (IOException e) { + logFailure(); + throw new NoSqlStoreException(e); + } + } + /** * Reads all the data up until the next blank line. */ @@ -98,7 +131,15 @@ public class ServerConnection { try { StringBuffer buffer = new StringBuffer(); String line; - while ((line = reader.readLine()) != null && line.length() != 0) { + while (true) { + line = reader.readLine(); + if (line == null) { + logFailure(); + throw new RemotingException("stream ended prematurely while reading data, aborting request"); + } + if (line.length() == 0) { + break; + } buffer.append(line); buffer.append('\n'); } @@ -108,7 +149,21 @@ public class ServerConnection { throw new RemotingException(e); } } +/* + public void getTermination() { + try { + String line = reader.readLine(); + if (line == null || !line.equals("***")) { + logFailure(); + throw new RemotingException("stream ended abruptly while reading data, aborting request"); + } + } catch (IOException e) { + logFailure(); + throw new RemotingException(e); + } + } +*/ public void notFound(String message) { writer.println("not-found"); writer.println(message); Modified: incubator/isis/trunk/runtimes/dflt/objectstores/nosql/src/test/java/org/apache/isis/runtimes/dflt/objectstores/nosql/DestroyObjectCommandImplementationTest.java URL: http://svn.apache.org/viewvc/incubator/isis/trunk/runtimes/dflt/objectstores/nosql/src/test/java/org/apache/isis/runtimes/dflt/objectstores/nosql/DestroyObjectCommandImplementationTest.java?rev=1089546&r1=1089545&r2=1089546&view=diff ============================================================================== --- incubator/isis/trunk/runtimes/dflt/objectstores/nosql/src/test/java/org/apache/isis/runtimes/dflt/objectstores/nosql/DestroyObjectCommandImplementationTest.java (original) +++ incubator/isis/trunk/runtimes/dflt/objectstores/nosql/src/test/java/org/apache/isis/runtimes/dflt/objectstores/nosql/DestroyObjectCommandImplementationTest.java Wed Apr 6 17:47:03 2011 @@ -53,9 +53,9 @@ public class DestroyObjectCommandImpleme ObjectAdapter object = IsisContext.getPersistenceSession().createInstance(specification); IsisContext.getPersistenceSession().makePersistent(object); object.setOptimisticLock(new SerialNumberVersion(3, "username", new Date(1000))); - + long id = ((SerialOid) object.getOid()).getSerialNo(); - final String key = Long.toHexString(id); + final String key = Long.toString(id, 16); Mockery context = new Mockery(); final NoSqlCommandContext commandContext = context.mock(NoSqlCommandContext.class); Modified: incubator/isis/trunk/runtimes/dflt/objectstores/nosql/src/test/java/org/apache/isis/runtimes/dflt/objectstores/nosql/file/server/FileServerTest.java URL: http://svn.apache.org/viewvc/incubator/isis/trunk/runtimes/dflt/objectstores/nosql/src/test/java/org/apache/isis/runtimes/dflt/objectstores/nosql/file/server/FileServerTest.java?rev=1089546&r1=1089545&r2=1089546&view=diff ============================================================================== --- incubator/isis/trunk/runtimes/dflt/objectstores/nosql/src/test/java/org/apache/isis/runtimes/dflt/objectstores/nosql/file/server/FileServerTest.java (original) +++ incubator/isis/trunk/runtimes/dflt/objectstores/nosql/src/test/java/org/apache/isis/runtimes/dflt/objectstores/nosql/file/server/FileServerTest.java Wed Apr 6 17:47:03 2011 @@ -19,6 +19,17 @@ package org.apache.isis.runtimes.dflt.objectstores.nosql.file.server; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileWriter; +import java.io.InputStream; + +import org.apache.isis.core.commons.lang.IoUtils; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + import static org.apache.isis.core.commons.lang.StringUtils.lineSeparated; import static org.apache.isis.core.commons.matchers.IsisMatchers.existsAndNotEmpty; import static org.hamcrest.Matchers.containsString; @@ -32,19 +43,6 @@ import static org.junit.Assert.assertNot import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileWriter; -import java.io.InputStream; - -import org.junit.After; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; - -import org.apache.isis.core.commons.lang.IoUtils; - public class FileServerTest { private FileServerProcessor server; private File logFile1; @@ -85,7 +83,7 @@ public class FileServerTest { @Test public void cantReadOrWriteAfterShutdown() throws Exception { - InputStream in = new ByteArrayInputStream(new byte[128]); + InputStream in = IoUtils.asUtf8ByteStream("R[org.domain.Class 1025]\n"); ByteArrayOutputStream out = new ByteArrayOutputStream(); ServerConnection connection = new ServerConnection(in, out); @@ -95,6 +93,33 @@ public class FileServerTest { } @Test + public void writeAbortedAsDataNotComplete() throws Exception { + InputStream in = IoUtils.asUtf8ByteStream("W\nIorg.domain.Class 1025 null 1 \n{da"); + ServerConnection connection = new ServerConnection(in, out); + server.process(connection); + + assertThat(out.toString(), is(containsString("stream ended prematurely while reading data, aborting request"))); + } + + @Test + public void writeAbortsIfMissingNextDataBlock() throws Exception { + InputStream in = IoUtils.asUtf8ByteStream("W\nIorg.domain.Class 1025 null 1 \n{data1}\n\n"); + ServerConnection connection = new ServerConnection(in, out); + server.process(connection); + + assertThat(out.toString(), is(containsString("stream ended prematurely while reading header, aborting request"))); + } + + @Test + public void writeAbortedAsHeaderNotComplete() throws Exception { + InputStream in = IoUtils.asUtf8ByteStream("W\nIorg.domain.Class 1025"); + ServerConnection connection = new ServerConnection(in, out); + server.process(connection); + + assertThat(out.toString(), is(containsString("invalid header string, aborting request"))); + } + + @Test public void writeCreatesFilesUsingDataWriter() throws Exception { File file1 = new File("target/test/org.domain.Class", "1025.data"); File file2 = new File("target/test/org.domain.Class", "1026.data"); @@ -104,7 +129,7 @@ public class FileServerTest { assertFalse(file2.exists()); InputStream in = - IoUtils.asUtf8ByteStream("W\nIorg.domain.Class 1025 null 1 \n{data1}\n\nIorg.domain.Class 1026 null 1\n{data2}\n"); + IoUtils.asUtf8ByteStream("W\nIorg.domain.Class 1025 null 1 \n{data1}\n\nIorg.domain.Class 1026 null 1\n{data2}\n\n\n"); ServerConnection connection = new ServerConnection(in, out); server.process(connection); @@ -122,7 +147,7 @@ public class FileServerTest { fileWriter.close(); ServerConnection connection = - new ServerConnection(IoUtils.asUtf8ByteStream("W\nUorg.domain.Class 1026 21 22 \n{data2}\n"), out); + new ServerConnection(IoUtils.asUtf8ByteStream("W\nUorg.domain.Class 1026 21 22 \n{data2}\n\n\n"), out); server.process(connection); assertThat(out.toString(), is(equalTo(lineSeparated("ok\n")))); @@ -133,21 +158,21 @@ public class FileServerTest { public void writeUpdateFailsWhenVersionsDontMatch() throws Exception { File file2 = new File("target/test/org.domain.Class", "1026.data"); FileWriter fileWriter = new FileWriter(file2); - String originalData = "org.domain.Class 1026 21\n{datax}"; + String originalData = "org.domain.Class 1026 21\n{datax}\n\n\n***"; fileWriter.write(originalData); fileWriter.close(); ServerConnection connection = - new ServerConnection(IoUtils.asUtf8ByteStream("W\nUorg.domain.Class 1026 19 21 \n{data2}\n"), out); + new ServerConnection(IoUtils.asUtf8ByteStream("W\nUorg.domain.Class 1026 19 21 \n{data2}\n\n\n"), out); server.process(connection); - assertThat(out.toString(), is(equalTo(lineSeparated("error\n{datax}\n")))); + assertThat(out.toString(), is(equalTo(lineSeparated("error\nmismatch between FileContent version (19) and DataReader version (21)\n")))); } @Test public void writeCreatesLogFile() throws Exception { ServerConnection connection = - new ServerConnection(IoUtils.asUtf8ByteStream("W\nIorg.domain.Class 1025 6 7\n{data1}\n"), out); + new ServerConnection(IoUtils.asUtf8ByteStream("W\nIorg.domain.Class 1025 6 7\n{data1}\n\n\n"), out); server.process(connection); assertThat(out.toString(), is(equalTo(lineSeparated("ok\n")))); @@ -160,7 +185,7 @@ public class FileServerTest { public void readNonExistingFileThrowsException() throws Exception { File file1 = new File("target/test/org.domain.Class", "2020.data"); file1.delete(); - ServerConnection connection = new ServerConnection(IoUtils.asUtf8ByteStream("Rorg.domain.Class 2020"), out); + ServerConnection connection = new ServerConnection(IoUtils.asUtf8ByteStream("Rorg.domain.Class 2020\n\n"), out); server.process(connection); String string = out.toString(); @@ -190,12 +215,19 @@ public class FileServerTest { fileWriter.write("type 1025 1\n{data1}"); fileWriter.close(); - ServerConnection connection = new ServerConnection(IoUtils.asUtf8ByteStream("Rorg.domain.Class 2025"), out); + ServerConnection connection = new ServerConnection(IoUtils.asUtf8ByteStream("Rorg.domain.Class 2025\n\n"), out); server.process(connection); assertThat(out.toString(), is(equalTo(lineSeparated("ok\n{data1}\n")))); } + @Test + public void ReadFailIfEndsEarly() throws Exception { + ServerConnection connection = new ServerConnection(IoUtils.asUtf8ByteStream("Rorg.domain.Class 2025\n"), out); + server.process(connection); + + assertThat(out.toString(), is(containsString("stream ended prematurely while reading end of command, aborting request"))); + } @Test public void LookReadRenamed() throws Exception { @@ -204,7 +236,7 @@ public class FileServerTest { fileWriter.write("type 1025 1\n{data1}"); fileWriter.close(); - ServerConnection connection = new ServerConnection(IoUtils.asUtf8ByteStream("Rorg.domain.Class 2025"), out); + ServerConnection connection = new ServerConnection(IoUtils.asUtf8ByteStream("Rorg.domain.Class 2025\n\n"), out); server.process(connection); assertThat(out.toString(), is(equalTo(lineSeparated("ok\n{data1}\n")))); @@ -218,7 +250,7 @@ public class FileServerTest { fileWriter.write("type 1025 1\n{data1}"); fileWriter.close(); - ServerConnection connection = new ServerConnection(IoUtils.asUtf8ByteStream("Rorg.domain.Class 2025"), out); + ServerConnection connection = new ServerConnection(IoUtils.asUtf8ByteStream("Rorg.domain.Class 2025\n\n"), out); server.process(connection); assertThat(out.toString(), is(equalTo(lineSeparated("ok\n{data1}\n")))); Modified: incubator/isis/trunk/runtimes/dflt/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/persistence/PersistenceSessionAbstract.java URL: http://svn.apache.org/viewvc/incubator/isis/trunk/runtimes/dflt/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/persistence/PersistenceSessionAbstract.java?rev=1089546&r1=1089545&r2=1089546&view=diff ============================================================================== --- incubator/isis/trunk/runtimes/dflt/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/persistence/PersistenceSessionAbstract.java (original) +++ incubator/isis/trunk/runtimes/dflt/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/persistence/PersistenceSessionAbstract.java Wed Apr 6 17:47:03 2011 @@ -339,7 +339,9 @@ public abstract class PersistenceSession if (adapter.getResolveState().isGhost()) { adapter.changeState(ResolveState.RESOLVING); } - adapter.changeState(ResolveState.RESOLVED); + if (adapter.getResolveState().isValidToChangeTo(ResolveState.RESOLVED)) { + adapter.changeState(ResolveState.RESOLVED); + } return adapter; } Modified: incubator/isis/trunk/runtimes/dflt/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/persistence/oidgenerator/simple/SerialOid.java URL: http://svn.apache.org/viewvc/incubator/isis/trunk/runtimes/dflt/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/persistence/oidgenerator/simple/SerialOid.java?rev=1089546&r1=1089545&r2=1089546&view=diff ============================================================================== --- incubator/isis/trunk/runtimes/dflt/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/persistence/oidgenerator/simple/SerialOid.java (original) +++ incubator/isis/trunk/runtimes/dflt/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/persistence/oidgenerator/simple/SerialOid.java Wed Apr 6 17:47:03 2011 @@ -26,9 +26,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.lang.StringUtils; - import org.apache.isis.core.commons.encoding.DataInputExtended; -import org.apache.isis.core.commons.encoding.DataInputStreamExtended; import org.apache.isis.core.commons.encoding.DataOutputExtended; import org.apache.isis.core.commons.encoding.Encodable; import org.apache.isis.core.commons.ensure.Assert;