blob: f264c7817380337bca3e2b0e2739507bd67d84c2 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 com.epam.dlab.backendapi.domain;
import com.epam.dlab.backendapi.resources.dto.LibraryAutoCompleteDTO;
import com.epam.dlab.backendapi.resources.dto.LibraryDTO;
import com.epam.dlab.exceptions.DlabException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.MoreObjects;
import io.dropwizard.util.Duration;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;
/**
* Class to store the info about libraries.
*/
@Slf4j
public class ExploratoryLibList {
/**
* Timeout in milliseconds when the info is out of date.
*/
private static final long EXPIRED_TIMEOUT_MILLIS = Duration.hours(2).toMilliseconds();
/**
* Timeout in milliseconds until the is out of date.
*/
private static final long UPDATE_TIMEOUT_MILLIS = Duration.minutes(30).toMilliseconds();
/**
* Timeout in milliseconds for request to update lib.
*/
protected static final long UPDATE_REQUEST_TIMEOUT_MILLIS = Duration.minutes(15).toMilliseconds();
/**
* Group name.
*/
private String group;
/**
* List of libraries group:libraries:version.
*/
private Map<String, Map<String, String>> libs = new HashMap<>();
/**
* Time in milliseconds when the info is out of date.
*/
private long expiredTimeMillis = 0;
/**
* Last access time in milliseconds to the info.
*/
private long accessTimeMillis = 0;
/**
* Update start time in milliseconds.
*/
private long updateStartTimeMillis = 0;
/**
* Update in progress.
*/
private boolean updating = false;
/**
* Instantiate the list of libraries.
*
* @param group the name of docker's image.
* @param content JSON string.
*/
ExploratoryLibList(String group, String content) {
this.group = group;
if (content != null) {
setLibs(content);
}
}
/**
* Return the list of all groups.
*/
public List<String> getGroupList() {
List<String> list = new ArrayList<>(libs.keySet());
Collections.sort(list);
return list;
}
/**
* Return the name of docker image;
*/
public String getGroup() {
return group;
}
/**
* Return the full list of libraries for group.
*
* @param group the name of group.
*/
public Map<String, String> getLibs(String group) {
return libs.get(group);
}
/**
* Return the full list of libraries for group.
*
* @param content JSON string.
*/
private void setLibs(String content) {
ObjectMapper mapper = new ObjectMapper();
try {
synchronized (this) {
@SuppressWarnings("unchecked")
Map<String, Map<String, String>> map = mapper.readValue(content, Map.class);
for (Map.Entry<String, Map<String, String>> entry : map.entrySet()) {
Map<String, String> group = entry.getValue();
String groupName = entry.getKey();
libs.remove(groupName);
log.info("Update {} group with lib group {} with {} libraries", this.group, groupName, (group != null) ? group.size() : null);
libs.put(groupName, new TreeMap<>(group));
}
setExpiredTime();
updating = false;
}
} catch (IOException e) {
throw new DlabException("Cannot deserialize the list of libraries. " + e.getLocalizedMessage(), e);
}
}
public void setExpiredTime() {
expiredTimeMillis = System.currentTimeMillis() + EXPIRED_TIMEOUT_MILLIS;
accessTimeMillis = System.currentTimeMillis();
}
/**
* Search and return the list of libraries for name's prefix <b>startWith</b>.
*
* @param group the name of group.
* @param startWith the prefix for library name.
* @return LibraryAutoCompleteDTO dto
*/
public LibraryAutoCompleteDTO getLibs(String group, String startWith) {
final String startsWithLower = startWith.toLowerCase();
Map<String, String> libMap = getLibs(group);
if (libMap == null) {
return LibraryAutoCompleteDTO.builder()
.autoComplete(isUpdating() ? AutoCompleteEnum.UPDATING : AutoCompleteEnum.NONE)
.libraries(Collections.emptyList())
.build();
}
List<LibraryDTO> libraries = libMap.entrySet()
.stream()
.filter(e -> e.getKey().toLowerCase().startsWith(startsWithLower))
.map(e -> new LibraryDTO(e.getKey(), e.getValue()))
.collect(Collectors.toList());
return LibraryAutoCompleteDTO.builder()
.autoComplete(AutoCompleteEnum.ENABLED)
.libraries(libraries)
.build();
}
/**
* Set last access time.
*/
private void touch() {
accessTimeMillis = System.currentTimeMillis();
}
/**
* Return <b>true</b> if the info is out of date.
*/
public boolean isExpired() {
touch();
return (expiredTimeMillis < System.currentTimeMillis());
}
/**
* Return <b>true</b> if the info needs to update.
*/
public boolean isUpdateNeeded() {
touch();
return (accessTimeMillis > expiredTimeMillis - UPDATE_TIMEOUT_MILLIS);
}
/**
* Set updating in progress.
*/
public void setUpdating() {
updateStartTimeMillis = System.currentTimeMillis();
updating = true;
}
/**
* Set updating to false.
*/
public void setNotUpdating() {
updating = Boolean.FALSE;
}
/**
* Return <b>true</b> if the update in progress.
*/
public boolean isUpdating() {
if (updating &&
updateStartTimeMillis + UPDATE_REQUEST_TIMEOUT_MILLIS < System.currentTimeMillis()) {
updating = false;
}
return updating;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("group", group)
.add("expiredTimeMillis", expiredTimeMillis)
.add("accessTimeMillis", accessTimeMillis)
.add("updateStartTimeMillis", updateStartTimeMillis)
.add("isUpdating", updating)
.add("libs", (libs == null ? "null" : "..."))
.toString();
}
}