Don't migrate old databases

This commit is contained in:
Ruud
2014-10-05 11:05:56 +02:00
parent 230b7f47cc
commit 9de8ed2dee
+290 -275
View File
@@ -2,6 +2,7 @@ import json
import os import os
import time import time
import traceback import traceback
from sqlite3 import OperationalError
from CodernityDB.database import RecordNotFound from CodernityDB.database import RecordNotFound
from CodernityDB.index import IndexException, IndexNotFoundException, IndexConflict from CodernityDB.index import IndexException, IndexNotFoundException, IndexConflict
@@ -9,7 +10,7 @@ from couchpotato import CPLog
from couchpotato.api import addApiView from couchpotato.api import addApiView
from couchpotato.core.event import addEvent, fireEvent, fireEventAsync from couchpotato.core.event import addEvent, fireEvent, fireEventAsync
from couchpotato.core.helpers.encoding import toUnicode, sp from couchpotato.core.helpers.encoding import toUnicode, sp
from couchpotato.core.helpers.variable import getImdb, tryInt from couchpotato.core.helpers.variable import getImdb, tryInt, randomString
log = CPLog(__name__) log = CPLog(__name__)
@@ -311,312 +312,326 @@ class Database(object):
} }
migrate_data = {} migrate_data = {}
rename_old = False
c = conn.cursor() try:
for ml in migrate_list: c = conn.cursor()
migrate_data[ml] = {}
rows = migrate_list[ml]
try: for ml in migrate_list:
c.execute('SELECT %s FROM `%s`' % ('`' + '`,`'.join(rows) + '`', ml)) migrate_data[ml] = {}
except: rows = migrate_list[ml]
# ignore faulty destination_id database
if ml == 'category': try:
migrate_data[ml] = {} c.execute('SELECT %s FROM `%s`' % ('`' + '`,`'.join(rows) + '`', ml))
except:
# ignore faulty destination_id database
if ml == 'category':
migrate_data[ml] = {}
else:
rename_old = True
raise
for p in c.fetchall():
columns = {}
for row in migrate_list[ml]:
columns[row] = p[rows.index(row)]
if not migrate_data[ml].get(p[0]):
migrate_data[ml][p[0]] = columns
else:
if not isinstance(migrate_data[ml][p[0]], list):
migrate_data[ml][p[0]] = [migrate_data[ml][p[0]]]
migrate_data[ml][p[0]].append(columns)
conn.close()
log.info('Getting data took %s', time.time() - migrate_start)
db = self.getDB()
if not db.opened:
return
# Use properties
properties = migrate_data['properties']
log.info('Importing %s properties', len(properties))
for x in properties:
property = properties[x]
Env.prop(property.get('identifier'), property.get('value'))
# Categories
categories = migrate_data.get('category', [])
log.info('Importing %s categories', len(categories))
category_link = {}
for x in categories:
c = categories[x]
new_c = db.insert({
'_t': 'category',
'order': c.get('order', 999),
'label': toUnicode(c.get('label', '')),
'ignored': toUnicode(c.get('ignored', '')),
'preferred': toUnicode(c.get('preferred', '')),
'required': toUnicode(c.get('required', '')),
'destination': toUnicode(c.get('destination', '')),
})
category_link[x] = new_c.get('_id')
# Profiles
log.info('Importing profiles')
new_profiles = db.all('profile', with_doc = True)
new_profiles_by_label = {}
for x in new_profiles:
# Remove default non core profiles
if not x['doc'].get('core'):
db.delete(x['doc'])
else: else:
raise new_profiles_by_label[x['doc']['label']] = x['_id']
for p in c.fetchall(): profiles = migrate_data['profile']
columns = {} profile_link = {}
for row in migrate_list[ml]: for x in profiles:
columns[row] = p[rows.index(row)] p = profiles[x]
if not migrate_data[ml].get(p[0]): exists = new_profiles_by_label.get(p.get('label'))
migrate_data[ml][p[0]] = columns
# Update existing with order only
if exists and p.get('core'):
profile = db.get('id', exists)
profile['order'] = tryInt(p.get('order'))
profile['hide'] = p.get('hide') in [1, True, 'true', 'True']
db.update(profile)
profile_link[x] = profile.get('_id')
else: else:
if not isinstance(migrate_data[ml][p[0]], list):
migrate_data[ml][p[0]] = [migrate_data[ml][p[0]]]
migrate_data[ml][p[0]].append(columns)
conn.close() new_profile = {
'_t': 'profile',
'label': p.get('label'),
'order': int(p.get('order', 999)),
'core': p.get('core', False),
'qualities': [],
'wait_for': [],
'finish': []
}
log.info('Getting data took %s', time.time() - migrate_start) types = migrate_data['profiletype']
for profile_type in types:
p_type = types[profile_type]
if types[profile_type]['profile_id'] == p['id']:
if p_type['quality_id']:
new_profile['finish'].append(p_type['finish'])
new_profile['wait_for'].append(p_type['wait_for'])
new_profile['qualities'].append(migrate_data['quality'][p_type['quality_id']]['identifier'])
db = self.getDB() if len(new_profile['qualities']) > 0:
if not db.opened: new_profile.update(db.insert(new_profile))
return profile_link[x] = new_profile.get('_id')
else:
log.error('Corrupt profile list for "%s", using default.', p.get('label'))
# Use properties # Qualities
properties = migrate_data['properties'] log.info('Importing quality sizes')
log.info('Importing %s properties', len(properties)) new_qualities = db.all('quality', with_doc = True)
for x in properties: new_qualities_by_identifier = {}
property = properties[x] for x in new_qualities:
Env.prop(property.get('identifier'), property.get('value')) new_qualities_by_identifier[x['doc']['identifier']] = x['_id']
# Categories qualities = migrate_data['quality']
categories = migrate_data.get('category', []) quality_link = {}
log.info('Importing %s categories', len(categories)) for x in qualities:
category_link = {} q = qualities[x]
for x in categories: q_id = new_qualities_by_identifier[q.get('identifier')]
c = categories[x]
new_c = db.insert({ quality = db.get('id', q_id)
'_t': 'category', quality['order'] = q.get('order')
'order': c.get('order', 999), quality['size_min'] = tryInt(q.get('size_min'))
'label': toUnicode(c.get('label', '')), quality['size_max'] = tryInt(q.get('size_max'))
'ignored': toUnicode(c.get('ignored', '')), db.update(quality)
'preferred': toUnicode(c.get('preferred', '')),
'required': toUnicode(c.get('required', '')),
'destination': toUnicode(c.get('destination', '')),
})
category_link[x] = new_c.get('_id') quality_link[x] = quality
# Profiles # Titles
log.info('Importing profiles') titles = migrate_data['librarytitle']
new_profiles = db.all('profile', with_doc = True) titles_by_library = {}
new_profiles_by_label = {} for x in titles:
for x in new_profiles: title = titles[x]
if title.get('default'):
titles_by_library[title.get('libraries_id')] = title.get('title')
# Remove default non core profiles # Releases
if not x['doc'].get('core'): releaseinfos = migrate_data['releaseinfo']
db.delete(x['doc']) for x in releaseinfos:
else: info = releaseinfos[x]
new_profiles_by_label[x['doc']['label']] = x['_id']
profiles = migrate_data['profile'] # Skip if release doesn't exist for this info
profile_link = {} if not migrate_data['release'].get(info.get('release_id')):
for x in profiles:
p = profiles[x]
exists = new_profiles_by_label.get(p.get('label'))
# Update existing with order only
if exists and p.get('core'):
profile = db.get('id', exists)
profile['order'] = tryInt(p.get('order'))
profile['hide'] = p.get('hide') in [1, True, 'true', 'True']
db.update(profile)
profile_link[x] = profile.get('_id')
else:
new_profile = {
'_t': 'profile',
'label': p.get('label'),
'order': int(p.get('order', 999)),
'core': p.get('core', False),
'qualities': [],
'wait_for': [],
'finish': []
}
types = migrate_data['profiletype']
for profile_type in types:
p_type = types[profile_type]
if types[profile_type]['profile_id'] == p['id']:
if p_type['quality_id']:
new_profile['finish'].append(p_type['finish'])
new_profile['wait_for'].append(p_type['wait_for'])
new_profile['qualities'].append(migrate_data['quality'][p_type['quality_id']]['identifier'])
if len(new_profile['qualities']) > 0:
new_profile.update(db.insert(new_profile))
profile_link[x] = new_profile.get('_id')
else:
log.error('Corrupt profile list for "%s", using default.', p.get('label'))
# Qualities
log.info('Importing quality sizes')
new_qualities = db.all('quality', with_doc = True)
new_qualities_by_identifier = {}
for x in new_qualities:
new_qualities_by_identifier[x['doc']['identifier']] = x['_id']
qualities = migrate_data['quality']
quality_link = {}
for x in qualities:
q = qualities[x]
q_id = new_qualities_by_identifier[q.get('identifier')]
quality = db.get('id', q_id)
quality['order'] = q.get('order')
quality['size_min'] = tryInt(q.get('size_min'))
quality['size_max'] = tryInt(q.get('size_max'))
db.update(quality)
quality_link[x] = quality
# Titles
titles = migrate_data['librarytitle']
titles_by_library = {}
for x in titles:
title = titles[x]
if title.get('default'):
titles_by_library[title.get('libraries_id')] = title.get('title')
# Releases
releaseinfos = migrate_data['releaseinfo']
for x in releaseinfos:
info = releaseinfos[x]
# Skip if release doesn't exist for this info
if not migrate_data['release'].get(info.get('release_id')):
continue
if not migrate_data['release'][info.get('release_id')].get('info'):
migrate_data['release'][info.get('release_id')]['info'] = {}
migrate_data['release'][info.get('release_id')]['info'][info.get('identifier')] = info.get('value')
releases = migrate_data['release']
releases_by_media = {}
for x in releases:
release = releases[x]
if not releases_by_media.get(release.get('movie_id')):
releases_by_media[release.get('movie_id')] = []
releases_by_media[release.get('movie_id')].append(release)
# Type ids
types = migrate_data['filetype']
type_by_id = {}
for t in types:
type = types[t]
type_by_id[type.get('id')] = type
# Media
log.info('Importing %s media items', len(migrate_data['movie']))
statuses = migrate_data['status']
libraries = migrate_data['library']
library_files = migrate_data['library_files__file_library']
releases_files = migrate_data['release_files__file_release']
all_files = migrate_data['file']
poster_type = migrate_data['filetype']['poster']
medias = migrate_data['movie']
for x in medias:
m = medias[x]
status = statuses.get(m['status_id']).get('identifier')
l = libraries.get(m['library_id'])
# Only migrate wanted movies, Skip if no identifier present
if not l or not getImdb(l.get('identifier')): continue
profile_id = profile_link.get(m['profile_id'])
category_id = category_link.get(m['category_id'])
title = titles_by_library.get(m['library_id'])
releases = releases_by_media.get(x, [])
info = json.loads(l.get('info', ''))
files = library_files.get(m['library_id'], [])
if not isinstance(files, list):
files = [files]
added_media = fireEvent('movie.add', {
'info': info,
'identifier': l.get('identifier'),
'profile_id': profile_id,
'category_id': category_id,
'title': title
}, force_readd = False, search_after = False, update_after = False, notify_after = False, status = status, single = True)
if not added_media:
log.error('Failed adding media %s: %s', (l.get('identifier'), info))
continue
added_media['files'] = added_media.get('files', {})
for f in files:
ffile = all_files[f.get('file_id')]
# Only migrate posters
if ffile.get('type_id') == poster_type.get('id'):
if ffile.get('path') not in added_media['files'].get('image_poster', []) and os.path.isfile(ffile.get('path')):
added_media['files']['image_poster'] = [ffile.get('path')]
break
if 'image_poster' in added_media['files']:
db.update(added_media)
for rel in releases:
empty_info = False
if not rel.get('info'):
empty_info = True
rel['info'] = {}
quality = quality_link.get(rel.get('quality_id'))
if not quality:
continue continue
release_status = statuses.get(rel.get('status_id')).get('identifier') if not migrate_data['release'][info.get('release_id')].get('info'):
migrate_data['release'][info.get('release_id')]['info'] = {}
if rel['info'].get('download_id'): migrate_data['release'][info.get('release_id')]['info'][info.get('identifier')] = info.get('value')
status_support = rel['info'].get('download_status_support', False) in [True, 'true', 'True']
rel['info']['download_info'] = {
'id': rel['info'].get('download_id'),
'downloader': rel['info'].get('download_downloader'),
'status_support': status_support,
}
# Add status to keys releases = migrate_data['release']
rel['info']['status'] = release_status releases_by_media = {}
if not empty_info: for x in releases:
fireEvent('release.create_from_search', [rel['info']], added_media, quality, single = True) release = releases[x]
else: if not releases_by_media.get(release.get('movie_id')):
release = { releases_by_media[release.get('movie_id')] = []
'_t': 'release',
'identifier': rel.get('identifier'),
'media_id': added_media.get('_id'),
'quality': quality.get('identifier'),
'status': release_status,
'last_edit': int(time.time()),
'files': {}
}
# Add downloader info if provided releases_by_media[release.get('movie_id')].append(release)
try:
release['download_info'] = rel['info']['download_info']
del rel['download_info']
except:
pass
# Add files # Type ids
release_files = releases_files.get(rel.get('id'), []) types = migrate_data['filetype']
if not isinstance(release_files, list): type_by_id = {}
release_files = [release_files] for t in types:
type = types[t]
type_by_id[type.get('id')] = type
if len(release_files) == 0: # Media
log.info('Importing %s media items', len(migrate_data['movie']))
statuses = migrate_data['status']
libraries = migrate_data['library']
library_files = migrate_data['library_files__file_library']
releases_files = migrate_data['release_files__file_release']
all_files = migrate_data['file']
poster_type = migrate_data['filetype']['poster']
medias = migrate_data['movie']
for x in medias:
m = medias[x]
status = statuses.get(m['status_id']).get('identifier')
l = libraries.get(m['library_id'])
# Only migrate wanted movies, Skip if no identifier present
if not l or not getImdb(l.get('identifier')): continue
profile_id = profile_link.get(m['profile_id'])
category_id = category_link.get(m['category_id'])
title = titles_by_library.get(m['library_id'])
releases = releases_by_media.get(x, [])
info = json.loads(l.get('info', ''))
files = library_files.get(m['library_id'], [])
if not isinstance(files, list):
files = [files]
added_media = fireEvent('movie.add', {
'info': info,
'identifier': l.get('identifier'),
'profile_id': profile_id,
'category_id': category_id,
'title': title
}, force_readd = False, search_after = False, update_after = False, notify_after = False, status = status, single = True)
if not added_media:
log.error('Failed adding media %s: %s', (l.get('identifier'), info))
continue
added_media['files'] = added_media.get('files', {})
for f in files:
ffile = all_files[f.get('file_id')]
# Only migrate posters
if ffile.get('type_id') == poster_type.get('id'):
if ffile.get('path') not in added_media['files'].get('image_poster', []) and os.path.isfile(ffile.get('path')):
added_media['files']['image_poster'] = [ffile.get('path')]
break
if 'image_poster' in added_media['files']:
db.update(added_media)
for rel in releases:
empty_info = False
if not rel.get('info'):
empty_info = True
rel['info'] = {}
quality = quality_link.get(rel.get('quality_id'))
if not quality:
continue continue
for f in release_files: release_status = statuses.get(rel.get('status_id')).get('identifier')
rfile = all_files.get(f.get('file_id'))
if not rfile: if rel['info'].get('download_id'):
status_support = rel['info'].get('download_status_support', False) in [True, 'true', 'True']
rel['info']['download_info'] = {
'id': rel['info'].get('download_id'),
'downloader': rel['info'].get('download_downloader'),
'status_support': status_support,
}
# Add status to keys
rel['info']['status'] = release_status
if not empty_info:
fireEvent('release.create_from_search', [rel['info']], added_media, quality, single = True)
else:
release = {
'_t': 'release',
'identifier': rel.get('identifier'),
'media_id': added_media.get('_id'),
'quality': quality.get('identifier'),
'status': release_status,
'last_edit': int(time.time()),
'files': {}
}
# Add downloader info if provided
try:
release['download_info'] = rel['info']['download_info']
del rel['download_info']
except:
pass
# Add files
release_files = releases_files.get(rel.get('id'), [])
if not isinstance(release_files, list):
release_files = [release_files]
if len(release_files) == 0:
continue continue
file_type = type_by_id.get(rfile.get('type_id')).get('identifier') for f in release_files:
rfile = all_files.get(f.get('file_id'))
if not rfile:
continue
if not release['files'].get(file_type): file_type = type_by_id.get(rfile.get('type_id')).get('identifier')
release['files'][file_type] = []
release['files'][file_type].append(rfile.get('path')) if not release['files'].get(file_type):
release['files'][file_type] = []
try: release['files'][file_type].append(rfile.get('path'))
rls = db.get('release_identifier', rel.get('identifier'), with_doc = True)['doc']
rls.update(release) try:
db.update(rls) rls = db.get('release_identifier', rel.get('identifier'), with_doc = True)['doc']
except: rls.update(release)
db.insert(release) db.update(rls)
except:
db.insert(release)
log.info('Total migration took %s', time.time() - migrate_start)
log.info('=' * 30)
rename_old = True
except OperationalError:
log.error('Migrating from faulty database, probably a (too) old version: %s', traceback.format_exc())
except:
log.error('Migration failed: %s', traceback.format_exc())
log.info('Total migration took %s', time.time() - migrate_start)
log.info('=' * 30)
# rename old database # rename old database
log.info('Renaming old database to %s ', old_db + '.old') if rename_old:
os.rename(old_db, old_db + '.old') random = randomString()
log.info('Renaming old database to %s ', '%s.%s_old' % (old_db, random))
os.rename(old_db, '%s.%s_old' % (old_db, random))
if os.path.isfile(old_db + '-wal'): if os.path.isfile(old_db + '-wal'):
os.rename(old_db + '-wal', old_db + '-wal.old') os.rename(old_db + '-wal', '%s-wal.%s_old' % (old_db, random))
if os.path.isfile(old_db + '-shm'): if os.path.isfile(old_db + '-shm'):
os.rename(old_db + '-shm', old_db + '-shm.old') os.rename(old_db + '-shm', '%s-shm.%s_old' % (old_db, random))