Search in sources :

Example 1 with MigrationMessageEvent

use of org.nzbhydra.migration.FromPythonMigration.MigrationMessageEvent in project nzbhydra2 by theotherp.

the class JsonConfigMigration method migrate.

public ConfigMigrationResult migrate(String oldConfigJson) throws IOException {
    logger.info("Migrating config from NZBHydra 1");
    eventPublisher.publishEvent(new MigrationMessageEvent("Migrating config and checking indexers"));
    ObjectMapper mapper = new ObjectMapper();
    mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    mapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
    OldConfig oldConfig = mapper.readValue(oldConfigJson, OldConfig.class);
    BaseConfig newConfig = configProvider.getBaseConfig();
    mapper = new ObjectMapper(new YAMLFactory());
    mapper.registerModule(new Jdk8Module());
    // Easy way of cloning the base config
    newConfig = mapper.readValue(mapper.writeValueAsString(newConfig), BaseConfig.class);
    List<String> messages = new ArrayList<>();
    if (oldConfig.getMain().getConfigVersion() != NZBHYDRA1_SUPPORTED_CONFIG_VERSION) {
        logger.warn("Unable to migrate config from config version {}. Aborting", oldConfig.getMain().getConfigVersion());
        throw new IllegalStateException("Unable to migrate config from config version " + oldConfig.getMain().getConfigVersion());
    }
    try {
        messages.addAll(migrateMain(oldConfig.getMain(), newConfig.getMain()));
    } catch (Exception e) {
        logger.error("Error while migrating main settings", e);
        messages.add("Error while migrating main settings. Please check and set the values manually.");
    }
    try {
        messages.addAll(migrateIndexers(oldConfig, newConfig));
    } catch (Exception e) {
        logger.error("Error while migrating indexer settings", e);
        messages.add("Error while migrating indexer settings. Please check and set the values manually.");
    }
    try {
        messages.addAll(migrateSearching(oldConfig, newConfig.getSearching()));
    } catch (Exception e) {
        logger.error("Error while migrating searching settings", e);
        messages.add("Error while migrating searching settings. Please check and set the values manually.");
    }
    try {
        messages.addAll(migrateAuth(oldConfig.getAuth(), newConfig.getAuth()));
    } catch (Exception e) {
        logger.error("Error while migrating auth settings", e);
        messages.add("Error while migrating auth settings. Please check and set the values manually.");
    }
    try {
        messages.addAll(migrateLogging(oldConfig.getMain().getLogging(), newConfig.getMain().getLogging()));
    } catch (Exception e) {
        logger.error("Error while migrating logging settings", e);
        messages.add("Error while migrating logging settings. Please check and set the values manually.");
    }
    try {
        messages.addAll(migrateCategories(oldConfig.getCategories(), newConfig.getCategoriesConfig()));
    } catch (Exception e) {
        logger.error("Error while migrating category settings", e);
        messages.add("Error while migrating category settings. Please check and set the values manually.");
    }
    try {
        messages.addAll(migrateDownloaders(oldConfig, newConfig));
    } catch (Exception e) {
        logger.error("Error while migrating downloader settings", e);
        messages.add("Error while migrating downloader settings. Please check and set the values manually.");
    }
    configProvider.getBaseConfig().replace(newConfig);
    configProvider.getBaseConfig().save();
    eventPublisher.publishEvent(new MigrationMessageEvent("Completed migrating config with " + messages.size() + " messages"));
    return new ConfigMigrationResult(newConfig, messages);
}
Also used : Jdk8Module(com.fasterxml.jackson.datatype.jdk8.Jdk8Module) MigrationMessageEvent(org.nzbhydra.migration.FromPythonMigration.MigrationMessageEvent) YAMLFactory(com.fasterxml.jackson.dataformat.yaml.YAMLFactory) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) MalformedURLException(java.net.MalformedURLException) IOException(java.io.IOException)

Example 2 with MigrationMessageEvent

use of org.nzbhydra.migration.FromPythonMigration.MigrationMessageEvent in project nzbhydra2 by theotherp.

the class SqliteMigration method migrate.

protected void migrate() throws SQLException, IOException {
    logger.info("Starting database migration");
    eventPublisher.publishEvent(new MigrationMessageEvent("Starting database migration"));
    Map<Integer, IndexerEntity> oldIdToIndexersMap = migrateIndexers();
    Map<Integer, SearchEntity> oldIdToSearchesMap = migrateSearches();
    Statement statement = connection.createStatement();
    int databaseVersion = statement.executeQuery("SELECT version FROM versioninfo LIMIT 1").getInt(1);
    if (databaseVersion < 18) {
        logger.error("Expected database version to be at least 18 but got {}", databaseVersion);
        throw new SQLException("Expected database version to be at least 18 but got " + databaseVersion);
    }
    migrateIndexerApiAccesses(oldIdToIndexersMap);
    migrateIndexerSearches(oldIdToIndexersMap, oldIdToSearchesMap);
    migrateDownloads(oldIdToIndexersMap);
    logger.info("Finished database migration");
}
Also used : MigrationMessageEvent(org.nzbhydra.migration.FromPythonMigration.MigrationMessageEvent)

Example 3 with MigrationMessageEvent

use of org.nzbhydra.migration.FromPythonMigration.MigrationMessageEvent in project nzbhydra2 by theotherp.

the class SqliteMigration method migrateIndexerSearches.

protected void migrateIndexerSearches(Map<Integer, IndexerEntity> oldIdToIndexersMap, Map<Integer, SearchEntity> oldIdToSearchesMap) throws SQLException {
    Statement statement = connection.createStatement();
    int countIndexerSearches = getCount(statement, "INDEXERSEARCH");
    int countMigrated = 1;
    logger.info("Migrating {} indexer searches from old database", countIndexerSearches);
    eventPublisher.publishEvent(new MigrationMessageEvent("Migrating " + countIndexerSearches + " indexer search entries"));
    ResultSet oldIndexerSearch = statement.executeQuery("SELECT * FROM INDEXERSEARCH");
    IndexerSearchEntity newEntity;
    ProgressLogger progressLogger = new ProgressLogger(logger, 5, TimeUnit.SECONDS);
    progressLogger.expectedUpdates = countIndexerSearches;
    progressLogger.start();
    while (oldIndexerSearch.next()) {
        newEntity = new IndexerSearchEntity();
        newEntity.setSuccessful(oldIndexerSearch.getBoolean("successful"));
        newEntity.setIndexerEntity(oldIdToIndexersMap.get(oldIndexerSearch.getInt("indexer_id")));
        newEntity.setSearchEntity(oldIdToSearchesMap.get(oldIndexerSearch.getInt("search_id")));
        newEntity.setUniqueResults(oldIndexerSearch.getInt("uniqueResults"));
        newEntity.setProcessedResults(oldIndexerSearch.getInt("processedResults"));
        newEntity.setResultsCount(oldIndexerSearch.getInt("resultsCount"));
        entityManager.persist(newEntity);
        progressLogger.lightUpdate();
        if (countMigrated++ % 50 == 0) {
            entityManager.flush();
            entityManager.clear();
        }
    }
    statement.close();
    entityManager.flush();
    entityManager.clear();
    progressLogger.stop();
    logger.info("Successfully migrated indexer searches from old database");
    eventPublisher.publishEvent(new MigrationMessageEvent("Successfully migrated indexer searches from old database"));
}
Also used : MigrationMessageEvent(org.nzbhydra.migration.FromPythonMigration.MigrationMessageEvent) ProgressLogger(org.nzbhydra.logging.ProgressLogger)

Example 4 with MigrationMessageEvent

use of org.nzbhydra.migration.FromPythonMigration.MigrationMessageEvent in project nzbhydra2 by theotherp.

the class SqliteMigration method migrateSearches.

protected Map<Integer, SearchEntity> migrateSearches() throws SQLException {
    Map<Integer, SearchEntity> oldIdToNewEntity = new HashMap<>();
    Map<String, String> categoryMap = categoryProvider.getCategories().stream().map(Category::getName).collect(Collectors.toMap(x -> x.replace(" ", "").toLowerCase(), Function.identity()));
    Map<String, SearchType> oldTypeToNewMap = new HashMap<>();
    oldTypeToNewMap.put("general", SearchType.SEARCH);
    oldTypeToNewMap.put("book", SearchType.BOOK);
    oldTypeToNewMap.put("movie", SearchType.MOVIE);
    oldTypeToNewMap.put("tv", SearchType.TVSEARCH);
    oldTypeToNewMap.put("audio", SearchType.MUSIC);
    Map<String, IdType> oldIdTypeToNewMap = new HashMap<>();
    oldIdTypeToNewMap.put("rid", IdType.TVRAGE);
    oldIdTypeToNewMap.put("tvdbid", IdType.TVDB);
    oldIdTypeToNewMap.put("imdbid", IdType.IMDB);
    oldIdTypeToNewMap.put("tmdbid", IdType.TMDB);
    Statement statement = connection.createStatement();
    int searches = getCount(statement, "search");
    logger.info("Migrating {} searches from old database", searches);
    eventPublisher.publishEvent(new MigrationMessageEvent("Migrating " + searches + " search entries"));
    ResultSet oldSearches = statement.executeQuery("SELECT * FROM search");
    boolean hasAuthor = hasColumn(oldSearches, "author");
    boolean hasTitle = hasColumn(oldSearches, "title");
    int skippedSearches = 0;
    while (oldSearches.next()) {
        try {
            SearchEntity entity = new SearchEntity();
            String oldCategory = oldSearches.getString("category");
            String newCategory = (!Strings.isNullOrEmpty(oldCategory) && categoryMap.containsKey(oldCategory.toLowerCase())) ? categoryMap.get(oldCategory.toLowerCase()) : "All";
            entity.setCategoryName(newCategory);
            entity.setUsername(oldSearches.getString("username"));
            entity.setSeason(oldSearches.getObject("season") != null ? oldSearches.getInt("season") : null);
            entity.setEpisode(oldSearches.getString("episode"));
            entity.setQuery(oldSearches.getString("query"));
            if (hasAuthor) {
                entity.setAuthor(oldSearches.getString("author"));
            }
            if (hasTitle) {
                entity.setTitle(oldSearches.getString("title"));
            }
            entity.setSearchType(oldTypeToNewMap.getOrDefault(oldSearches.getString("type"), SearchType.SEARCH));
            if (oldSearches.getString("identifier_key") != null && oldSearches.getString("identifier_value") != null && oldIdTypeToNewMap.containsKey(oldSearches.getString("identifier_key"))) {
                String identifierKey = oldIdTypeToNewMap.get(oldSearches.getString("identifier_key")).name();
                IdentifierKeyValuePair keyValuePair = new IdentifierKeyValuePair(identifierKey, oldSearches.getString("identifier_value"));
                entity.setIdentifiers(Sets.newHashSet(keyValuePair));
            }
            entity.setSource((oldSearches.getBoolean("internal")) ? SearchSource.INTERNAL : SearchSource.API);
            Instant time;
            String timeString = oldSearches.getString("time");
            time = timestampToInstant(timeString);
            entity.setTime(time);
            oldIdToNewEntity.put(oldSearches.getInt("id"), entity);
        } catch (SQLException e) {
            logger.error("Problem while migrating search", e);
            skippedSearches++;
        }
    }
    logger.info("Saving search entities to database");
    searchRepository.save(oldIdToNewEntity.values());
    if (skippedSearches > 0) {
        String message = "Skipped " + skippedSearches + " of " + (skippedSearches + oldIdToNewEntity.size()) + " searches because the database entries could not be read";
        logger.warn(message);
        eventPublisher.publishEvent(new MigrationMessageEvent(message));
    } else {
        logger.info("Successfully migrated searches from old database");
        eventPublisher.publishEvent(new MigrationMessageEvent("Successfully migrated searches from old database"));
    }
    return oldIdToNewEntity;
}
Also used : java.sql(java.sql) java.util(java.util) org.nzbhydra.searching(org.nzbhydra.searching) Strings(joptsimple.internal.Strings) LoggerFactory(org.slf4j.LoggerFactory) LocalDateTime(java.time.LocalDateTime) Autowired(org.springframework.beans.factory.annotation.Autowired) Function(java.util.function.Function) FileDownloadEntity(org.nzbhydra.downloading.FileDownloadEntity) SearchSource(org.nzbhydra.searching.searchrequests.SearchRequest.SearchSource) FileDownloadStatus(org.nzbhydra.downloading.FileDownloadStatus) ApplicationEventPublisher(org.springframework.context.ApplicationEventPublisher) ZoneOffset(java.time.ZoneOffset) TypeReference(com.fasterxml.jackson.core.type.TypeReference) Category(org.nzbhydra.config.Category) Logger(org.slf4j.Logger) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) IdType(org.nzbhydra.mediainfo.InfoProvider.IdType) IOException(java.io.IOException) EntityManager(javax.persistence.EntityManager) PersistenceContext(javax.persistence.PersistenceContext) org.nzbhydra.indexers(org.nzbhydra.indexers) Instant(java.time.Instant) Collectors(java.util.stream.Collectors) Sets(com.google.common.collect.Sets) TimeUnit(java.util.concurrent.TimeUnit) FileDownloadAccessType(org.nzbhydra.config.FileDownloadAccessType) Component(org.springframework.stereotype.Component) ChronoUnit(java.time.temporal.ChronoUnit) ProgressLogger(org.nzbhydra.logging.ProgressLogger) DateTimeFormatter(java.time.format.DateTimeFormatter) MigrationMessageEvent(org.nzbhydra.migration.FromPythonMigration.MigrationMessageEvent) FileDownloadRepository(org.nzbhydra.downloading.FileDownloadRepository) Transactional(org.springframework.transaction.annotation.Transactional) Instant(java.time.Instant) MigrationMessageEvent(org.nzbhydra.migration.FromPythonMigration.MigrationMessageEvent) IdType(org.nzbhydra.mediainfo.InfoProvider.IdType)

Example 5 with MigrationMessageEvent

use of org.nzbhydra.migration.FromPythonMigration.MigrationMessageEvent in project nzbhydra2 by theotherp.

the class SqliteMigration method migrateDownloads.

private void migrateDownloads(Map<Integer, IndexerEntity> oldIdToIndexersMap) throws SQLException {
    Statement statement = connection.createStatement();
    int countDownloads = getCount(statement, "INDEXERNZBDOWNLOAD");
    logger.info("Migrating {} downloads from old database", countDownloads);
    eventPublisher.publishEvent(new MigrationMessageEvent("Migrating " + countDownloads + " NZB download entries"));
    ResultSet oldDownloads = statement.executeQuery("SELECT * FROM indexernzbdownload LEFT JOIN indexerapiaccess ON indexernzbdownload.apiAccess_id = indexerapiaccess.id");
    List<FileDownloadEntity> downloadEntities = new ArrayList<>();
    List<SearchResultEntity> dummySearchResultEntities = new ArrayList<>();
    while (oldDownloads.next()) {
        FileDownloadEntity entity = new FileDownloadEntity();
        entity.setTime(timestampToInstant(oldDownloads.getString("time")));
        IndexerEntity indexerEntity = oldIdToIndexersMap.get(oldDownloads.getInt("indexer_id"));
        if (indexerEntity == null) {
            logger.info("Skipping migration of download with indexer that doesn't exist anymore");
            continue;
        }
        entity.setError(oldDownloads.getString("error"));
        entity.setUsername(oldDownloads.getString("username"));
        entity.setAccessSource(oldDownloads.getBoolean("internal") ? SearchSource.INTERNAL : SearchSource.API);
        entity.setNzbAccessType(oldDownloads.getString("mode").equals("redirect") ? FileDownloadAccessType.REDIRECT : FileDownloadAccessType.PROXY);
        entity.setStatus(FileDownloadStatus.NONE);
        // long hash = hash64((result.getIndexer().getName() + result.getIndexerGuid() + result.getTitle() + result.getLink()));
        Instant dummyTime = Instant.now().minus(10000, ChronoUnit.DAYS);
        String title = oldDownloads.getString("title");
        if (title == null) {
            logger.warn("Skipping migration of download without title");
        }
        String randomIntSTring = String.valueOf(random.nextInt()) + indexerEntity.getName();
        // Must set a random link because the calculator would always return the same ID
        SearchResultEntity searchResultEntity = new SearchResultEntity(indexerEntity, dummyTime, title, "guid" + randomIntSTring, "link" + randomIntSTring, "details" + randomIntSTring, null, dummyTime);
        entity.setSearchResult(searchResultEntity);
        dummySearchResultEntities.add(searchResultEntity);
        downloadEntities.add(entity);
    }
    searchResultRepository.save(dummySearchResultEntities);
    downloadRepository.save(downloadEntities);
    logger.info("Successfully migrated downloads from old database");
    eventPublisher.publishEvent(new MigrationMessageEvent("Successfully migrated NZB download entries"));
}
Also used : Instant(java.time.Instant) MigrationMessageEvent(org.nzbhydra.migration.FromPythonMigration.MigrationMessageEvent) FileDownloadEntity(org.nzbhydra.downloading.FileDownloadEntity)

Aggregations

MigrationMessageEvent (org.nzbhydra.migration.FromPythonMigration.MigrationMessageEvent)7 ProgressLogger (org.nzbhydra.logging.ProgressLogger)3 ObjectMapper (com.fasterxml.jackson.databind.ObjectMapper)2 IOException (java.io.IOException)2 Instant (java.time.Instant)2 FileDownloadEntity (org.nzbhydra.downloading.FileDownloadEntity)2 TypeReference (com.fasterxml.jackson.core.type.TypeReference)1 YAMLFactory (com.fasterxml.jackson.dataformat.yaml.YAMLFactory)1 Jdk8Module (com.fasterxml.jackson.datatype.jdk8.Jdk8Module)1 Sets (com.google.common.collect.Sets)1 MalformedURLException (java.net.MalformedURLException)1 java.sql (java.sql)1 LocalDateTime (java.time.LocalDateTime)1 ZoneOffset (java.time.ZoneOffset)1 DateTimeFormatter (java.time.format.DateTimeFormatter)1 ChronoUnit (java.time.temporal.ChronoUnit)1 java.util (java.util)1 TimeUnit (java.util.concurrent.TimeUnit)1 Function (java.util.function.Function)1 Collectors (java.util.stream.Collectors)1