All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.neko233.toolchain.storage.wal.WalMetadataV1 Maven / Gradle / Ivy

package com.neko233.toolchain.storage.wal;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONWriter;
import com.neko233.toolchain.common.file.FileUtils233;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
 * @author SolarisNeko
 * Date on 2023-01-28
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Slf4j
public class WalMetadataV1 {

    public static final long BEGIN_NUMBER = 1;
    public static final long MAX_SEQUENCE_ID = 50;

    private Long currentSequenceId; // 当前指向的 sequenceId 是未刷盘的
    private String fileTemplate;
    private File currentWalFile;
    private long previousFlushMs;

    public static WalMetadataV1 createFirst(String fileTemplate) {
        return WalMetadataV1.builder()
                .currentSequenceId(BEGIN_NUMBER)
                .fileTemplate(fileTemplate)
                .currentWalFile(new File(fileTemplate + "." + BEGIN_NUMBER))
                .build();
    }

    public Long getCurrentSequenceId() {
        long historySequenceId = currentSequenceId;
        // auto fix | if MAX_SEQUENCE_ID happen change
        this.currentSequenceId = currentSequenceId > MAX_SEQUENCE_ID ? MAX_SEQUENCE_ID : currentSequenceId;
        this.currentWalFile = newWalFile();
        return historySequenceId;
    }

    /**
     * 当达到某种条件后, 进行迭代 metadata
     *
     * @return 更新后的 metadata
     * @throws IOException IO 异常
     */
    public WalMetadataV1 nextSequence() throws IOException {
        this.currentSequenceId += 1;
        // loop
        if (this.currentSequenceId > getMaxSequenceId()) {
            this.currentSequenceId = 1L;
        }
        this.currentWalFile = new File(buildDataFileName(this.currentSequenceId));
        FileUtils233.createFileIfNotExists(this.currentWalFile);
        return this;
    }

    public static long getMaxSequenceId() {
        return MAX_SEQUENCE_ID;
    }

    @NotNull
    public String buildDataFileName(long sequenceId) {
        return fileTemplate + "." + sequenceId;
    }


    /**
     * WAL core
     *
     * @param dataFile dataFile
     */
    public void flushMetadataToFile(final File dataFile) {
        if (dataFile == null) {
            log.error("why your WAL data file is null ? please check.");
            return;
        }
        String json = JSON.toJSONString(this, JSONWriter.Feature.PrettyFormat);
        try {
            FileUtils233.write(dataFile, json, StandardCharsets.UTF_8, false);
        } catch (IOException e) {
            log.error("write to metadata file error! file = {}, data = {}", dataFile, json, e);
        }
    }

    public File newWalFile() {
        return new File(fileTemplate + "." + this.currentSequenceId);
    }

    public boolean isNeedRollingByBytes(long fileRollingByteSize) {
        return currentWalFile.length() >= fileRollingByteSize;
    }

    public boolean isNeedRollingByTimeMsAndHaveData(long keepWalFileMs) {
        return (System.currentTimeMillis() - previousFlushMs) > keepWalFileMs;
    }


    public void resetCurrentWalFile(File walFile) throws IOException {
        this.currentWalFile = walFile;
        FileUtils233.createFileIfNotExists(walFile);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy