Skip to content

Commit

Permalink
Enhance FileRefreshableDataSource and FileWritableDataSource (alibaba…
Browse files Browse the repository at this point in the history
…#125)

- Add method to check if the resource is modified in `AutoRefreshDataSource`
- Implement FileWritableDataSource
  • Loading branch information
yfh0918 authored and sczyh30 committed Sep 5, 2018
1 parent 408fe84 commit 4da45ee
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@
/**
* A {@link ReadableDataSource} automatically fetches the backend data.
*
* @param <S> source data type
* @param <T> target data type
* @param <S>
* source data type
* @param <T>
* target data type
* @author Carpenter Lee
*/
public abstract class AutoRefreshDataSource<S, T> extends AbstractDataSource<S, T> {
Expand All @@ -50,13 +52,15 @@ public AutoRefreshDataSource(Converter<S, T> configParser, final long recommendR

private void startTimerService() {
service = Executors.newScheduledThreadPool(1,
new NamedThreadFactory("sentinel-datasource-auto-refresh-task", true));
new NamedThreadFactory("sentinel-datasource-auto-refresh-task", true));
service.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
if (!refresh()) {
return;
}
T newValue = loadConfig();

getProperty().updateValue(newValue);
} catch (Throwable e) {
RecordLog.info("loadConfig exception", e);
Expand All @@ -72,4 +76,8 @@ public void close() throws Exception {
service = null;
}
}

protected boolean refresh() {
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@

/**
* <p>
* A {@link ReadableDataSource} based on file. This class will automatically fetches the backend file every refresh period.
* A {@link ReadableDataSource} based on file. This class will automatically
* fetches the backend file every refresh 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.
* 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
Expand All @@ -45,35 +46,37 @@ public class FileRefreshableDataSource<T> extends AutoRefreshDataSource<String,
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.
* 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)
* @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 {
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 {
throws FileNotFoundException {
this(file, configParser, DEFAULT_REFRESH_MS, bufSize, DEFAULT_CHAR_SET);
}

public FileRefreshableDataSource(File file, Converter<String, T> configParser, Charset charset)
throws FileNotFoundException {
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 {
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");
Expand All @@ -87,6 +90,7 @@ public FileRefreshableDataSource(File file, Converter<String, T> configParser, l
this.buf = new byte[bufSize];
this.file = file;
this.charset = charset;
this.lastModified = file.lastModified();
firstLoad();
}

Expand All @@ -107,7 +111,7 @@ public String readSource() throws Exception {
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");
+ ", is bigger than bufSize=" + buf.length + ". Can't read");
}
int len = inputStream.read(buf);
return new String(buf, 0, len, charset);
Expand All @@ -121,6 +125,16 @@ public String readSource() throws Exception {
}
}

@Override
protected boolean refresh() {
long curLastModified = new File(file.getAbsolutePath()).lastModified();
if (curLastModified != this.lastModified) {
this.lastModified = curLastModified;
return true;
}
return false;
}

@Override
public void close() throws Exception {
super.close();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@
package com.alibaba.csp.sentinel.datasource;

import java.io.File;
import java.io.FileOutputStream;

/**
* A {@link WritableDataSource} based on file.
*
* @param <T> data type
* @param <T>
* data type
* @author Eric Zhao
* @since 0.2.0
*/
Expand All @@ -46,7 +48,27 @@ public FileWritableDataSource(File file, Converter<T, String> configEncoder) {

@Override
public void write(T value) throws Exception {
throw new UnsupportedOperationException("Not implemented");
if (configEncoder == null) {
throw new NullPointerException("configEncoder is null Can't write");
}
synchronized (file) {
String convertResult = configEncoder.convert(value);
FileOutputStream outputStream = null;
try {
outputStream = new FileOutputStream(file);
byte[] bytesArray = convertResult.getBytes();
outputStream.write(bytesArray);
outputStream.flush();
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (Exception ignore) {
// nothing
}
}
}
}
}

@Override
Expand Down

0 comments on commit 4da45ee

Please sign in to comment.