/*
* (C) 2007-2012 Alibaba Group Holding Limited.
*
* Licensed 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.
* Authors:
* wuhua <wq163@163.com> , boyan <killme2008@gmail.com>
*/
package com.taobao.metamorphosis.client.consumer.storage;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import javax.sql.DataSource;
import com.taobao.metamorphosis.client.consumer.TopicPartitionRegInfo;
import com.taobao.metamorphosis.cluster.Partition;
/**
* ����mysql���ݿ��offset�洢��
*
* @author boyan
* @Date 2011-4-28
*
*/
// TODO ʵ���Զ�����
public class MysqlOffsetStorage implements OffsetStorage {
public static final String DEFAULT_TABLE_NAME = "meta_topic_partition_group_offset";
private DataSource dataSource;
private String tableName = DEFAULT_TABLE_NAME;
/**
* offset����ı���
*
* @return
*/
public String getTableName() {
return this.tableName;
}
/**
* ���ñ�����Ĭ��Ϊmeta_topic_partiton_group_offset
*
* @param tableName
*/
public void setTableName(final String tableName) {
this.tableName = tableName;
}
public MysqlOffsetStorage(final DataSource dataSource) {
super();
this.dataSource = dataSource;
}
@Override
public void commitOffset(final String group, final Collection<TopicPartitionRegInfo> infoList) {
if (infoList == null || infoList.isEmpty()) {
return;
}
final Connection conn = JDBCUtils.getConnection(this.dataSource);
JDBCUtils.execute(conn, new JDBCUtils.ConnectionCallback() {
@Override
public Object doInConnection(final Connection conn) throws SQLException {
final String updateSQL =
"update " + MysqlOffsetStorage.this.tableName
+ " set offset=?,msg_id=? where topic=? and partition=? and group_id=?";
final PreparedStatement preparedStatement = conn.prepareStatement(updateSQL);
JDBCUtils.execute(preparedStatement, new JDBCUtils.PreparedStatementCallback() {
@Override
public Object doInPreparedStatement(final PreparedStatement pstmt) throws SQLException {
for (final TopicPartitionRegInfo info : infoList) {
long newOffset = -1;
long msgId = -1;
// ��������֤msgId��offsetһ��
synchronized (info) {
// ֻ�����б����
if (!info.isModified()) {
continue;
}
newOffset = info.getOffset().get();
msgId = info.getMessageId();
// ������ϣ�����Ϊfalse
info.setModified(false);
}
pstmt.setLong(1, newOffset);
pstmt.setLong(2, msgId);
pstmt.setString(3, info.getTopic());
pstmt.setString(4, info.getPartition().toString());
pstmt.setString(5, group);
pstmt.addBatch();
}
pstmt.executeBatch();
return null;
}
});
return null;
}
});
}
@Override
public void close() {
this.dataSource = null;
}
@Override
public void initOffset(final String topic, final String group, final Partition partition, final long offset) {
final Connection conn = JDBCUtils.getConnection(this.dataSource);
JDBCUtils.execute(conn, new JDBCUtils.ConnectionCallback() {
@Override
public Object doInConnection(final Connection conn) throws SQLException {
final String insertSQL =
"insert into " + MysqlOffsetStorage.this.tableName
+ " (topic,partition,group_id,offset,msg_id) values(?,?,?,?,?)";
final PreparedStatement preparedStatement = conn.prepareStatement(insertSQL);
JDBCUtils.execute(preparedStatement, new JDBCUtils.PreparedStatementCallback() {
@Override
public Object doInPreparedStatement(final PreparedStatement pstmt) throws SQLException {
pstmt.setString(1, topic);
pstmt.setString(2, partition.toString());
pstmt.setString(3, group);
pstmt.setLong(4, offset);
pstmt.setLong(5, -1L);
pstmt.executeUpdate();
return null;
}
});
return null;
}
});
}
@Override
public TopicPartitionRegInfo load(final String topic, final String group, final Partition partition) {
final Connection conn = JDBCUtils.getConnection(this.dataSource);
return (TopicPartitionRegInfo) JDBCUtils.execute(conn, new JDBCUtils.ConnectionCallback() {
@Override
public Object doInConnection(final Connection conn) throws SQLException {
final String selectSQL =
"select offset,msg_id from " + MysqlOffsetStorage.this.tableName
+ " where topic=? and partition=? and group_id=?";
final PreparedStatement preparedStatement = conn.prepareStatement(selectSQL);
return JDBCUtils.execute(preparedStatement, new JDBCUtils.PreparedStatementCallback() {
@Override
public Object doInPreparedStatement(final PreparedStatement pstmt) throws SQLException {
pstmt.setString(1, topic);
pstmt.setString(2, partition.toString());
pstmt.setString(3, group);
final ResultSet rs = pstmt.executeQuery();
return JDBCUtils.execute(rs, new JDBCUtils.ResultSetCallback() {
@Override
public Object doInResultSet(final ResultSet rs) throws SQLException {
if (rs.next()) {
final long offset = rs.getLong(1);
final long msgId = rs.getLong(2);
return new TopicPartitionRegInfo(topic, partition, offset, msgId);
}
else {
return null;
}
}
});
}
});
}
});
}
}