1 package org.apache.lucene.index;
4 * Licensed to the Apache Software Foundation (ASF) under one or more
5 * contributor license agreements. See the NOTICE file distributed with
6 * this work for additional information regarding copyright ownership.
7 * The ASF licenses this file to You under the Apache License, Version 2.0
8 * (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
21 import java.io.IOException;
22 import java.util.BitSet;
23 import java.util.Collection;
24 import java.util.Iterator;
25 import java.util.List;
27 import java.util.HashMap;
29 import org.apache.lucene.util.LuceneTestCase;
30 import org.apache.lucene.analysis.MockAnalyzer;
31 import org.apache.lucene.document.Document;
32 import org.apache.lucene.document.Field;
33 import org.apache.lucene.store.Directory;
36 * Test class to illustrate using IndexDeletionPolicy to provide multi-level rollback capability.
37 * This test case creates an index of records 1 to 100, introducing a commit point every 10 records.
39 * A "keep all" deletion policy is used to ensure we keep all commit points for testing purposes
42 public class TestTransactionRollback extends LuceneTestCase {
44 private static final String FIELD_RECORD_ID = "record_id";
45 private Directory dir;
47 //Rolls back index to a chosen ID
48 private void rollBackLast(int id) throws Exception {
50 // System.out.println("Attempting to rollback to "+id);
52 IndexCommit last=null;
53 Collection<IndexCommit> commits = IndexReader.listCommits(dir);
54 for (Iterator<IndexCommit> iterator = commits.iterator(); iterator.hasNext();) {
55 IndexCommit commit = iterator.next();
56 Map<String,String> ud=commit.getUserData();
58 if (ud.get("index").endsWith(ids))
63 throw new RuntimeException("Couldn't find commit point "+id);
65 IndexWriter w = new IndexWriter(dir, newIndexWriterConfig(
66 TEST_VERSION_CURRENT, new MockAnalyzer(random)).setIndexDeletionPolicy(
67 new RollbackDeletionPolicy(id)).setIndexCommit(last));
68 Map<String,String> data = new HashMap<String,String>();
69 data.put("index", "Rolled back to 1-"+id);
74 public void testRepeatedRollBacks() throws Exception {
76 int expectedLastRecordId=100;
77 while (expectedLastRecordId>10) {
78 expectedLastRecordId -=10;
79 rollBackLast(expectedLastRecordId);
81 BitSet expecteds = new BitSet(100);
82 expecteds.set(1,(expectedLastRecordId+1),true);
83 checkExpecteds(expecteds);
87 private void checkExpecteds(BitSet expecteds) throws Exception {
88 IndexReader r = IndexReader.open(dir, true);
90 //Perhaps not the most efficient approach but meets our needs here.
91 for (int i = 0; i < r.maxDoc(); i++) {
93 String sval=r.document(i).get(FIELD_RECORD_ID);
95 int val=Integer.parseInt(sval);
96 assertTrue("Did not expect document #"+val, expecteds.get(val));
97 expecteds.set(val,false);
102 assertEquals("Should have 0 docs remaining ", 0 ,expecteds.cardinality());
106 private void showAvailableCommitPoints() throws Exception {
107 Collection commits = IndexReader.listCommits(dir);
108 for (Iterator iterator = commits.iterator(); iterator.hasNext();) {
109 IndexCommit comm = (IndexCommit) iterator.next();
110 System.out.print("\t Available commit point:["+comm.getUserData()+"] files=");
111 Collection files = comm.getFileNames();
112 for (Iterator iterator2 = files.iterator(); iterator2.hasNext();) {
113 String filename = (String) iterator2.next();
114 System.out.print(filename+", ");
116 System.out.println();
122 public void setUp() throws Exception {
124 dir = newDirectory();
125 //Build index, of records 1 to 100, committing after each batch of 10
126 IndexDeletionPolicy sdp=new KeepAllDeletionPolicy();
127 IndexWriter w=new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)).setIndexDeletionPolicy(sdp));
128 for(int currentRecordId=1;currentRecordId<=100;currentRecordId++) {
129 Document doc=new Document();
130 doc.add(newField(FIELD_RECORD_ID,""+currentRecordId,Field.Store.YES,Field.Index.ANALYZED));
133 if (currentRecordId%10 == 0) {
134 Map<String,String> data = new HashMap<String,String>();
135 data.put("index", "records 1-"+currentRecordId);
144 public void tearDown() throws Exception {
149 // Rolls back to previous commit point
150 class RollbackDeletionPolicy implements IndexDeletionPolicy {
151 private int rollbackPoint;
153 public RollbackDeletionPolicy(int rollbackPoint) {
154 this.rollbackPoint = rollbackPoint;
157 public void onCommit(List<? extends IndexCommit> commits) throws IOException {
160 public void onInit(List<? extends IndexCommit> commits) throws IOException {
161 for (final IndexCommit commit : commits) {
162 Map<String,String> userData=commit.getUserData();
163 if (userData.size() > 0) {
164 // Label for a commit point is "Records 1-30"
165 // This code reads the last id ("30" in this example) and deletes it
166 // if it is after the desired rollback point
167 String x = userData.get("index");
168 String lastVal = x.substring(x.lastIndexOf("-")+1);
169 int last = Integer.parseInt(lastVal);
170 if (last>rollbackPoint) {
172 System.out.print("\tRolling back commit point:" +
173 " UserData="+commit.getUserData() +") ("+(commits.size()-1)+" commit points left) files=");
174 Collection files = commit.getFileNames();
175 for (Iterator iterator2 = files.iterator(); iterator2.hasNext();) {
176 System.out.print(" "+iterator2.next());
178 System.out.println();
188 class DeleteLastCommitPolicy implements IndexDeletionPolicy {
190 public void onCommit(List<? extends IndexCommit> commits) throws IOException {}
192 public void onInit(List<? extends IndexCommit> commits) throws IOException {
193 commits.get(commits.size()-1).delete();
197 public void testRollbackDeletionPolicy() throws Exception {
198 for(int i=0;i<2;i++) {
199 // Unless you specify a prior commit point, rollback
201 new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random))
202 .setIndexDeletionPolicy(new DeleteLastCommitPolicy())).close();
203 IndexReader r = IndexReader.open(dir, true);
204 assertEquals(100, r.numDocs());
209 // Keeps all commit points (used to build index)
210 class KeepAllDeletionPolicy implements IndexDeletionPolicy {
211 public void onCommit(List<? extends IndexCommit> commits) throws IOException {}
212 public void onInit(List<? extends IndexCommit> commits) throws IOException {}