001: /*
002: * Copyright 2004-2006 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.apache.lucene.store.jdbc.lock;
018:
019: import java.io.IOException;
020: import java.sql.PreparedStatement;
021: import java.sql.ResultSet;
022: import java.sql.Types;
023:
024: import org.apache.lucene.index.IndexWriter;
025: import org.apache.lucene.store.Lock;
026: import org.apache.lucene.store.jdbc.JdbcDirectory;
027: import org.apache.lucene.store.jdbc.JdbcStoreException;
028: import org.apache.lucene.store.jdbc.support.JdbcTemplate;
029:
030: /**
031: * A lock based on select...for update.
032: * <p/>
033: * Note, that not all databases support select ... for update, if the database (dialect) does not support it,
034: * a exception will be thrown (see {@link org.apache.lucene.store.jdbc.dialect.Dialect#supportsForUpdate()} .
035: * <p/>
036: * Also note, that when using select for update locking, when the database is created, the commit and write
037: * locks will be created and the select for update will be performed on them. If one wishes to switch to
038: * {@link PhantomReadLock}, they must be manually deleted.
039: * <p/>
040: * The lock is released when the transaction is committed, and not when the release method is called.
041:
042: * @author kimchy
043: */
044: public class SelectForUpdateLock extends Lock implements JdbcLock {
045:
046: private JdbcDirectory jdbcDirectory;
047:
048: private String name;
049:
050: public void configure(JdbcDirectory jdbcDirectory, String name)
051: throws IOException {
052: if (!jdbcDirectory.getDialect().supportsForUpdate()) {
053: throw new JdbcStoreException("Database dialect ["
054: + jdbcDirectory.getDialect()
055: + "] does not support select for update");
056: }
057: this .jdbcDirectory = jdbcDirectory;
058: this .name = name;
059: }
060:
061: public void initializeDatabase(JdbcDirectory jdbcDirectory)
062: throws IOException {
063: jdbcDirectory.getJdbcTemplate().executeUpdate(
064: jdbcDirectory.getTable().sqlInsert(),
065: new JdbcTemplate.PrepateStatementAwareCallback() {
066: public void fillPrepareStatement(
067: PreparedStatement ps) throws Exception {
068: ps.setFetchSize(1);
069: ps.setString(1, IndexWriter.WRITE_LOCK_NAME);
070: ps.setNull(2, Types.BLOB);
071: ps.setLong(3, 0);
072: ps.setBoolean(4, false);
073: }
074: });
075: }
076:
077: public boolean obtain() {
078: try {
079: return ((Boolean) jdbcDirectory.getJdbcTemplate()
080: .executeSelect(
081: jdbcDirectory.getTable()
082: .sqlSelectNameForUpdateNoWait(),
083: new JdbcTemplate.ExecuteSelectCallback() {
084:
085: public void fillPrepareStatement(
086: PreparedStatement ps)
087: throws Exception {
088: ps.setFetchSize(1);
089: ps.setString(1, name);
090: }
091:
092: public Object execute(ResultSet rs)
093: throws Exception {
094: if (!rs.next()) {
095: System.err
096: .println("Should not happen, the lock ["
097: + name
098: + "] should already exists");
099: return Boolean.FALSE;
100: }
101: return Boolean.TRUE;
102: }
103: })).booleanValue();
104: } catch (Exception e) {
105: return false;
106: }
107: }
108:
109: public void release() {
110: // no way to activly release a select for update lock
111: // when the transaction commits or rolls back, it will be released
112: }
113:
114: public boolean isLocked() {
115: // no way to know if it is locked or not
116: throw new IllegalStateException(
117: "SelectForUpdate lock does not support is locked");
118: }
119:
120: public String toString() {
121: return "SelectForUpdateLock[" + name + "/"
122: + jdbcDirectory.getTable() + "]";
123: }
124:
125: }
|