/* * Copyright 2016 Red Hat, Inc. and/or its affiliates * and other contributors as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.keycloak.models.sessions.infinispan.initializer; import org.jboss.logging.Logger; import org.keycloak.models.sessions.infinispan.entities.SessionEntity; import java.util.ArrayList; import java.util.List; /** * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a> */ public class InitializerState extends SessionEntity { private static final Logger log = Logger.getLogger(InitializerState.class); private int sessionsCount; private List<Boolean> segments = new ArrayList<>(); private int lowestUnfinishedSegment = 0; public void init(int sessionsCount, int sessionsPerSegment) { this.sessionsCount = sessionsCount; int segmentsCount = sessionsCount / sessionsPerSegment; if (sessionsPerSegment * segmentsCount < sessionsCount) { segmentsCount = segmentsCount + 1; } log.debugf("sessionsCount: %d, sessionsPerSegment: %d, segmentsCount: %d", sessionsCount, sessionsPerSegment, segmentsCount); for (int i=0 ; i<segmentsCount ; i++) { segments.add(false); } updateLowestUnfinishedSegment(); } // Return true just if computation is entirely finished (all segments are true) public boolean isFinished() { return lowestUnfinishedSegment == -1; } // Return next un-finished segments. It can return "segmentCount" segments or less public List<Integer> getUnfinishedSegments(int segmentCount) { List<Integer> result = new ArrayList<>(); int next = lowestUnfinishedSegment; boolean remaining = lowestUnfinishedSegment != -1; while (remaining && result.size() < segmentCount) { next = getNextUnfinishedSegmentFromIndex(next); if (next == -1) { remaining = false; } else { result.add(next); next++; } } return result; } public void markSegmentFinished(int index) { segments.set(index, true); updateLowestUnfinishedSegment(); } private void updateLowestUnfinishedSegment() { this.lowestUnfinishedSegment = getNextUnfinishedSegmentFromIndex(lowestUnfinishedSegment); } private int getNextUnfinishedSegmentFromIndex(int index) { int segmentsSize = segments.size(); for (int i=index ; i<segmentsSize ; i++) { Boolean entry = segments.get(i); if (!entry) { return i; } } return -1; } public String printState() { int finished = 0; int nonFinished = 0; int size = segments.size(); for (int i=0 ; i<size ; i++) { Boolean done = segments.get(i); if (done) { finished++; } else { nonFinished++; } } StringBuilder strBuilder = new StringBuilder("sessionsCount: " + sessionsCount) .append(", finished segments count: " + finished) .append(", non-finished segments count: " + nonFinished); return strBuilder.toString(); } }