fix(windows): fix some startup problem under windows platform

This commit is contained in:
Alexey Kasyanchuk 2019-11-04 23:54:46 +03:00
parent d94656a347
commit 177d6ffc1a
5 changed files with 87 additions and 37 deletions

View File

@ -111,7 +111,7 @@
"cheerio": "^1.0.0-rc.2", "cheerio": "^1.0.0-rc.2",
"compare-versions": "^3.5.0", "compare-versions": "^3.5.0",
"debug": "^4.1.1", "debug": "^4.1.1",
"detect-onebyte-encoding": "^1.0.2", "detect-onebyte-encoding": "^1.0.3",
"electron-context-menu": "^0.15.0", "electron-context-menu": "^0.15.0",
"electron-log": "^3.0.8", "electron-log": "^3.0.8",
"electron-updater": "^4.1.2", "electron-updater": "^4.1.2",

View File

@ -174,7 +174,8 @@ autoUpdater.on('update-downloaded', () => {
let tray = undefined let tray = undefined
app.on("ready", async () => { app.on("ready", async () => {
sphinx = await startSphinx(() => { let rootPath;
({ sphinx, rootPath } = await startSphinx(() => {
mainWindow = createWindow("main", { mainWindow = createWindow("main", {
width: 1000, width: 1000,
@ -333,7 +334,14 @@ app.on("ready", async () => {
}, app.getPath("userData"), () => { }, app.getPath("userData"), () => {
stopped = true stopped = true
app.quit() app.quit()
}) }, {
noWindowsReEncoding: process.argv.includes('--noreencoding')
}))
// After configuration of sphinx user directory can be changed
if(app.getPath("userData") !== rootPath) {
logT('app', 'changed configuration user directory:', rootPath)
app.setPath("userData", rootPath);
}
}); });
let stopProtect = false let stopProtect = false
@ -363,6 +371,11 @@ const stop = () => {
else if(sphinx) else if(sphinx)
{ {
sphinx.stop() sphinx.stop()
if(sphinx.windowsEncodingFix) {
logT('app', 'perform restart because of bad config');
app.relaunch({ args: process.argv.slice(1).concat(['--noreencoding']) })
app.exit(0)
}
} }
else else
{ {

View File

@ -0,0 +1,7 @@
module.exports = (str) => {
for(let i = 0; i < str.length; i++) {
if(str.charCodeAt(i) > 191)
return false;
}
return true;
}

View File

@ -71,13 +71,13 @@ io.on('connection', (socket) =>
const start = async () => const start = async () =>
{ {
sphinx = await startSphinx(() => { ({ sphinx } = await startSphinx(() => {
dbPatcher(() => { dbPatcher(() => {
spider = new spiderCall((...data) => io.sockets.emit(...data), (message, callback) => { spider = new spiderCall((...data) => io.sockets.emit(...data), (message, callback) => {
socketMessages[message] = callback socketMessages[message] = callback
}, path.resolve(packageJson.serverDataDirectory), packageJson.version, 'production') }, path.resolve(packageJson.serverDataDirectory), packageJson.version, 'production')
}, null, sphinx) }, null, sphinx)
}, path.resolve(packageJson.serverDataDirectory), () => {}) }, path.resolve(packageJson.serverDataDirectory), () => {}))
} }
start() start()

View File

@ -13,6 +13,9 @@ const _ = require('lodash')
const isRunning = require('is-running') const isRunning = require('is-running')
const portCheck = require('./portCheck') const portCheck = require('./portCheck')
const detectOnebyteEncoding = require('detect-onebyte-encoding') const detectOnebyteEncoding = require('detect-onebyte-encoding')
const isOneByteEncoding = require('./detectOneByte')
const {promisify} = require('util');
const mkdirp = promisify(require('mkdirp'))
const findGoodPort = async (port, host) => { const findGoodPort = async (port, host) => {
while (!(await portCheck(port, host))) { while (!(await portCheck(port, host))) {
@ -22,12 +25,12 @@ const findGoodPort = async (port, host) => {
return port return port
} }
const writeSphinxConfig = async (path, dbPath) => { const writeSphinxConfig = async (rootPath, dbPath, params = {}) => {
appConfig.sphinx.port = await findGoodPort(appConfig.sphinx.port) appConfig.sphinx.port = await findGoodPort(appConfig.sphinx.port)
appConfig.sphinx.interfacePort = await findGoodPort(appConfig.sphinx.interfacePort) appConfig.sphinx.interfacePort = await findGoodPort(appConfig.sphinx.interfacePort)
appConfig.sphinx = appConfig.sphinx appConfig.sphinx = appConfig.sphinx
let config = ` let generateConfig = () => (`
index torrents index torrents
{ {
type = rt type = rt
@ -109,12 +112,40 @@ const writeSphinxConfig = async (path, dbPath) => {
preopen_indexes = 1 preopen_indexes = 1
unlink_old = 1 unlink_old = 1
workers = threads # for RT to work workers = threads # for RT to work
pid_file = ${path}/searchd.pid pid_file = ${rootPath}/searchd.pid
log = ${path}/searchd.log log = ${rootPath}/searchd.log
query_log = ${path}/query.log query_log = ${rootPath}/query.log
binlog_path = ${path} binlog_path = ${rootPath}
} }
`; `);
let config = generateConfig()
// fix db path under windows platform (one-byte path)
let windowsEncodingFix = false;
if(/^win/.test(process.platform) && (!isOneByteEncoding(dbPath) || !isOneByteEncoding(rootPath)))
{
logT('sphinx', 'detected non-one byte encoding, trying to fix config for db path', dbPath, params.noWindowsReEncoding)
let encoding = detectOnebyteEncoding(rootPath + dbPath)
if (encoding !== 'utf8' && !params.noWindowsReEncoding) {
config = iconv.encode(config, encoding)
logT('sphinx', 'config encoded to', encoding)
windowsEncodingFix = true
} else {
logT('sphinx', 'config encoded with utf8, moving config to some root directory')
while(!isOneByteEncoding(dbPath) || !(fs.statSync(dbPath).mode & 0x92))
dbPath = path.dirname(dbPath)
while(!isOneByteEncoding(rootPath) || !(fs.statSync(rootPath).mode & 0x92))
rootPath = path.dirname(rootPath)
dbPath += "/RatsConfig"
rootPath += "/RatsConfig"
await mkdirp(dbPath)
await mkdirp(rootPath)
logT('sphinx', 'changed root directory', rootPath)
logT('sphinx', 'changed db directory', dbPath)
config = generateConfig()
}
}
// clear dir in test env // clear dir in test env
if(env && env.name === 'test') if(env && env.name === 'test')
@ -127,10 +158,10 @@ const writeSphinxConfig = async (path, dbPath) => {
} }
}); });
fs.readdirSync(path).forEach(function(file, index){ fs.readdirSync(rootPath).forEach(function(file, index){
if(!file.startsWith('binlog')) if(!file.startsWith('binlog'))
return; return;
const curPath = path + "/" + file; const curPath = rootPath + "/" + file;
if (!fs.lstatSync(curPath).isDirectory()) { if (!fs.lstatSync(curPath).isDirectory()) {
fs.unlinkSync(curPath); fs.unlinkSync(curPath);
} }
@ -139,9 +170,9 @@ const writeSphinxConfig = async (path, dbPath) => {
} }
// clean query.log because it too large and don't consist any good info // clean query.log because it too large and don't consist any good info
if(fs.existsSync(`${path}/query.log`)) if(fs.existsSync(`${rootPath}/query.log`))
{ {
fs.unlinkSync(`${path}/query.log`) fs.unlinkSync(`${rootPath}/query.log`)
} }
let isInitDb = false let isInitDb = false
@ -151,33 +182,20 @@ const writeSphinxConfig = async (path, dbPath) => {
isInitDb = true isInitDb = true
} }
// fix db path under windows platform (one-byte path) fs.writeFileSync(`${rootPath}/sphinx.conf`, config)
if(/^win/.test(process.platform)) logT('sphinx', `writed sphinx config to ${rootPath}`)
{
let encoding = detectOnebyteEncoding(dbPath)
let encoding2 = detectOnebyteEncoding(path)
if(encoding != encoding2)
{
encoding = detectOnebyteEncoding(config)
}
config = iconv.encode(config, encoding)
logT('sphinx', 'config encoded to', encoding)
}
fs.writeFileSync(`${path}/sphinx.conf`, config)
logT('sphinx', `writed sphinx config to ${path}`)
logT('sphinx', 'db path:', dbPath) logT('sphinx', 'db path:', dbPath)
return {isInitDb} return {isInitDb, rootPath, dbPath, windowsEncodingFix}
} }
module.exports = async (callback, dataDirectory, onClose) => { module.exports = async (callback, dataDirectory, onClose, params = {}) => {
const start = async (callback) => { const start = async (callback) => {
const sphinxPath = path.resolve(appPath('searchd')) const sphinxPath = path.resolve(appPath('searchd'))
logT('sphinx', 'Sphinx Path:', sphinxPath) logT('sphinx', 'Sphinx Path:', sphinxPath)
const sphinxConfigDirectory = dataDirectory let sphinxConfigDirectory = dataDirectory
appConfig['dbPath'] = appConfig.dbPath && appConfig.dbPath.length > 0 ? appConfig.dbPath : sphinxConfigDirectory; appConfig['dbPath'] = appConfig.dbPath && appConfig.dbPath.length > 0 ? appConfig.dbPath : sphinxConfigDirectory;
// on portable dir can move database directory // on portable dir can move database directory
if(!fs.existsSync(appConfig.dbPath) && fs.existsSync(sphinxConfigDirectory)) if(!fs.existsSync(appConfig.dbPath) && fs.existsSync(sphinxConfigDirectory))
@ -191,7 +209,13 @@ module.exports = async (callback, dataDirectory, onClose) => {
if(isSphinxExternal) if(isSphinxExternal)
logT('sphinx', `founded running sphinx instance in ${sphinxPid}, using it`) logT('sphinx', `founded running sphinx instance in ${sphinxPid}, using it`)
const { isInitDb } = isSphinxExternal ? {isInitDb: false} : await writeSphinxConfig(sphinxConfigDirectory, appConfig.dbPath) const { isInitDb, rootPath, dbPath, windowsEncodingFix } = isSphinxExternal ? {isInitDb: false} : await writeSphinxConfig(sphinxConfigDirectory, appConfig.dbPath, params)
// on windows directory can be changed during sphinx bug with one byte path
if (rootPath != sphinxConfigDirectory || dbPath != appConfig.dbPath)
{
sphinxConfigDirectory = rootPath;
appConfig.dbPath = dbPath;
}
const config = `${sphinxConfigDirectory}/sphinx.conf` const config = `${sphinxConfigDirectory}/sphinx.conf`
const options = ['--config', config] const options = ['--config', config]
@ -228,7 +252,13 @@ module.exports = async (callback, dataDirectory, onClose) => {
{ {
sphinx.fixDatabase() sphinx.fixDatabase()
} }
if(windowsEncodingFix && data.includes('failed to parse config file'))
{
logT('sphinx', 'encoding rewrite failed, forcing restart of application to fix that problem')
sphinx.windowsEncodingFix = true;
}
const checkOptimized = String(data).match(/index ([\w]+): optimized/) const checkOptimized = String(data).match(/index ([\w]+): optimized/)
if(checkOptimized) if(checkOptimized)
{ {
@ -321,7 +351,7 @@ module.exports = async (callback, dataDirectory, onClose) => {
if (isSphinxExternal && callback) setTimeout(()=>{logT('sphinx', 'external sphinx signalled');callback()}, 0); if (isSphinxExternal && callback) setTimeout(()=>{logT('sphinx', 'external sphinx signalled');callback()}, 0);
return sphinx return {sphinx, rootPath: sphinxConfigDirectory, dbPath}
} }
return await start(callback) return await start(callback)