All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.solr.core.backup.BackupProperties Maven / Gradle / Ivy

There is a newer version: 9.7.0
Show newest version
/*
 * 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 org.apache.solr.core.backup;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.Writer;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.stream.Collectors;
import org.apache.lucene.store.IOContext;
import org.apache.lucene.util.Version;
import org.apache.solr.common.params.CollectionAdminParams;
import org.apache.solr.core.backup.repository.BackupRepository;
import org.apache.solr.util.PropertiesInputStream;

/**
 * Represents a backup[-*].properties file, responsible for holding whole-collection and
 * whole-backup metadata.
 *
 * 

These files live in a different location and hold different metadata depending on the backup * format used. The (now deprecated) traditional 'full-snapshot' backup format places this file at * $LOCATION/$NAME, while the preferred incremental backup format stores these files in * $LOCATION/$NAME/$COLLECTION. */ public class BackupProperties { private static final String EXTRA_PROPERTY_PREFIX = "property."; private double indexSizeMB; private int indexFileCount; private final Properties properties; private final Map extraProperties; private BackupProperties(Properties properties, Map extraProperties) { this.properties = properties; if (extraProperties == null) { extraProperties = Map.of(); } else if (extraProperties.keySet().stream().anyMatch(String::isEmpty)) { throw new IllegalArgumentException("Can't have an extra property with an empty key"); } this.extraProperties = extraProperties; } public static BackupProperties create( String backupName, String collectionName, String extCollectionName, String configName, Map extraProperties) { final Properties properties = new Properties(); properties.put(BackupManager.BACKUP_NAME_PROP, backupName); properties.put(BackupManager.COLLECTION_NAME_PROP, collectionName); properties.put(BackupManager.COLLECTION_ALIAS_PROP, extCollectionName); properties.put(CollectionAdminParams.COLL_CONF, configName); properties.put(BackupManager.START_TIME_PROP, Instant.now().toString()); properties.put(BackupManager.INDEX_VERSION_PROP, Version.LATEST.toString()); return new BackupProperties(properties, extraProperties); } public static Optional readFromLatest( BackupRepository repository, URI backupPath) throws IOException { Optional lastBackupId = BackupFilePaths.findMostRecentBackupIdFromFileListing( repository.listAllOrEmpty(backupPath)); if (!lastBackupId.isPresent()) { return Optional.empty(); } return Optional.of( readFrom(repository, backupPath, BackupFilePaths.getBackupPropsName(lastBackupId.get()))); } public static BackupProperties readFrom( BackupRepository repository, URI backupPath, String fileName) throws IOException { Properties props = new Properties(); try (Reader is = new InputStreamReader( new PropertiesInputStream( repository.openInput(backupPath, fileName, IOContext.DEFAULT)), StandardCharsets.UTF_8)) { props.load(is); Map extraProperties = extractExtraProperties(props); return new BackupProperties(props, extraProperties); } } private static Map extractExtraProperties(Properties props) { Map extraProperties = new HashMap<>(); props .entrySet() .removeIf( e -> { String entryKey = e.getKey().toString(); if (entryKey.startsWith(EXTRA_PROPERTY_PREFIX)) { extraProperties.put( entryKey.substring(EXTRA_PROPERTY_PREFIX.length()), String.valueOf(e.getValue())); return true; } return false; }); return extraProperties; } public List getAllShardBackupMetadataFiles() { return properties.entrySet().stream() .filter(entry -> entry.getKey().toString().endsWith(".md")) .map(entry -> entry.getValue().toString()) .collect(Collectors.toList()); } public void countIndexFiles(int numFiles, double sizeMB) { indexSizeMB += sizeMB; indexFileCount += numFiles; } public Optional getShardBackupIdFor(String shardName) { String key = getKeyForShardBackupId(shardName); if (properties.containsKey(key)) { return Optional.of(ShardBackupId.fromShardMetadataFilename(properties.getProperty(key))); } return Optional.empty(); } public ShardBackupId putAndGetShardBackupIdFor(String shardName, int backupId) { final ShardBackupId shardBackupId = new ShardBackupId(shardName, new BackupId(backupId)); properties.put(getKeyForShardBackupId(shardName), shardBackupId.getBackupMetadataFilename()); return shardBackupId; } private String getKeyForShardBackupId(String shardName) { return shardName + ".md"; } public void store(Writer propsWriter) throws IOException { Properties propertiesCopy = (Properties) properties.clone(); propertiesCopy.put("indexSizeMB", String.valueOf(indexSizeMB)); propertiesCopy.put("indexFileCount", String.valueOf(indexFileCount)); propertiesCopy.put(BackupManager.END_TIME_PROP, Instant.now().toString()); if (extraProperties != null && !extraProperties.isEmpty()) { extraProperties.forEach((k, v) -> propertiesCopy.put(EXTRA_PROPERTY_PREFIX + k, v)); } propertiesCopy.store(propsWriter, "Backup properties file"); } public String getCollection() { return properties.getProperty(BackupManager.COLLECTION_NAME_PROP); } public String getCollectionAlias() { return properties.getProperty(BackupManager.COLLECTION_ALIAS_PROP); } public String getConfigName() { return properties.getProperty(CollectionAdminParams.COLL_CONF); } public String getStartTime() { return properties.getProperty(BackupManager.START_TIME_PROP); } public String getEndTime() { return properties.getProperty(BackupManager.END_TIME_PROP); } public String getIndexVersion() { return properties.getProperty(BackupManager.INDEX_VERSION_PROP); } public Map getExtraProperties() { return extraProperties; } public Map getDetails() { final Map result = new HashMap<>(); properties.entrySet().forEach(entry -> result.put(entry.getKey().toString(), entry.getValue())); result.remove(BackupManager.BACKUP_NAME_PROP); result.remove(BackupManager.COLLECTION_NAME_PROP); result.put("indexSizeMB", Double.valueOf(properties.getProperty("indexSizeMB"))); result.put("indexFileCount", Integer.valueOf(properties.getProperty("indexFileCount"))); if (extraProperties != null && !extraProperties.isEmpty()) { result.put("extraProperties", extraProperties); } Map shardBackupIds = new HashMap<>(); Iterator keyIt = result.keySet().iterator(); while (keyIt.hasNext()) { String key = keyIt.next(); if (key.endsWith(".md")) { shardBackupIds.put(key.substring(0, key.length() - 3), properties.getProperty(key)); keyIt.remove(); } } result.put("shardBackupIds", shardBackupIds); return result; } public String getBackupName() { return properties.getProperty(BackupManager.BACKUP_NAME_PROP); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy