dubbo FileCacheStore 源码
dubbo FileCacheStore 代码
文件路径:/dubbo-common/src/main/java/org/apache/dubbo/common/cache/FileCacheStore.java
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.dubbo.common.cache;
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.CollectionUtils;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.channels.FileLock;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_CACHE_MAX_ENTRY_COUNT_LIMIT_EXCEED;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_CACHE_MAX_FILE_SIZE_LIMIT_EXCEED;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_CACHE_PATH_INACCESSIBLE;
/**
* Local file interaction class that can back different caches.
* <p>
* All items in local file are of human friendly format.
*/
public class FileCacheStore {
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(FileCacheStore.class);
private String cacheFilePath;
private File cacheFile;
private File lockFile;
private FileLock directoryLock;
private FileCacheStore(String cacheFilePath, File cacheFile, File lockFile, FileLock directoryLock) {
this.cacheFilePath = cacheFilePath;
this.cacheFile = cacheFile;
this.lockFile = lockFile;
this.directoryLock = directoryLock;
}
public synchronized Map<String, String> loadCache(int entrySize) throws IOException {
Map<String, String> properties = new HashMap<>();
try (BufferedReader reader = new BufferedReader(new FileReader(cacheFile))) {
int count = 1;
String line = reader.readLine();
while (line != null && count <= entrySize) {
// content has '=' need to be encoded before write
if (!line.startsWith("#") && line.contains("=")) {
String[] pairs = line.split("=");
properties.put(pairs[0], pairs[1]);
count++;
}
line = reader.readLine();
}
if (count > entrySize) {
logger.warn(COMMON_CACHE_MAX_FILE_SIZE_LIMIT_EXCEED, "mis-configuration of system properties",
"Check Java system property 'dubbo.mapping.cache.entrySize' and 'dubbo.meta.cache.entrySize'.",
"Cache file was truncated for exceeding the maximum entry size: " + entrySize);
}
} catch (IOException e) {
logger.warn(COMMON_CACHE_PATH_INACCESSIBLE, "inaccessible of cache path", "",
"Load cache failed ", e);
throw e;
}
return properties;
}
private void unlock() {
if (directoryLock != null && directoryLock.isValid()) {
try {
directoryLock.release();
directoryLock.channel().close();
deleteFile(lockFile);
} catch (IOException e) {
logger.error(COMMON_CACHE_PATH_INACCESSIBLE, "inaccessible of cache path", "",
"Failed to release cache path's lock file:" + lockFile, e);
throw new RuntimeException("Failed to release cache path's lock file:" + lockFile, e);
}
}
}
public synchronized void refreshCache(Map<String, String> properties, String comment, long maxFileSize) {
if (CollectionUtils.isEmptyMap(properties)) {
return;
}
try (LimitedLengthBufferedWriter bw =
new LimitedLengthBufferedWriter(
new OutputStreamWriter(
new FileOutputStream(cacheFile, false), StandardCharsets.UTF_8), maxFileSize)) {
bw.write("#" + comment);
bw.newLine();
bw.write("#" + new Date());
bw.newLine();
for (Map.Entry<String, String> e : properties.entrySet()) {
String key = e.getKey();
String val = e.getValue();
bw.write(key + "=" + val);
bw.newLine();
}
bw.flush();
long remainSize = bw.getRemainSize();
if (remainSize < 0) {
logger.warn(COMMON_CACHE_MAX_ENTRY_COUNT_LIMIT_EXCEED, "mis-configuration of system properties",
"Check Java system property 'dubbo.mapping.cache.maxFileSize' and 'dubbo.meta.cache.maxFileSize'.",
"Cache file was truncated for exceeding the maximum file size " + maxFileSize + " byte. Exceeded by " + (-remainSize) + " byte.");
}
} catch (IOException e) {
logger.warn(COMMON_CACHE_PATH_INACCESSIBLE, "inaccessible of cache path", "",
"Update cache error.", e);
}
}
private static void deleteFile(File f) {
Path pathOfFile = f.toPath();
try {
Files.delete(pathOfFile);
} catch (IOException ioException) {
logger.debug("Failed to delete file " + f.getAbsolutePath(), ioException);
}
}
public synchronized void destroy() {
unlock();
FileCacheStoreFactory.removeCache(cacheFilePath);
}
/**
* for unit test only
*/
@Deprecated
protected String getCacheFilePath() {
return cacheFilePath;
}
public static Builder newBuilder() {
return new Builder();
}
public static class Builder {
private String cacheFilePath;
private File cacheFile;
private File lockFile;
private FileLock directoryLock;
private Builder() {
}
public Builder cacheFilePath(String cacheFilePath) {
this.cacheFilePath = cacheFilePath;
return this;
}
public Builder cacheFile(File cacheFile) {
this.cacheFile = cacheFile;
return this;
}
public Builder lockFile(File lockFile) {
this.lockFile = lockFile;
return this;
}
public Builder directoryLock(FileLock directoryLock) {
this.directoryLock = directoryLock;
return this;
}
public FileCacheStore build() {
return new FileCacheStore(cacheFilePath, cacheFile, lockFile, directoryLock);
}
}
/**
* An empty (or fallback) implementation of FileCacheStore. Used when cache file creation failed.
*/
protected static class Empty extends FileCacheStore {
private Empty(String cacheFilePath) {
super(cacheFilePath, null, null, null);
}
public static Empty getInstance(String cacheFilePath) {
return new Empty(cacheFilePath);
}
@Override
public Map<String, String> loadCache(int entrySize) throws IOException {
return Collections.emptyMap();
}
@Override
public void refreshCache(Map<String, String> properties, String comment, long maxFileSize) {
// No-op.
}
}
/**
* A BufferedWriter which limits the length (in bytes). When limit exceed, this writer stops writing.
*/
private static class LimitedLengthBufferedWriter extends BufferedWriter {
private long remainSize;
public LimitedLengthBufferedWriter(Writer out, long maxSize) {
super(out);
this.remainSize = maxSize == 0 ? Long.MAX_VALUE : maxSize;
}
@Override
public void write(String str) throws IOException {
remainSize -= str.getBytes(StandardCharsets.UTF_8).length;
if (remainSize < 0) {
return;
}
super.write(str);
}
public long getRemainSize() {
return remainSize;
}
}
}
相关信息
相关文章
0
赞
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
8、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦