init
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>com.alibaba.csp</groupId>
|
||||
<artifactId>sentinel-extension</artifactId>
|
||||
<version>1.8.3</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>sentinel-datasource-extension</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.csp</groupId>
|
||||
<artifactId>sentinel-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* 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.csp.sentinel.datasource;
|
||||
|
||||
import com.alibaba.csp.sentinel.property.DynamicSentinelProperty;
|
||||
import com.alibaba.csp.sentinel.property.SentinelProperty;
|
||||
|
||||
/**
|
||||
* The abstract readable data source provides basic functionality for loading and parsing config.
|
||||
*
|
||||
* @param <S> source data type
|
||||
* @param <T> target data type
|
||||
* @author Carpenter Lee
|
||||
* @author Eric Zhao
|
||||
*/
|
||||
public abstract class AbstractDataSource<S, T> implements ReadableDataSource<S, T> {
|
||||
|
||||
protected final Converter<S, T> parser;
|
||||
protected final SentinelProperty<T> property;
|
||||
|
||||
public AbstractDataSource(Converter<S, T> parser) {
|
||||
if (parser == null) {
|
||||
throw new IllegalArgumentException("parser can't be null");
|
||||
}
|
||||
this.parser = parser;
|
||||
this.property = new DynamicSentinelProperty<T>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T loadConfig() throws Exception {
|
||||
return loadConfig(readSource());
|
||||
}
|
||||
|
||||
public T loadConfig(S conf) throws Exception {
|
||||
T value = parser.convert(conf);
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SentinelProperty<T> getProperty() {
|
||||
return property;
|
||||
}
|
||||
}
|
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* 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.csp.sentinel.datasource;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.alibaba.csp.sentinel.concurrent.NamedThreadFactory;
|
||||
import com.alibaba.csp.sentinel.log.RecordLog;
|
||||
|
||||
/**
|
||||
* A {@link ReadableDataSource} automatically fetches the backend data.
|
||||
*
|
||||
* @param <S> source data type
|
||||
* @param <T> target data type
|
||||
* @author Carpenter Lee
|
||||
*/
|
||||
public abstract class AutoRefreshDataSource<S, T> extends AbstractDataSource<S, T> {
|
||||
|
||||
private ScheduledExecutorService service;
|
||||
protected long recommendRefreshMs = 3000;
|
||||
|
||||
public AutoRefreshDataSource(Converter<S, T> configParser) {
|
||||
super(configParser);
|
||||
startTimerService();
|
||||
}
|
||||
|
||||
public AutoRefreshDataSource(Converter<S, T> configParser, final long recommendRefreshMs) {
|
||||
super(configParser);
|
||||
if (recommendRefreshMs <= 0) {
|
||||
throw new IllegalArgumentException("recommendRefreshMs must > 0, but " + recommendRefreshMs + " get");
|
||||
}
|
||||
this.recommendRefreshMs = recommendRefreshMs;
|
||||
startTimerService();
|
||||
}
|
||||
|
||||
@SuppressWarnings("PMD.ThreadPoolCreationRule")
|
||||
private void startTimerService() {
|
||||
service = Executors.newScheduledThreadPool(1,
|
||||
new NamedThreadFactory("sentinel-datasource-auto-refresh-task", true));
|
||||
service.scheduleAtFixedRate(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if (!isModified()) {
|
||||
return;
|
||||
}
|
||||
T newValue = loadConfig();
|
||||
getProperty().updateValue(newValue);
|
||||
} catch (Throwable e) {
|
||||
RecordLog.info("loadConfig exception", e);
|
||||
}
|
||||
}
|
||||
}, recommendRefreshMs, recommendRefreshMs, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
if (service != null) {
|
||||
service.shutdownNow();
|
||||
service = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isModified() {
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* 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.csp.sentinel.datasource;
|
||||
|
||||
/**
|
||||
* Convert an object from source type {@code S} to target type {@code T}.
|
||||
*
|
||||
* @author leyou
|
||||
* @author Eric Zhao
|
||||
*/
|
||||
public interface Converter<S, T> {
|
||||
|
||||
/**
|
||||
* Convert {@code source} to the target type.
|
||||
*
|
||||
* @param source the source object
|
||||
* @return the target object
|
||||
*/
|
||||
T convert(S source);
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* 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.csp.sentinel.datasource;
|
||||
|
||||
import com.alibaba.csp.sentinel.property.NoOpSentinelProperty;
|
||||
import com.alibaba.csp.sentinel.property.SentinelProperty;
|
||||
|
||||
/**
|
||||
* A {@link ReadableDataSource} based on nothing. {@link EmptyDataSource#getProperty()} will always return the same cached
|
||||
* {@link SentinelProperty} that doing nothing.
|
||||
* <br/>
|
||||
* This class is used when we want to use default settings instead of configs from the {@link ReadableDataSource}.
|
||||
*
|
||||
* @author leyou
|
||||
*/
|
||||
public final class EmptyDataSource implements ReadableDataSource<Object, Object> {
|
||||
|
||||
public static final ReadableDataSource<Object, Object> EMPTY_DATASOURCE = new EmptyDataSource();
|
||||
|
||||
private static final SentinelProperty<Object> PROPERTY = new NoOpSentinelProperty();
|
||||
|
||||
private EmptyDataSource() { }
|
||||
|
||||
@Override
|
||||
public Object loadConfig() throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object readSource() throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SentinelProperty<Object> getProperty() {
|
||||
return PROPERTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception { }
|
||||
}
|
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* 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.csp.sentinel.datasource;
|
||||
|
||||
import com.alibaba.csp.sentinel.log.RecordLog;
|
||||
import com.alibaba.csp.sentinel.util.AssertUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A {@link ReadableDataSource} based on jar file. This class can only read file initially when it loads file.
|
||||
* </p>
|
||||
* <p>
|
||||
* Limitations: Default read buffer size is 1 MB, while max allowed buffer size is 4MB.
|
||||
* File size should not exceed the buffer size, or exception will be thrown. Default charset is UTF-8.
|
||||
* </p>
|
||||
*
|
||||
* @author dingq
|
||||
* @author Eric Zhao
|
||||
* @since 1.6.0
|
||||
*/
|
||||
public class FileInJarReadableDataSource<T> extends AbstractDataSource<String, T> {
|
||||
|
||||
private static final int MAX_SIZE = 1024 * 1024 * 4;
|
||||
private static final int DEFAULT_BUF_SIZE = 1024 * 1024;
|
||||
private static final Charset DEFAULT_CHARSET = Charset.forName("utf-8");
|
||||
|
||||
private final Charset charset;
|
||||
private final String jarName;
|
||||
private final String fileInJarName;
|
||||
|
||||
private byte[] buf;
|
||||
private JarEntry jarEntry;
|
||||
private JarFile jarFile;
|
||||
|
||||
/**
|
||||
* @param jarName the jar to read
|
||||
* @param fileInJarName the file in jar to read
|
||||
* @param configParser the config decoder (parser)
|
||||
* @throws IOException if IO failure occurs
|
||||
*/
|
||||
public FileInJarReadableDataSource(String jarName, String fileInJarName, Converter<String, T> configParser)
|
||||
throws IOException {
|
||||
this(jarName, fileInJarName, configParser, DEFAULT_BUF_SIZE, DEFAULT_CHARSET);
|
||||
}
|
||||
|
||||
public FileInJarReadableDataSource(String jarName, String fileInJarName, Converter<String, T> configParser,
|
||||
int bufSize) throws IOException {
|
||||
this(jarName, fileInJarName, configParser, bufSize, DEFAULT_CHARSET);
|
||||
}
|
||||
|
||||
public FileInJarReadableDataSource(String jarName, String fileInJarName, Converter<String, T> configParser,
|
||||
Charset charset) throws IOException {
|
||||
this(jarName, fileInJarName, configParser, DEFAULT_BUF_SIZE, charset);
|
||||
}
|
||||
|
||||
public FileInJarReadableDataSource(String jarName, String fileInJarName, Converter<String, T> configParser,
|
||||
int bufSize, Charset charset) throws IOException {
|
||||
super(configParser);
|
||||
AssertUtil.assertNotBlank(jarName, "jarName cannot be blank");
|
||||
AssertUtil.assertNotBlank(fileInJarName, "fileInJarName cannot be blank");
|
||||
if (bufSize <= 0 || bufSize > MAX_SIZE) {
|
||||
throw new IllegalArgumentException("bufSize must between (0, " + MAX_SIZE + "], but " + bufSize + " get");
|
||||
}
|
||||
AssertUtil.notNull(charset, "charset can't be null");
|
||||
this.buf = new byte[bufSize];
|
||||
this.charset = charset;
|
||||
this.jarName = jarName;
|
||||
this.fileInJarName = fileInJarName;
|
||||
initializeJar();
|
||||
firstLoad();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readSource() throws Exception {
|
||||
if (null == jarEntry) {
|
||||
// Will throw FileNotFoundException later.
|
||||
RecordLog.warn(String.format("[FileInJarReadableDataSource] File does not exist: %s", jarFile.getName()));
|
||||
}
|
||||
try (InputStream inputStream = jarFile.getInputStream(jarEntry)) {
|
||||
if (inputStream.available() > buf.length) {
|
||||
throw new IllegalStateException(String.format("Size of file <%s> exceeds the bufSize (%d): %d",
|
||||
jarFile.getName(), buf.length, inputStream.available()));
|
||||
}
|
||||
int len = inputStream.read(buf);
|
||||
return new String(buf, 0, len, charset);
|
||||
}
|
||||
}
|
||||
|
||||
private void firstLoad() {
|
||||
try {
|
||||
T newValue = loadConfig();
|
||||
getProperty().updateValue(newValue);
|
||||
} catch (Throwable e) {
|
||||
RecordLog.warn("[FileInJarReadableDataSource] Error when loading config", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
buf = null;
|
||||
}
|
||||
|
||||
private void initializeJar() throws IOException {
|
||||
this.jarFile = new JarFile(jarName);
|
||||
this.jarEntry = jarFile.getJarEntry(fileInJarName);
|
||||
}
|
||||
}
|
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* 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.csp.sentinel.datasource;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import com.alibaba.csp.sentinel.log.RecordLog;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A {@link ReadableDataSource} based on file. This class will automatically
|
||||
* fetches the backend file every isModified period.
|
||||
* </p>
|
||||
* <p>
|
||||
* Limitations: Default read buffer size is 1 MB. If file size is greater than
|
||||
* buffer size, exceeding bytes will be ignored. Default charset is UTF-8.
|
||||
* </p>
|
||||
*
|
||||
* @author Carpenter Lee
|
||||
* @author Eric Zhao
|
||||
*/
|
||||
public class FileRefreshableDataSource<T> extends AutoRefreshDataSource<String, T> {
|
||||
|
||||
private static final int MAX_SIZE = 1024 * 1024 * 4;
|
||||
private static final long DEFAULT_REFRESH_MS = 3000;
|
||||
private static final int DEFAULT_BUF_SIZE = 1024 * 1024;
|
||||
private static final Charset DEFAULT_CHAR_SET = Charset.forName("utf-8");
|
||||
|
||||
private byte[] buf;
|
||||
private final Charset charset;
|
||||
private final File file;
|
||||
|
||||
private long lastModified = 0L;
|
||||
|
||||
/**
|
||||
* Create a file based {@link ReadableDataSource} whose read buffer size is
|
||||
* 1MB, charset is UTF8, and read interval is 3 seconds.
|
||||
*
|
||||
* @param file the file to read
|
||||
* @param configParser the config decoder (parser)
|
||||
*/
|
||||
public FileRefreshableDataSource(File file, Converter<String, T> configParser) throws FileNotFoundException {
|
||||
this(file, configParser, DEFAULT_REFRESH_MS, DEFAULT_BUF_SIZE, DEFAULT_CHAR_SET);
|
||||
}
|
||||
|
||||
public FileRefreshableDataSource(String fileName, Converter<String, T> configParser) throws FileNotFoundException {
|
||||
this(new File(fileName), configParser, DEFAULT_REFRESH_MS, DEFAULT_BUF_SIZE, DEFAULT_CHAR_SET);
|
||||
}
|
||||
|
||||
public FileRefreshableDataSource(File file, Converter<String, T> configParser, int bufSize)
|
||||
throws FileNotFoundException {
|
||||
this(file, configParser, DEFAULT_REFRESH_MS, bufSize, DEFAULT_CHAR_SET);
|
||||
}
|
||||
|
||||
public FileRefreshableDataSource(File file, Converter<String, T> configParser, Charset charset)
|
||||
throws FileNotFoundException {
|
||||
this(file, configParser, DEFAULT_REFRESH_MS, DEFAULT_BUF_SIZE, charset);
|
||||
}
|
||||
|
||||
public FileRefreshableDataSource(File file, Converter<String, T> configParser, long recommendRefreshMs, int bufSize,
|
||||
Charset charset) throws FileNotFoundException {
|
||||
super(configParser, recommendRefreshMs);
|
||||
if (bufSize <= 0 || bufSize > MAX_SIZE) {
|
||||
throw new IllegalArgumentException("bufSize must between (0, " + MAX_SIZE + "], but " + bufSize + " get");
|
||||
}
|
||||
if (file == null || file.isDirectory()) {
|
||||
throw new IllegalArgumentException("File can't be null or a directory");
|
||||
}
|
||||
if (charset == null) {
|
||||
throw new IllegalArgumentException("charset can't be null");
|
||||
}
|
||||
this.buf = new byte[bufSize];
|
||||
this.file = file;
|
||||
this.charset = charset;
|
||||
// If the file does not exist, the last modified will be 0.
|
||||
this.lastModified = file.lastModified();
|
||||
firstLoad();
|
||||
}
|
||||
|
||||
private void firstLoad() {
|
||||
try {
|
||||
T newValue = loadConfig();
|
||||
getProperty().updateValue(newValue);
|
||||
} catch (Throwable e) {
|
||||
RecordLog.info("loadConfig exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readSource() throws Exception {
|
||||
if (!file.exists()) {
|
||||
// Will throw FileNotFoundException later.
|
||||
RecordLog.warn(String.format("[FileRefreshableDataSource] File does not exist: %s", file.getAbsolutePath()));
|
||||
}
|
||||
FileInputStream inputStream = null;
|
||||
try {
|
||||
inputStream = new FileInputStream(file);
|
||||
FileChannel channel = inputStream.getChannel();
|
||||
if (channel.size() > buf.length) {
|
||||
throw new IllegalStateException(file.getAbsolutePath() + " file size=" + channel.size()
|
||||
+ ", is bigger than bufSize=" + buf.length + ". Can't read");
|
||||
}
|
||||
int len = inputStream.read(buf);
|
||||
return new String(buf, 0, len, charset);
|
||||
} finally {
|
||||
if (inputStream != null) {
|
||||
try {
|
||||
inputStream.close();
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isModified() {
|
||||
long curLastModified = file.lastModified();
|
||||
if (curLastModified != this.lastModified) {
|
||||
this.lastModified = curLastModified;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
super.close();
|
||||
buf = null;
|
||||
}
|
||||
}
|
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* 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.csp.sentinel.datasource;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import com.alibaba.csp.sentinel.log.RecordLog;
|
||||
|
||||
/**
|
||||
* A {@link WritableDataSource} based on file.
|
||||
*
|
||||
* @param <T> data type
|
||||
* @author Eric Zhao
|
||||
* @since 0.2.0
|
||||
*/
|
||||
public class FileWritableDataSource<T> implements WritableDataSource<T> {
|
||||
|
||||
private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
|
||||
|
||||
private final Converter<T, String> configEncoder;
|
||||
private final File file;
|
||||
private final Charset charset;
|
||||
|
||||
private final Lock lock = new ReentrantLock(true);
|
||||
|
||||
public FileWritableDataSource(String filePath, Converter<T, String> configEncoder) {
|
||||
this(new File(filePath), configEncoder);
|
||||
}
|
||||
|
||||
public FileWritableDataSource(File file, Converter<T, String> configEncoder) {
|
||||
this(file, configEncoder, DEFAULT_CHARSET);
|
||||
}
|
||||
|
||||
public FileWritableDataSource(File file, Converter<T, String> configEncoder, Charset charset) {
|
||||
if (file == null || file.isDirectory()) {
|
||||
throw new IllegalArgumentException("Bad file");
|
||||
}
|
||||
if (configEncoder == null) {
|
||||
throw new IllegalArgumentException("Config encoder cannot be null");
|
||||
}
|
||||
if (charset == null) {
|
||||
throw new IllegalArgumentException("Charset cannot be null");
|
||||
}
|
||||
this.configEncoder = configEncoder;
|
||||
this.file = file;
|
||||
this.charset = charset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(T value) throws Exception {
|
||||
lock.lock();
|
||||
try {
|
||||
String convertResult = configEncoder.convert(value);
|
||||
FileOutputStream outputStream = null;
|
||||
try {
|
||||
outputStream = new FileOutputStream(file);
|
||||
byte[] bytesArray = convertResult.getBytes(charset);
|
||||
|
||||
RecordLog.info("[FileWritableDataSource] Writing to file {}: {}", file, convertResult);
|
||||
outputStream.write(bytesArray);
|
||||
outputStream.flush();
|
||||
} finally {
|
||||
if (outputStream != null) {
|
||||
try {
|
||||
outputStream.close();
|
||||
} catch (Exception ignore) {
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
// Nothing
|
||||
}
|
||||
}
|
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* 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.csp.sentinel.datasource;
|
||||
|
||||
import com.alibaba.csp.sentinel.property.SentinelProperty;
|
||||
|
||||
/**
|
||||
* The readable data source is responsible for retrieving configs (read-only).
|
||||
*
|
||||
* @param <S> source data type
|
||||
* @param <T> target data type
|
||||
* @author leyou
|
||||
* @author Eric Zhao
|
||||
*/
|
||||
public interface ReadableDataSource<S, T> {
|
||||
|
||||
/**
|
||||
* Load data data source as the target type.
|
||||
*
|
||||
* @return the target data.
|
||||
* @throws Exception IO or other error occurs
|
||||
*/
|
||||
T loadConfig() throws Exception;
|
||||
|
||||
/**
|
||||
* Read original data from the data source.
|
||||
*
|
||||
* @return the original data.
|
||||
* @throws Exception IO or other error occurs
|
||||
*/
|
||||
S readSource() throws Exception;
|
||||
|
||||
/**
|
||||
* Get {@link SentinelProperty} of the data source.
|
||||
*
|
||||
* @return the property.
|
||||
*/
|
||||
SentinelProperty<T> getProperty();
|
||||
|
||||
/**
|
||||
* Close the data source.
|
||||
*
|
||||
* @throws Exception IO or other error occurs
|
||||
*/
|
||||
void close() throws Exception;
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* 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.csp.sentinel.datasource;
|
||||
|
||||
/**
|
||||
* Interface of writable data source support.
|
||||
*
|
||||
* @author Eric Zhao
|
||||
* @since 0.2.0
|
||||
*/
|
||||
public interface WritableDataSource<T> {
|
||||
|
||||
/**
|
||||
* Write the {@code value} to the data source.
|
||||
*
|
||||
* @param value value to write
|
||||
* @throws Exception IO or other error occurs
|
||||
*/
|
||||
void write(T value) throws Exception;
|
||||
|
||||
/**
|
||||
* Close the data source.
|
||||
*
|
||||
* @throws Exception IO or other error occurs
|
||||
*/
|
||||
void close() throws Exception;
|
||||
}
|
Reference in New Issue
Block a user