aboutsummaryrefslogtreecommitdiffstats
path: root/jrt/src/com/yahoo/jrt/slobrok/api/SlobrokList.java
blob: 4cd01293798558e0802e86a173a39896c98efc51 (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
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.jrt.slobrok.api;

import java.util.Arrays;
import java.util.concurrent.ThreadLocalRandom;
import java.util.logging.Logger;

public class SlobrokList {

    private static final Logger log = Logger.getLogger(SlobrokList.class.getName());

    private final Internal internal;
    private String[] slobroks;
    private int idx = 0;

    public SlobrokList() {
        this.internal = new Internal();
    }

    public SlobrokList(SlobrokList sibling) {
        this.internal = sibling.internal;
    }

    private void checkUpdate() {
        synchronized (internal) {
            if (slobroks == internal.slobroks) {
                return;
            }
            slobroks = internal.slobroks;
            log.fine(() -> "checkUpdate() updated tmp list="+Arrays.toString(slobroks)+" from shared list="+Arrays.toString(internal.slobroks));
            idx = 0;
        }
    }

    public String nextSlobrokSpec() {
        checkUpdate();
        if (idx < slobroks.length) {
            log.fine(() -> "nextSlobrokSpec() returns: "+slobroks[idx]);
            return slobroks[idx++];
        }
        log.fine(() -> "nextSlobrokSpec() reached end of internal list, idx="+idx+"/"+slobroks.length+", tmp list="+Arrays.toString(slobroks)+", shared list="+Arrays.toString(internal.slobroks));
        idx = 0;
        return null;
    }

    public void setup(String[] slobroks) {
        internal.setup(slobroks);
    }

    public int length() {
        return internal.length();
    }

    public boolean contains(String slobrok) {
        checkUpdate();
        for (String s : slobroks) {
            if (s.equals(slobrok)) return true;
        }
        return false;
    }

    @Override
    public String toString() {
        return internal.toString();
    }

    private static class Internal {

        String[] slobroks = new String[0];

        void setup(String[] slobroks) {
            String[] next = new String[slobroks.length];
            for (int i = 0; i < slobroks.length; i++) {
                next[i] = slobroks[i];
            }
            for (int i = 0; i + 1 < next.length; i++) {
                int lim = next.length - i;
                int x = ThreadLocalRandom.current().nextInt(lim);
                if (x != 0) {
                    String tmp = next[i];
                    next[i] = next[i+x];
                    next[i+x] = tmp;
                }
            }
            synchronized (this) {
                this.slobroks = next;
            }
        }

        synchronized int length() {
            return slobroks.length;
        }

        @Override
        public synchronized String toString() {
            return Arrays.toString(slobroks);
        }
    }

}