public void doSaveProperties()

in dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/AbstractRegistry.java [220:336]


    public void doSaveProperties(long version) {
        if (version < lastCacheChanged.get()) {
            return;
        }
        if (file == null) {
            return;
        }
        // Save
        File lockfile = null;
        try {
            lockfile = new File(file.getAbsolutePath() + ".lock");
            if (!lockfile.exists()) {
                lockfile.createNewFile();
            }

            try (RandomAccessFile raf = new RandomAccessFile(lockfile, "rw");
                    FileChannel channel = raf.getChannel()) {
                FileLock lock = channel.tryLock();
                if (lock == null) {

                    IOException ioException = new IOException(
                            "Can not lock the registry cache file " + file.getAbsolutePath() + ", "
                                    + "ignore and retry later, maybe multi java process use the file, please config: dubbo.registry.file=xxx.properties");

                    // 1-9 failed to read / save registry cache file.
                    logger.warn(
                            REGISTRY_FAILED_READ_WRITE_CACHE_FILE,
                            CAUSE_MULTI_DUBBO_USING_SAME_FILE,
                            "",
                            "Adjust dubbo.registry.file.",
                            ioException);

                    throw ioException;
                }

                // Save
                try {
                    if (!file.exists()) {
                        file.createNewFile();
                    }

                    Properties tmpProperties;
                    if (syncSaveFile) {
                        // When syncReport = true, properties.setProperty and properties.store are called from the same
                        // thread(reportCacheExecutor), so deep copy is not required
                        tmpProperties = properties;
                    } else {
                        // Using properties.setProperty and properties.store method will cause lock contention
                        // under multi-threading, so deep copy a new container
                        tmpProperties = new Properties();
                        Set<Map.Entry<Object, Object>> entries = properties.entrySet();
                        for (Map.Entry<Object, Object> entry : entries) {
                            tmpProperties.setProperty((String) entry.getKey(), (String) entry.getValue());
                        }
                    }

                    try (FileOutputStream outputFile = new FileOutputStream(file)) {
                        tmpProperties.store(outputFile, "Dubbo Registry Cache");
                    }
                } finally {
                    lock.release();
                }
            }
        } catch (Throwable e) {
            savePropertiesRetryTimes.incrementAndGet();

            if (savePropertiesRetryTimes.get() >= MAX_RETRY_TIMES_SAVE_PROPERTIES) {
                if (e instanceof OverlappingFileLockException) {
                    // fix #9341, ignore OverlappingFileLockException
                    logger.info("Failed to save registry cache file for file overlapping lock exception, file name "
                            + file.getName());
                } else {
                    // 1-9 failed to read / save registry cache file.
                    logger.warn(
                            REGISTRY_FAILED_READ_WRITE_CACHE_FILE,
                            CAUSE_MULTI_DUBBO_USING_SAME_FILE,
                            "",
                            "Failed to save registry cache file after retrying " + MAX_RETRY_TIMES_SAVE_PROPERTIES
                                    + " times, cause: " + e.getMessage(),
                            e);
                }

                savePropertiesRetryTimes.set(0);
                return;
            }

            if (version < lastCacheChanged.get()) {
                savePropertiesRetryTimes.set(0);
                return;
            } else {
                registryCacheExecutor.schedule(
                        () -> doSaveProperties(lastCacheChanged.incrementAndGet()),
                        DEFAULT_INTERVAL_SAVE_PROPERTIES,
                        TimeUnit.MILLISECONDS);
            }

            if (!(e instanceof OverlappingFileLockException)) {
                logger.warn(
                        REGISTRY_FAILED_READ_WRITE_CACHE_FILE,
                        CAUSE_MULTI_DUBBO_USING_SAME_FILE,
                        "However, the retrying count limit is not exceeded. Dubbo will still try.",
                        "Failed to save registry cache file, will retry, cause: " + e.getMessage(),
                        e);
            }
        } finally {
            if (lockfile != null) {
                if (!lockfile.delete()) {
                    // 1-10 Failed to delete lock file.
                    logger.warn(
                            REGISTRY_FAILED_DELETE_LOCKFILE,
                            "",
                            "",
                            String.format("Failed to delete lock file [%s]", lockfile.getName()));
                }
            }
        }
    }