|
@@ -26,7 +26,7 @@ import com.alibaba.csp.sentinel.log.RecordLog; |
|
|
/** |
|
|
/** |
|
|
* <p> |
|
|
* <p> |
|
|
* A {@link ReadableDataSource} based on file. This class will automatically |
|
|
* A {@link ReadableDataSource} based on file. This class will automatically |
|
|
* fetches the backend file every refresh period. |
|
|
|
|
|
|
|
|
* fetches the backend file every isModified period. |
|
|
* </p> |
|
|
* </p> |
|
|
* <p> |
|
|
* <p> |
|
|
* Limitations: Default read buffer size is 1 MB. If file size is greater than |
|
|
* Limitations: Default read buffer size is 1 MB. If file size is greater than |
|
@@ -46,16 +46,15 @@ public class FileRefreshableDataSource<T> extends AutoRefreshDataSource<String, |
|
|
private byte[] buf; |
|
|
private byte[] buf; |
|
|
private final Charset charset; |
|
|
private final Charset charset; |
|
|
private final File file; |
|
|
private final File file; |
|
|
|
|
|
|
|
|
private long lastModified = 0L; |
|
|
private long lastModified = 0L; |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Create a file based {@link ReadableDataSource} whose read buffer size is |
|
|
* Create a file based {@link ReadableDataSource} whose read buffer size is |
|
|
* 1MB, charset is UTF8, and read interval is 3 seconds. |
|
|
* 1MB, charset is UTF8, and read interval is 3 seconds. |
|
|
* |
|
|
* |
|
|
* @param file |
|
|
|
|
|
* the file to read |
|
|
|
|
|
* @param configParser |
|
|
|
|
|
* the config decoder (parser) |
|
|
|
|
|
|
|
|
* @param file the file to read |
|
|
|
|
|
* @param configParser the config decoder (parser) |
|
|
*/ |
|
|
*/ |
|
|
public FileRefreshableDataSource(File file, Converter<String, T> configParser) throws FileNotFoundException { |
|
|
public FileRefreshableDataSource(File file, Converter<String, T> configParser) throws FileNotFoundException { |
|
|
this(file, configParser, DEFAULT_REFRESH_MS, DEFAULT_BUF_SIZE, DEFAULT_CHAR_SET); |
|
|
this(file, configParser, DEFAULT_REFRESH_MS, DEFAULT_BUF_SIZE, DEFAULT_CHAR_SET); |
|
@@ -66,23 +65,23 @@ public class FileRefreshableDataSource<T> extends AutoRefreshDataSource<String, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public FileRefreshableDataSource(File file, Converter<String, T> configParser, int bufSize) |
|
|
public FileRefreshableDataSource(File file, Converter<String, T> configParser, int bufSize) |
|
|
throws FileNotFoundException { |
|
|
|
|
|
|
|
|
throws FileNotFoundException { |
|
|
this(file, configParser, DEFAULT_REFRESH_MS, bufSize, DEFAULT_CHAR_SET); |
|
|
this(file, configParser, DEFAULT_REFRESH_MS, bufSize, DEFAULT_CHAR_SET); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public FileRefreshableDataSource(File file, Converter<String, T> configParser, Charset charset) |
|
|
public FileRefreshableDataSource(File file, Converter<String, T> configParser, Charset charset) |
|
|
throws FileNotFoundException { |
|
|
|
|
|
|
|
|
throws FileNotFoundException { |
|
|
this(file, configParser, DEFAULT_REFRESH_MS, DEFAULT_BUF_SIZE, charset); |
|
|
this(file, configParser, DEFAULT_REFRESH_MS, DEFAULT_BUF_SIZE, charset); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public FileRefreshableDataSource(File file, Converter<String, T> configParser, long recommendRefreshMs, int bufSize, |
|
|
public FileRefreshableDataSource(File file, Converter<String, T> configParser, long recommendRefreshMs, int bufSize, |
|
|
Charset charset) throws FileNotFoundException { |
|
|
|
|
|
|
|
|
Charset charset) throws FileNotFoundException { |
|
|
super(configParser, recommendRefreshMs); |
|
|
super(configParser, recommendRefreshMs); |
|
|
if (bufSize <= 0 || bufSize > MAX_SIZE) { |
|
|
if (bufSize <= 0 || bufSize > MAX_SIZE) { |
|
|
throw new IllegalArgumentException("bufSize must between (0, " + MAX_SIZE + "], but " + bufSize + " get"); |
|
|
throw new IllegalArgumentException("bufSize must between (0, " + MAX_SIZE + "], but " + bufSize + " get"); |
|
|
} |
|
|
} |
|
|
if (file == null) { |
|
|
|
|
|
throw new IllegalArgumentException("file can't be null"); |
|
|
|
|
|
|
|
|
if (file == null || file.isDirectory()) { |
|
|
|
|
|
throw new IllegalArgumentException("File can't be null or a directory"); |
|
|
} |
|
|
} |
|
|
if (charset == null) { |
|
|
if (charset == null) { |
|
|
throw new IllegalArgumentException("charset can't be null"); |
|
|
throw new IllegalArgumentException("charset can't be null"); |
|
@@ -90,6 +89,7 @@ public class FileRefreshableDataSource<T> extends AutoRefreshDataSource<String, |
|
|
this.buf = new byte[bufSize]; |
|
|
this.buf = new byte[bufSize]; |
|
|
this.file = file; |
|
|
this.file = file; |
|
|
this.charset = charset; |
|
|
this.charset = charset; |
|
|
|
|
|
// If the file does not exist, the last modified will be 0. |
|
|
this.lastModified = file.lastModified(); |
|
|
this.lastModified = file.lastModified(); |
|
|
firstLoad(); |
|
|
firstLoad(); |
|
|
} |
|
|
} |
|
@@ -105,13 +105,17 @@ public class FileRefreshableDataSource<T> extends AutoRefreshDataSource<String, |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
public String readSource() throws Exception { |
|
|
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; |
|
|
FileInputStream inputStream = null; |
|
|
try { |
|
|
try { |
|
|
inputStream = new FileInputStream(file); |
|
|
inputStream = new FileInputStream(file); |
|
|
FileChannel channel = inputStream.getChannel(); |
|
|
FileChannel channel = inputStream.getChannel(); |
|
|
if (channel.size() > buf.length) { |
|
|
if (channel.size() > buf.length) { |
|
|
throw new IllegalStateException(file.getAbsolutePath() + " file size=" + channel.size() |
|
|
throw new IllegalStateException(file.getAbsolutePath() + " file size=" + channel.size() |
|
|
+ ", is bigger than bufSize=" + buf.length + ". Can't read"); |
|
|
|
|
|
|
|
|
+ ", is bigger than bufSize=" + buf.length + ". Can't read"); |
|
|
} |
|
|
} |
|
|
int len = inputStream.read(buf); |
|
|
int len = inputStream.read(buf); |
|
|
return new String(buf, 0, len, charset); |
|
|
return new String(buf, 0, len, charset); |
|
@@ -126,8 +130,8 @@ public class FileRefreshableDataSource<T> extends AutoRefreshDataSource<String, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
protected boolean refresh() { |
|
|
|
|
|
long curLastModified = new File(file.getAbsolutePath()).lastModified(); |
|
|
|
|
|
|
|
|
protected boolean isModified() { |
|
|
|
|
|
long curLastModified = file.lastModified(); |
|
|
if (curLastModified != this.lastModified) { |
|
|
if (curLastModified != this.lastModified) { |
|
|
this.lastModified = curLastModified; |
|
|
this.lastModified = curLastModified; |
|
|
return true; |
|
|
return true; |
|
|