mirror of https://github.com/apache/lucene.git
LUCENE-1449: if deletion policy deletes head commit point and then IW is closed w/ no further changes, write a new segments_N
git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@713206 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
8e8e8ddec4
commit
4596360907
|
@ -105,6 +105,8 @@ final class IndexFileDeleter {
|
||||||
private IndexDeletionPolicy policy;
|
private IndexDeletionPolicy policy;
|
||||||
private DocumentsWriter docWriter;
|
private DocumentsWriter docWriter;
|
||||||
|
|
||||||
|
final boolean startingCommitDeleted;
|
||||||
|
|
||||||
/** Change to true to see details of reference counts when
|
/** Change to true to see details of reference counts when
|
||||||
* infoStream != null */
|
* infoStream != null */
|
||||||
public static boolean VERBOSE_REF_COUNTS = false;
|
public static boolean VERBOSE_REF_COUNTS = false;
|
||||||
|
@ -244,6 +246,8 @@ final class IndexFileDeleter {
|
||||||
// sometime it may not be the most recent commit
|
// sometime it may not be the most recent commit
|
||||||
checkpoint(segmentInfos, false);
|
checkpoint(segmentInfos, false);
|
||||||
|
|
||||||
|
startingCommitDeleted = currentCommitPoint.isDeleted();
|
||||||
|
|
||||||
deleteCommits();
|
deleteCommits();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1207,6 +1207,13 @@ public class IndexWriter {
|
||||||
deletionPolicy == null ? new KeepOnlyLastCommitDeletionPolicy() : deletionPolicy,
|
deletionPolicy == null ? new KeepOnlyLastCommitDeletionPolicy() : deletionPolicy,
|
||||||
segmentInfos, infoStream, docWriter);
|
segmentInfos, infoStream, docWriter);
|
||||||
|
|
||||||
|
if (deleter.startingCommitDeleted)
|
||||||
|
// Deletion policy deleted the "head" commit point.
|
||||||
|
// We have to mark ourself as changed so that if we
|
||||||
|
// are closed w/o any further changes we write a new
|
||||||
|
// segments_N file.
|
||||||
|
changeCount++;
|
||||||
|
|
||||||
pushMaxBufferedDocs();
|
pushMaxBufferedDocs();
|
||||||
|
|
||||||
if (infoStream != null) {
|
if (infoStream != null) {
|
||||||
|
|
|
@ -0,0 +1,210 @@
|
||||||
|
package org.apache.lucene.index;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.BitSet;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.apache.lucene.analysis.WhitespaceAnalyzer;
|
||||||
|
import org.apache.lucene.document.Document;
|
||||||
|
import org.apache.lucene.document.Field;
|
||||||
|
import org.apache.lucene.index.IndexWriter.MaxFieldLength;
|
||||||
|
import org.apache.lucene.store.Directory;
|
||||||
|
import org.apache.lucene.store.MockRAMDirectory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test class to illustrate using IndexDeletionPolicy to provide multi-level rollback capability.
|
||||||
|
* This test case creates an index of records 1 to 100, introducing a commit point every 10 records.
|
||||||
|
*
|
||||||
|
* A "keep all" deletion policy is used to ensure we keep all commit points for testing purposes
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class TestTransactionRollback extends TestCase {
|
||||||
|
|
||||||
|
private static final String FIELD_RECORD_ID = "record_id";
|
||||||
|
private Directory dir;
|
||||||
|
|
||||||
|
|
||||||
|
//Rolls back index to a chosen ID
|
||||||
|
private void rollBackLast(int id) throws Exception {
|
||||||
|
|
||||||
|
// System.out.println("Attempting to rollback to "+id);
|
||||||
|
String ids="-"+id;
|
||||||
|
IndexCommit last=null;
|
||||||
|
Collection commits = IndexReader.listCommits(dir);
|
||||||
|
for (Iterator iterator = commits.iterator(); iterator.hasNext();) {
|
||||||
|
IndexCommit commit = (IndexCommit) iterator.next();
|
||||||
|
String ud=commit.getUserData();
|
||||||
|
if (ud != null)
|
||||||
|
if (ud.endsWith(ids))
|
||||||
|
last=commit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (last==null)
|
||||||
|
throw new RuntimeException("Couldn't find commit point "+id);
|
||||||
|
|
||||||
|
IndexWriter w = new IndexWriter(dir, new WhitespaceAnalyzer(),
|
||||||
|
new RollbackDeletionPolicy(id), MaxFieldLength.UNLIMITED, last);
|
||||||
|
w.commit("Rolled back to 1-"+id);
|
||||||
|
w.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRepeatedRollBacks() throws Exception {
|
||||||
|
|
||||||
|
int expectedLastRecordId=100;
|
||||||
|
while (expectedLastRecordId>10) {
|
||||||
|
expectedLastRecordId -=10;
|
||||||
|
rollBackLast(expectedLastRecordId);
|
||||||
|
|
||||||
|
BitSet expecteds = new BitSet(100);
|
||||||
|
expecteds.set(1,(expectedLastRecordId+1),true);
|
||||||
|
checkExpecteds(expecteds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkExpecteds(BitSet expecteds) throws Exception {
|
||||||
|
IndexReader r = IndexReader.open(dir);
|
||||||
|
|
||||||
|
//Perhaps not the most efficient approach but meets our needs here.
|
||||||
|
for (int i = 0; i < r.maxDoc(); i++) {
|
||||||
|
if(!r.isDeleted(i)) {
|
||||||
|
String sval=r.document(i).get(FIELD_RECORD_ID);
|
||||||
|
if(sval!=null) {
|
||||||
|
int val=Integer.parseInt(sval);
|
||||||
|
assertTrue("Did not expect document #"+val, expecteds.get(val));
|
||||||
|
expecteds.set(val,false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r.close();
|
||||||
|
assertEquals("Should have 0 docs remaining ", 0 ,expecteds.cardinality());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showAvailableCommitPoints() throws Exception {
|
||||||
|
Collection commits = IndexReader.listCommits(dir);
|
||||||
|
for (Iterator iterator = commits.iterator(); iterator.hasNext();) {
|
||||||
|
IndexCommit comm = (IndexCommit) iterator.next();
|
||||||
|
System.out.print("\t Available commit point:["+comm.getUserData()+"] files=");
|
||||||
|
Collection files = comm.getFileNames();
|
||||||
|
for (Iterator iterator2 = files.iterator(); iterator2.hasNext();) {
|
||||||
|
String filename = (String) iterator2.next();
|
||||||
|
System.out.print(filename+", ");
|
||||||
|
}
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
dir = new MockRAMDirectory();
|
||||||
|
// dir=FSDirectory.getDirectory("/indexes/testDeletionPolicy");
|
||||||
|
// String[] files = dir.list();
|
||||||
|
// for (String string : files) {
|
||||||
|
// dir.deleteFile(string);
|
||||||
|
// }
|
||||||
|
|
||||||
|
//Build index, of records 1 to 100, committing after each batch of 10
|
||||||
|
IndexDeletionPolicy sdp=new KeepAllDeletionPolicy();
|
||||||
|
IndexWriter w=new IndexWriter(dir,new WhitespaceAnalyzer(),sdp,MaxFieldLength.UNLIMITED);
|
||||||
|
int firstRecordIdInThisTransaction=1;
|
||||||
|
for(int currentRecordId=1;currentRecordId<=100;currentRecordId++) {
|
||||||
|
Document doc=new Document();
|
||||||
|
doc.add(new Field(FIELD_RECORD_ID,""+currentRecordId,Field.Store.YES,Field.Index.ANALYZED));
|
||||||
|
w.addDocument(doc);
|
||||||
|
|
||||||
|
if (currentRecordId%10 == 0) {
|
||||||
|
String userData="records 1-"+currentRecordId;
|
||||||
|
w.commit(userData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
w.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rolls back to previous commit point
|
||||||
|
class RollbackDeletionPolicy implements IndexDeletionPolicy {
|
||||||
|
private int rollbackPoint;
|
||||||
|
|
||||||
|
public RollbackDeletionPolicy(int rollbackPoint) {
|
||||||
|
this.rollbackPoint = rollbackPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onCommit(List commits) throws IOException {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onInit(List commits) throws IOException {
|
||||||
|
for (Iterator iterator = commits.iterator(); iterator.hasNext();) {
|
||||||
|
IndexCommit commit = (IndexCommit) iterator.next();
|
||||||
|
String userData=commit.getUserData();
|
||||||
|
if (userData != null) {
|
||||||
|
// Label for a commit point is "Records 1-30"
|
||||||
|
// This code reads the last id ("30" in this example) and deletes it
|
||||||
|
// if it is after the desired rollback point
|
||||||
|
String lastVal = userData.substring(userData.lastIndexOf("-")+1);
|
||||||
|
int last = Integer.parseInt(lastVal);
|
||||||
|
if (last>rollbackPoint) {
|
||||||
|
/*
|
||||||
|
System.out.print("\tRolling back commit point:" +
|
||||||
|
" UserData="+commit.getUserData() +") ("+(commits.size()-1)+" commit points left) files=");
|
||||||
|
Collection files = commit.getFileNames();
|
||||||
|
for (Iterator iterator2 = files.iterator(); iterator2.hasNext();) {
|
||||||
|
System.out.print(" "+iterator2.next());
|
||||||
|
}
|
||||||
|
System.out.println();
|
||||||
|
*/
|
||||||
|
|
||||||
|
commit.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DeleteLastCommitPolicy implements IndexDeletionPolicy {
|
||||||
|
|
||||||
|
public void onCommit(List commits) throws IOException {}
|
||||||
|
|
||||||
|
public void onInit(List commits) throws IOException {
|
||||||
|
((IndexCommit) commits.get(commits.size()-1)).delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRollbackDeletionPolicy() throws Exception {
|
||||||
|
for(int i=0;i<2;i++) {
|
||||||
|
// Unless you specify a prior commit point, rollback
|
||||||
|
// should not work:
|
||||||
|
new IndexWriter(dir,new WhitespaceAnalyzer(),
|
||||||
|
new DeleteLastCommitPolicy(),
|
||||||
|
MaxFieldLength.UNLIMITED).close();
|
||||||
|
IndexReader r = IndexReader.open(dir);
|
||||||
|
assertEquals(100, r.numDocs());
|
||||||
|
r.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keeps all commit points (used to build index)
|
||||||
|
class KeepAllDeletionPolicy implements IndexDeletionPolicy {
|
||||||
|
public void onCommit(List commits) throws IOException {}
|
||||||
|
public void onInit(List commits) throws IOException {}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue