aboutsummaryrefslogtreecommitdiffstats
path: root/vespalog/src/main/java/com/yahoo/log/MappedLevelControllerRepo.java
blob: 10b4d11c69582bfea9e37176a458912d51ccaf53 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.log;

import com.yahoo.text.Utf8;

import java.nio.MappedByteBuffer;
import java.util.HashMap;
import java.util.Map;

/**
 * Contains a repository of mapped log level controllers.
 *
 * @author Ulf Lilleengen
 * @since 5.1
 * Should only be used internally in the log library
 */
class MappedLevelControllerRepo {
    private final Map<String, LevelController> levelControllerMap = new HashMap<>();
    private final MappedByteBuffer mapBuf;
    private final int controlFileHeaderLength;
    private final int numLevels;
    private final String logControlFilename;

    MappedLevelControllerRepo(MappedByteBuffer mapBuf, int controlFileHeaderLength, int numLevels, String logControlFilename) {
        this.mapBuf = mapBuf;
        this.controlFileHeaderLength = controlFileHeaderLength;
        this.numLevels = numLevels;
        this.logControlFilename = logControlFilename;
        buildMap();
    }

    private void buildMap() {
        int len = mapBuf.capacity();
        int startOfLine = controlFileHeaderLength;

        int numLine = 1;
        int i = 0;
        while (i < len) {
            if (mapBuf.get(i) == '\n') {
                startOfLine = ++i;
                ++numLine;
            } else if (i < controlFileHeaderLength) {
                ++i;
            } else if (mapBuf.get(i) == ':') {
                int endOfName = i;
                int levels = i;
                levels += 2;
                while ((levels % 4) != 0) {
                    levels++;
                }
                int endLine = levels + 4*numLevels;

                if (checkLine(startOfLine, endOfName, levels, endLine)) {
                    int l = endOfName - startOfLine;
                    if (l > 1 && mapBuf.get(startOfLine) == '.') {
                        ++startOfLine;
                        --l;
                    }
                    byte[] namebytes = new byte[l];
                    for (int j = 0; j < l; j++) {
                        namebytes[j] = mapBuf.get(startOfLine + j);
                    }
                    String name = Utf8.toString(namebytes);
                    if (name.equals("default")) {
                        name = "";
                    }
                    MappedLevelController ctrl = new MappedLevelController(mapBuf, levels, name);
                    levelControllerMap.put(name, ctrl);
                    i = endLine;
                    continue; // good line
                }
                // bad line, skip
                while (i < len && mapBuf.get(i) != '\n') {
                    i++;
                }
                int bll = i - startOfLine;
                byte[] badline = new byte[bll];
                for (int j = 0; j < bll; j++) {
                    badline[j] = mapBuf.get(startOfLine + j);
                }
                System.err.println("bad loglevel line "+numLine+" in "
                                   + logControlFilename + ": " + Utf8.toString(badline));
            } else {
                i++;
            }
        }
    }

    private boolean checkLine(int sol, int endnam, int levstart, int eol) {
        if (eol >= mapBuf.capacity()) {
            System.err.println("line would end after end of file");
            return false;
        }
        if (mapBuf.get(eol) != '\n') {
            System.err.println("line must end with newline, was: "+mapBuf.get(eol));
            return false;
        }
        if (endnam < sol + 1) {
            System.err.println("name must be at least one character after start of line");
            return false;
        }
        return MappedLevelController.checkOnOff(mapBuf, levstart);
    }

    LevelController getLevelController(String suffix) {

        return levelControllerMap.get(suffix);
    }

    void checkBack() {
        for (LevelController ctrl : levelControllerMap.values()) {
            ctrl.checkBack();
        }
    }
}