package com.yahoo.vespa.model.search;

import com.yahoo.config.provision.Flavor;
import com.yahoo.vespa.config.search.core.ProtonConfig;

import static java.lang.Long.min;

/**
 * Tuning of proton config for a search node based on the node flavor of that node.
 *
 * @author geirst
 */
public class NodeFlavorTuning implements ProtonConfig.Producer {

    static long MB = 1024 * 1024;
    static long GB = MB * 1024;
    private final Flavor nodeFlavor;

    public NodeFlavorTuning(Flavor nodeFlavor) {
        this.nodeFlavor = nodeFlavor;
    }

    @Override
    public void getConfig(ProtonConfig.Builder builder) {
        tuneDiskWriteSpeed(builder);
        tuneDocumentStoreMaxFileSize(builder);
        ProtonConfig.Flush.Memory.Builder flushMemoryBuilder = new ProtonConfig.Flush.Memory.Builder();
        tuneFlushStrategyMemoryLimits(flushMemoryBuilder);
        tuneFlushStrategyTlsSize(flushMemoryBuilder);
        builder.flush(new ProtonConfig.Flush.Builder().memory(flushMemoryBuilder));
    }

    private void tuneDiskWriteSpeed(ProtonConfig.Builder builder) {
        ProtonConfig.Hwinfo.Disk.Builder diskInfo = new ProtonConfig.Hwinfo.Disk.Builder();
        if (!nodeFlavor.hasFastDisk()) {
            diskInfo.writespeed(40);
        }
        builder.hwinfo(new ProtonConfig.Hwinfo.Builder().disk(diskInfo));
    }

    private void tuneDocumentStoreMaxFileSize(ProtonConfig.Builder builder) {
        double memoryGb = nodeFlavor.getMinMainMemoryAvailableGb();
        long fileSizeBytes = 4 * GB;
        if (memoryGb <= 12.0) {
            fileSizeBytes = 256 * MB;
        } else if (memoryGb < 24.0) {
            fileSizeBytes = 512 * MB;
        } else if (memoryGb <= 64.0) {
            fileSizeBytes = 1 * GB;
        }
        builder.summary(new ProtonConfig.Summary.Builder()
                .log(new ProtonConfig.Summary.Log.Builder()
                        .maxfilesize(fileSizeBytes)));
    }

    private void tuneFlushStrategyMemoryLimits(ProtonConfig.Flush.Memory.Builder builder) {
        long memoryLimitBytes = (long) ((nodeFlavor.getMinMainMemoryAvailableGb() / 8) * GB);
        builder.maxmemory(memoryLimitBytes)
                .each(new ProtonConfig.Flush.Memory.Each.Builder()
                        .maxmemory(memoryLimitBytes));
    }

    private void tuneFlushStrategyTlsSize(ProtonConfig.Flush.Memory.Builder builder) {
        long tlsSizeBytes = (long) ((nodeFlavor.getMinDiskAvailableGb() * 0.07) * GB);
        tlsSizeBytes = min(tlsSizeBytes, 100 * GB);
        builder.maxtlssize(tlsSizeBytes);
    }

}

@@ -703,112 +703,8 @@
 r);%0A
-        ProtonConfig.Flush.Memory.Builder flushMemoryBuilder = new ProtonConfig.Flush.Memory.Builder();%0A
     
@@ -737,34 +737,36 @@
 yLimits(
+builder.
 flush
-M
+.m
 emory
-Builder
 );%0A     
@@ -797,279 +797,105 @@
 ize(
-flushMemoryBuilder);%0A        builder.flush(new ProtonConfig.Flush.Builder().memory(flushMemoryBuilder));%0A    %7D%0A%0A    private void tuneDiskWriteSpeed(ProtonConfig.Builder builder) %7B%0A        ProtonConfig.Hwinfo.Disk.Builder diskInfo = new ProtonConfig.Hwinfo.Disk.Builder();
+builder.flush.memory);%0A    %7D%0A%0A    private void tuneDiskWriteSpeed(ProtonConfig.Builder builder) %7B
 %0A   
@@ -944,24 +944,35 @@
         
+builder.hwinfo.
 disk
-Info
 .writesp
@@ -994,82 +994,8 @@
   %7D%0A
-        builder.hwinfo(new ProtonConfig.Hwinfo.Builder().disk(diskInfo));%0A
     
@@ -1438,128 +1438,12 @@
 mary
-(new ProtonConfig.Summary.Builder()%0A                .log(new ProtonConfig.Summary.Log.Builder()%0A                        
+.log
 .max
@@ -1465,18 +1465,16 @@
 zeBytes)
-))
 ;%0A    %7D%0A
@@ -1703,16 +1703,17 @@
 itBytes)
+;
 %0A       
@@ -1717,91 +1717,20 @@
     
-        .each(new ProtonConfig.Flush.Memory.Each.Builder()%0A                        
+builder.each
 .max
@@ -1753,17 +1753,16 @@
 itBytes)
-)
 ;%0A    %7D%0A

Use default builders directly to avoid replacing previous changes done by other producers of proton config.