blob: 83755345c0d77c4f2a47e4a9ac31576dbd191835 [file] [log] [blame]
/*
* Copyright 1999-2011 Alibaba Group.
*
* 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.
*/
package com.alibaba.dubbo.remoting.p2p.exchange.support;
import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.utils.IOUtils;
import com.alibaba.dubbo.common.utils.NamedThreadFactory;
import com.alibaba.dubbo.common.utils.NetUtils;
import com.alibaba.dubbo.remoting.RemotingException;
import com.alibaba.dubbo.remoting.exchange.ExchangeHandler;
import com.alibaba.dubbo.remoting.p2p.exchange.ExchangePeer;
/**
* FileGroup
*
* @author william.liangf
*/
public class FileExchangeGroup extends AbstractExchangeGroup {
private final File file;
private volatile long last;
// 定时任务执行器
private final ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3, new NamedThreadFactory("FileGroupModifiedChecker", true));
// 重连定时器,定时检查连接是否可用,不可用时,无限次重连
private final ScheduledFuture<?> checkModifiedFuture;
public FileExchangeGroup(URL url){
super(url);
String path = url.getHost() + "/" + url.getPath();
file = new File(path);
if (! file.exists()) {
throw new IllegalStateException("The group file not exists. file: " + path);
}
checkModifiedFuture = scheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
public void run() {
// 检测文件变更
try {
check();
} catch (Throwable t) { // 防御性容错
logger.error("Unexpected error occur at reconnect, cause: " + t.getMessage(), t);
}
}
}, 2000, 2000, TimeUnit.MILLISECONDS);
}
public void close() {
super.close();
try {
if (! checkModifiedFuture.isCancelled()) {
checkModifiedFuture.cancel(true);
}
} catch (Throwable t) {
logger.error(t.getMessage(), t);
}
}
private void check() throws RemotingException {
long modified = file.lastModified();
if (modified > last) {
last = modified;
changed();
}
}
private void changed() throws RemotingException {
try {
String[] lines = IOUtils.readLines(file);
for (String line : lines) {
connect(URL.valueOf(line));
}
} catch (IOException e) {
throw new RemotingException(new InetSocketAddress(NetUtils.getLocalHost(), 0), getUrl().toInetSocketAddress(), e.getMessage(), e);
}
}
public ExchangePeer joinExchange(URL url, ExchangeHandler handler) throws RemotingException {
ExchangePeer peer = super.join(url, handler);
try {
String full = url.toFullString();
String[] lines = IOUtils.readLines(file);
for (String line : lines) {
if (full.equals(line)) {
return peer;
}
}
IOUtils.appendLines(file, new String[] {full});
} catch (IOException e) {
throw new RemotingException(new InetSocketAddress(NetUtils.getLocalHost(), 0), getUrl().toInetSocketAddress(), e.getMessage(), e);
}
return peer;
}
@Override
public void leave(URL url) throws RemotingException {
super.leave(url);
try {
String full = url.toFullString();
String[] lines = IOUtils.readLines(file);
List<String> saves = new ArrayList<String>();
for (String line : lines) {
if (full.equals(line)) {
return;
}
saves.add(line);
}
IOUtils.appendLines(file, saves.toArray(new String[0]));
} catch (IOException e) {
throw new RemotingException(new InetSocketAddress(NetUtils.getLocalHost(), 0), getUrl().toInetSocketAddress(), e.getMessage(), e);
}
}
}