PageRenderTime 59ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/akubra-qsc/src/test/java/org/akubraproject/qsc/QuiescingBlobStoreTCKTest.java

https://github.com/JerryPan/akubra
Java | 266 lines | 190 code | 40 blank | 36 comment | 12 complexity | af0c08340fc80ced53251c4598fb5392 MD5 | raw file
  1. /* $HeadURL:: $
  2. * $Id$
  3. *
  4. * Copyright (c) 2009-2010 DuraSpace
  5. * http://duraspace.org
  6. *
  7. * In collaboration with Topaz Inc.
  8. * http://www.topazproject.org
  9. *
  10. * Licensed under the Apache License, Version 2.0 (the "License");
  11. * you may not use this file except in compliance with the License.
  12. * You may obtain a copy of the License at
  13. *
  14. * http://www.apache.org/licenses/LICENSE-2.0
  15. *
  16. * Unless required by applicable law or agreed to in writing, software
  17. * distributed under the License is distributed on an "AS IS" BASIS,
  18. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  19. * See the License for the specific language governing permissions and
  20. * limitations under the License.
  21. */
  22. package org.akubraproject.qsc;
  23. import java.io.File;
  24. import java.io.IOException;
  25. import java.io.OutputStream;
  26. import java.net.URI;
  27. import org.apache.commons.io.FileUtils;
  28. import org.testng.annotations.Factory;
  29. import org.testng.annotations.Test;
  30. import static org.testng.Assert.assertEquals;
  31. import static org.testng.Assert.assertFalse;
  32. import static org.testng.Assert.assertTrue;
  33. import static org.testng.Assert.fail;
  34. import org.akubraproject.AkubraException;
  35. import org.akubraproject.Blob;
  36. import org.akubraproject.BlobStore;
  37. import org.akubraproject.BlobStoreConnection;
  38. import org.akubraproject.mem.MemBlobStore;
  39. import org.akubraproject.tck.TCKTestSuite;
  40. import org.akubraproject.txn.derby.TransactionalStore;
  41. /**
  42. * TCK test suite for {@link QuiescingBlobStore}.
  43. *
  44. * @author Chris Wilper;
  45. */
  46. public class QuiescingBlobStoreTCKTest {
  47. @Factory
  48. public Object[] createTests() throws Exception {
  49. URI storeId1 = URI.create("urn:qsc-tck-test:42");
  50. URI storeId2 = URI.create("urn:qsc-tck-test:43");
  51. BlobStore nonTxnStore = new MemBlobStore(URI.create("urn:store:1"));
  52. BlobStore txnStore =
  53. createTxnStore("qsc-txn-text-1", new MemBlobStore(URI.create("urn:store:2")));
  54. return new Object[] {
  55. new QuiescingBlobStoreTestSuite(new QuiescingBlobStore(storeId1, nonTxnStore), storeId1,
  56. false, true),
  57. new QuiescingBlobStoreTestSuite(new QuiescingBlobStore(storeId2, txnStore), storeId2,
  58. true, false),
  59. };
  60. }
  61. private BlobStore createTxnStore(String name, BlobStore backingStore) throws IOException {
  62. File base = new File(System.getProperty("basedir"), "target");
  63. File dbDir = new File(base, name);
  64. FileUtils.deleteDirectory(dbDir);
  65. dbDir.getParentFile().mkdirs();
  66. System.setProperty("derby.stream.error.file", new File(base, "derby.log").toString());
  67. BlobStore store = new TransactionalStore(URI.create("urn:" + name), backingStore, dbDir.getPath());
  68. return store;
  69. }
  70. public static class QuiescingBlobStoreTestSuite extends TCKTestSuite {
  71. public QuiescingBlobStoreTestSuite(BlobStore store, URI storeId, boolean isTransactional,
  72. boolean supportsIdGen) {
  73. super(store, storeId, isTransactional, supportsIdGen);
  74. }
  75. @Override
  76. protected URI[] getAliases(URI uri) {
  77. // for underlying mem store, all uris are distinct
  78. return new URI[] { uri };
  79. }
  80. @Override
  81. protected URI getInvalidId() {
  82. // for underlying mem store, all uris are valid
  83. return null;
  84. }
  85. /**
  86. * Request to go quiescent and non-quiescent (even when already in those
  87. * states) should be supported.
  88. */
  89. @Test(groups={ "store" }, dependsOnGroups={ "init" })
  90. public void testSetQuiescent() throws Exception {
  91. // basic set (non-)quiescent
  92. assertTrue(((QuiescingBlobStore) store).setQuiescent(true));
  93. assertTrue(((QuiescingBlobStore) store).setQuiescent(true));
  94. assertTrue(((QuiescingBlobStore) store).setQuiescent(false));
  95. assertTrue(((QuiescingBlobStore) store).setQuiescent(false));
  96. // in quiescent state: read-only should proceed, write should block
  97. final URI id1 = createId("blobSetQuiescent1");
  98. final URI id2 = createId("blobSetQuiescent2");
  99. createBlob(id1, "bar", true);
  100. runTests(new ConAction() {
  101. public void run(BlobStoreConnection con) throws Exception {
  102. final Blob b1 = getBlob(con, id1, "bar");
  103. final Blob b2 = getBlob(con, id2, false);
  104. assertTrue(((QuiescingBlobStore) store).setQuiescent(true));
  105. try {
  106. doWithTimeout(new ERunnable() {
  107. @Override
  108. public void erun() throws Exception {
  109. assertTrue(b1.exists());
  110. }
  111. }, 100, true);
  112. doWithTimeout(new ERunnable() {
  113. @Override
  114. public void erun() throws Exception {
  115. assertFalse(b2.exists());
  116. }
  117. }, 100, true);
  118. doWithTimeout(new ERunnable() {
  119. @Override
  120. public void erun() throws Exception {
  121. assertEquals(getBody(b1), "bar");
  122. }
  123. }, 100, true);
  124. if (isOutputSupp) {
  125. doWithTimeout(new ERunnable() {
  126. @Override
  127. public void erun() throws Exception {
  128. b1.openOutputStream(-1, true);
  129. }
  130. }, 100, false);
  131. }
  132. if (isDeleteSupp) {
  133. doWithTimeout(new ERunnable() {
  134. @Override
  135. public void erun() throws Exception {
  136. b1.delete();
  137. }
  138. }, 100, false);
  139. }
  140. if (isMoveToSupp) {
  141. doWithTimeout(new ERunnable() {
  142. @Override
  143. public void erun() throws Exception {
  144. b1.moveTo(b2.getId(), null);
  145. }
  146. }, 100, false);
  147. }
  148. } finally {
  149. assertTrue(((QuiescingBlobStore) store).setQuiescent(false));
  150. }
  151. }
  152. }, true);
  153. // going quiescent should wait for in-progress write operations to complete
  154. if (isOutputSupp) {
  155. final boolean[] cv = new boolean[] { false };
  156. final boolean[] failed = new boolean[] { false };
  157. final Thread t = doInThread(new ERunnable() {
  158. @Override
  159. public void erun() throws Exception {
  160. waitFor(cv, true, 0);
  161. try {
  162. assertTrue(((QuiescingBlobStore) store).setQuiescent(true));
  163. } finally {
  164. assertTrue(((QuiescingBlobStore) store).setQuiescent(false));
  165. }
  166. }
  167. }, failed);
  168. runTests(new ConAction() {
  169. public void run(BlobStoreConnection con) throws Exception {
  170. final Blob b1 = getBlob(con, id1, "bar");
  171. OutputStream os = b1.openOutputStream(-1, true);
  172. TCKTestSuite.notify(cv, true);
  173. t.join(100);
  174. assertTrue(t.isAlive());
  175. os.close();
  176. t.join(100);
  177. if (isTransactional) {
  178. assertTrue(t.isAlive());
  179. } else {
  180. assertFalse(t.isAlive());
  181. assertFalse(failed[0]);
  182. }
  183. }
  184. }, true);
  185. if (isTransactional) {
  186. t.join(100);
  187. assertFalse(t.isAlive());
  188. assertFalse(failed[0]);
  189. }
  190. assertTrue(((QuiescingBlobStore) store).setQuiescent(false));
  191. }
  192. // clean up
  193. assertTrue(((QuiescingBlobStore) store).setQuiescent(false));
  194. deleteBlob(id1, "", true);
  195. assertNoBlobs(getPrefixFor("blobSetQuiescent"));
  196. }
  197. private void doWithTimeout(final ERunnable test, final long timeout, final boolean expSucc)
  198. throws Exception {
  199. boolean[] failed = new boolean[] { false };
  200. Thread t = doInThread(new Runnable() {
  201. public void run() {
  202. try {
  203. test.erun();
  204. if (!expSucc)
  205. fail("Did not get expected exception");
  206. } catch (IOException ioe) {
  207. if (expSucc || ioe instanceof AkubraException)
  208. throw new RuntimeException(ioe);
  209. } catch (Exception e) {
  210. throw new RuntimeException(e);
  211. }
  212. }
  213. }, failed);
  214. t.join(timeout);
  215. if (expSucc) {
  216. assertFalse(t.isAlive());
  217. } else {
  218. assertTrue(t.isAlive());
  219. t.interrupt();
  220. t.join(timeout);
  221. assertFalse(t.isAlive(), "operation failed to return after interrupt");
  222. }
  223. assertFalse(failed[0]);
  224. }
  225. }
  226. }