const {single} = require('./mysql') const forBigTable = require('./forBigTable') const { BrowserWindow } = require("electron"); const url = require('url') const path = require('path') const fs = require('fs') const glob = require("glob") const asyncForEach = require('./asyncForEach') const {torrentTypeDetect} = require('../app/content'); const getTorrent = require('./gettorrent') const startSphinx = require('./sphinx') const currentVersion = 5 module.exports = async (callback, mainWindow, sphinxApp) => { let sphinx = await single().waitConnection() const setVersion = async (version) => { await sphinx.query(`delete from version where id = 1`) await sphinx.query(`insert into version(id, version) values(1, ${version})`) if(sphinxApp) fs.writeFileSync(`${sphinxApp.directoryPath}/version.vrs`, version) } let patchWindow; const openPatchWindow = () => { if(patchWindow) return if(!BrowserWindow) return if(mainWindow) mainWindow.hide() patchWindow = new BrowserWindow({width: 800, height: 400, closable: false}) patchWindow.setMenu(null) patchWindow.loadURL("data:text/html;charset=utf-8," + encodeURI(` Database patching...
`)) } const patch = async (version) => { logT('patcher', 'db version', version) switch(version) { case 1: { logT('patcher', 'patch db to version 2') openPatchWindow() let i = 1 const torrents = (await sphinx.query("SELECT COUNT(*) AS c FROM torrents"))[0].c const files = (await sphinx.query("SELECT COUNT(*) AS c FROM files"))[0].c await forBigTable(sphinx, 'torrents', async (torrent) => { logT('patcher', 'update index', torrent.id, torrent.name, '[', i, 'of', torrents, ']') if(patchWindow) patchWindow.webContents.send('reindex', {field: torrent.name, index: i++, all: torrents, torrent: true}) torrent.nameIndex = torrent.name await sphinx.query(`DELETE FROM torrents WHERE id = ${torrent.id}`) await sphinx.insertValues('torrents', torrent) }) i = 1 await forBigTable(sphinx, 'files', async (file) => { logT('patcher', 'update index', file.id, file.path, '[', i, 'of', files, ']') if(patchWindow) patchWindow.webContents.send('reindex', {field: file.path, index: i++, all: files}) file.pathIndex = file.path await sphinx.query(`DELETE FROM files WHERE id = ${file.id}`) await sphinx.insertValues('files', file) }) await setVersion(2) } case 2: { openPatchWindow() logT('patcher', 'optimizing torrents') if(patchWindow) patchWindow.webContents.send('optimize', {field: 'torrents'}) sphinx.query(`OPTIMIZE INDEX torrents`) await sphinxApp.waitOptimized('torrents') logT('patcher', 'optimizing files') if(patchWindow) patchWindow.webContents.send('optimize', {field: 'files'}) sphinx.query(`OPTIMIZE INDEX files`) await sphinxApp.waitOptimized('files') await setVersion(3) } case 3: { openPatchWindow() // block xxx let bad = 0 let i = 1 const torrents = (await sphinx.query("SELECT COUNT(*) AS c FROM torrents"))[0].c await forBigTable(sphinx, 'torrents', async (torrent) => { logT('patcher', 'update index', torrent.id, torrent.name, '[', i, 'of', torrents, '] - delete:', bad) if(patchWindow) patchWindow.webContents.send('reindex', {field: torrent.name, index: i++, all: torrents, torrent: true}) if(torrent.contentcategory == 'xxx') { delete torrent.contentcategory delete torrent.contenttype torrent = await getTorrent(sphinx, null, torrent) // get files torrentTypeDetect(torrent, torrent.filesList) if(torrent.contentType == 'bad') { logT('patcher', 'remove bad torrent', torrent.name) bad++ await sphinx.query(`DELETE FROM torrents WHERE hash = '${torrent.hash}'`) await sphinx.query(`DELETE FROM files WHERE hash = '${torrent.hash}'`) } } }) logT('patcher', 'removed', bad, 'torrents') await setVersion(4) } case 4: { openPatchWindow() let i = 1 const torrents = (await sphinx.query("SELECT COUNT(*) AS c FROM torrents"))[0].c let torrentsArray = [] let patch = 1 await forBigTable(sphinx, 'torrents', async (torrent) => { logT('patcher', 'remember index', torrent.id, torrent.name, '[', i, 'of', torrents, ']') if(patchWindow) patchWindow.webContents.send('reindex', {field: torrent.name, index: i++, all: torrents, torrent: true}) torrentsArray.push(torrent) // keep memory safe if(torrentsArray.length >= 20000) { fs.writeFileSync(`${sphinxApp.directoryPath}/torrents.patch.${patch++}`, JSON.stringify(torrentsArray, null, 4), 'utf8'); logT('patcher', 'write torrents dump', `${sphinxApp.directoryPath}/torrents.patch.${patch - 1}`) torrentsArray = [] } }) // keep last elemets if(torrentsArray.length > 0) { fs.writeFileSync(`${sphinxApp.directoryPath}/torrents.patch.${patch}`, JSON.stringify(torrentsArray, null, 4), 'utf8'); logT('patcher', 'write torrents dump', `${sphinxApp.directoryPath}/torrents.patch.${patch}`) torrentsArray = [] } else { patch-- //no last patch } // stop sphinx await new Promise((resolve) => { // reopen sphinx sphinx.destroy() // destory connection sphinxApp.stop(resolve, true) }) logT('patcher', 'sphinx stoped for patching') await new Promise((resolve) => { glob(`${sphinxApp.directoryPathDb}/torrents.*`, function (er, files) { files.forEach(file => { logT('patcher', 'clear torrents file', file) fs.unlinkSync(path.resolve(file)) }) resolve() }) }) logT('patcher', 'cleaned torrents db structure, rectreating again') i = 1 await new Promise((resolve) => { // reopen sphinx sphinxApp = sphinxApp.start(async () => { sphinx = await single().waitConnection() resolve() }) // same args }) logT('patcher', 'sphinx restarted, patch db now') for(let k = 1; k <= patch; k++) { torrentsArray = JSON.parse(fs.readFileSync(`${sphinxApp.directoryPath}/torrents.patch.${k}`, 'utf8')) logT('patcher', 'read torrents dump', `${sphinxApp.directoryPath}/torrents.patch.${k}`) await asyncForEach(torrentsArray, async (torrent) => { logT('patcher', 'update index', torrent.id, torrent.name, '[', i, 'of', torrents, ']') if(patchWindow) patchWindow.webContents.send('reindex', {field: torrent.name, index: i++, all: torrents, torrent: true}) torrent.nameIndex = torrent.name await sphinx.query(`DELETE FROM torrents WHERE id = ${torrent.id}`) await sphinx.insertValues('torrents', torrent) }) } await new Promise((resolve) => { glob(`${sphinxApp.directoryPath}/torrents.patch.*`, function (er, files) { files.forEach(file => { logT('patcher', 'clear dump file', file) fs.unlinkSync(path.resolve(file)) }) resolve() }) }) torrentsArray = null logT('patcher', 'optimizing torrents') if(patchWindow) patchWindow.webContents.send('optimize', {field: 'torrents'}) sphinx.query(`OPTIMIZE INDEX torrents`) await sphinxApp.waitOptimized('torrents') await setVersion(5) } } logT('patcher', 'db patch done') sphinx.destroy() if(patchWindow) { patchWindow.destroy() if(mainWindow) mainWindow.show() } callback() } // init of db, we can set version to last if(sphinxApp && sphinxApp.isInitDb) { logT('patcher', 'new db, set version to last version', currentVersion) await setVersion(currentVersion) } sphinx.query('select * from version', async (err, version) => { if(err) { logTE('patcher', 'error on version get on db patch') return } if(!version || !version[0] || !version[0].version) { if(sphinxApp && fs.existsSync(`${sphinxApp.directoryPath}/version.vrs`)) { const ver = parseInt(fs.readFileSync(`${sphinxApp.directoryPath}/version.vrs`)) if(ver > 0) { logT('patcher', 'readed version from version.vrs', ver) patch(ver) } else { logT('patcher', 'error: bad version in version.vrs') } } else { logT('patcher', 'version not founded, set db version to 1') await setVersion(1) patch(1) } } else { patch(version[0].version) } }) }