Cross-platform support (Win, MacOS, Linux)

-All shell scripts have been removed and replaced with javascript equivalents which allows for better platform independence
-All scripts have been improved over the older shell scripts to be more functional and dynamic
-Updated all applicable cmds in the package.json to target the new js scripts + added the backup, restore and delete database functions to the list
-Removed the json and strip-json-comments-cli packages as they are no longer needed
-Added a new package realine-sync
-Updated cluster code with better Windows support when shutting down the explorer
-Backup and Restore scripts now use mongo's own encryption instead of tar.gz by default. Older tar.gz backups can still be restored as long as the tar.gz suffix is explicitly added
-Backup and Restore scripts now support connecting to remote database based on the mongo details in settings.json
-Updated README to include a new line for the 'platform independence' feature, updated script cmds and notes about certain steps being Linux only
This commit is contained in:
Joe Uhren
2022-04-23 11:28:32 -06:00
parent 5eeb6ed0c0
commit 8e32e294b7
21 changed files with 777 additions and 557 deletions
+44 -29
View File
@@ -80,6 +80,7 @@ Table of Contents
- Chart.js v3.6.1
- chartjs-plugin-crosshair v1.2.0 ([https://github.com/abelheinsbroek/chartjs-plugin-crosshair](https://github.com/abelheinsbroek/chartjs-plugin-crosshair))
- flag-icon-css v4.1.4 ([https://github.com/lipis/flag-icon-css](https://github.com/lipis/flag-icon-css))
- Platform independent (tested to run on Windows, MacOS and Linux) **NOTE:** Most of the instructions in this guide were written for use with Linux and may need to be modified when using another OS
- Mobile-friendly
- Sass support
- Pages/features:
@@ -291,7 +292,7 @@ npm start
or (useful for crontab):
```
npm run prestart && /path/to/node --stack-size=10000 ./bin/cluster
cd /path/to/explorer && /path/to/npm run prestart && /path/to/node --stack-size=10000 ./bin/cluster
```
**NOTE:** mongod must be running to start the explorer.
@@ -305,7 +306,7 @@ npm run start-instance
or (useful for crontab):
```
npm run prestart && /path/to/node --stack-size=10000 ./bin/instance
cd /path/to/explorer && /path/to/npm run prestart && /path/to/node --stack-size=10000 ./bin/instance
```
#### Stop Explorer (Use for Testing)
@@ -319,7 +320,7 @@ npm stop
or (useful for crontab):
```
sh ./scripts/stop_explorer.sh
cd /path/to/explorer && /path/to/node ./scripts/stop_explorer.js
```
#### Start Explorer Using PM2 (Recommended for Production)
@@ -335,10 +336,10 @@ npm run start-pm2
or (useful for crontab):
```
npm run prestart "pm2" && /path/to/pm2 start ./bin/instance -i 0 --node-args="--stack-size=10000"
cd /path/to/explorer && /path/to/npm run prestart "pm2" && /path/to/pm2 start ./bin/instance -i 0 --node-args="--stack-size=10000"
```
**NOTE:** Use the following cmd to find the install path for PM2:
**NOTE:** Use the following cmd to find the install path for PM2 (Linux only):
```
which pm2
@@ -355,7 +356,7 @@ npm run start-pm2-debug
or (useful for crontab):
```
npm run prestart "pm2" && /path/to/pm2 start ./bin/instance -i 0 --node-args="--stack-size=10000" && /path/to/pm2 logs
cd /path/to/explorer && /path/to/npm run prestart "pm2" && /path/to/pm2 start ./bin/instance -i 0 --node-args="--stack-size=10000" && /path/to/pm2 logs
```
#### Stop Explorer Using PM2 (Recommended for Production)
@@ -369,7 +370,7 @@ npm run stop-pm2
or (useful for crontab):
```
/path/to/pm2 stop ./bin/instance
cd /path/to/explorer && /path/to/pm2 stop ./bin/instance
```
#### Start Explorer Using Forever (Alternate Production Option)
@@ -385,10 +386,10 @@ npm run start-forever
or (useful for crontab):
```
npm run prestart && /path/to/node /path/to/forever start ./bin/cluster
cd /path/to/explorer && /path/to/npm run prestart && /path/to/forever start ./bin/cluster
```
**NOTE:** Use the following cmd to find the install path for forever:
**NOTE:** Use the following cmd to find the install path for forever (Linux only):
```
which forever
@@ -405,15 +406,15 @@ npm run stop-forever
or (useful for crontab):
```
/path/to/node /path/to/forever stop ./bin/cluster
cd /path/to/explorer && /path/to/forever stop ./bin/cluster
```
### Syncing Databases with the Blockchain
sync.sh (located in scripts/) is used for updating the local databases. This script must be called from the explorers root directory.
sync.js (located in scripts/) is used for updating the local databases. This script must be called from the explorers root directory.
```
Usage: scripts/sync.sh /path/to/node [mode]
Usage: /path/to/node scripts/sync.js [mode]
Mode: (required)
update Updates index from last sync to current block
@@ -469,10 +470,10 @@ Easier crontab syntax using npm scripts, but may not work on some systems depend
Or, run the crontab by calling the sync script directly, which should work better in the event you have problems running the npm scripts from a crontab:
```
*/1 * * * * /path/to/explorer/scripts/sync.sh /path/to/node update > /dev/null 2>&1
*/2 * * * * /path/to/explorer/scripts/sync.sh /path/to/node market > /dev/null 2>&1
*/5 * * * * /path/to/explorer/scripts/sync.sh /path/to/node peers > /dev/null 2>&1
*/5 * * * * /path/to/explorer/scripts/sync.sh /path/to/node masternodes > /dev/null 2>&1
*/1 * * * * cd /path/to/explorer && /path/to/node scripts/sync.js update > /dev/null 2>&1
*/2 * * * * cd /path/to/explorer && /path/to/node scripts/sync.js market > /dev/null 2>&1
*/5 * * * * cd /path/to/explorer && /path/to/node scripts/sync.js peers > /dev/null 2>&1
*/5 * * * * cd /path/to/explorer && /path/to/node scripts/sync.js masternodes > /dev/null 2>&1
```
### Wallet Settings
@@ -504,6 +505,8 @@ A typical webserver binds to port 80 to serve webpages over the http protocol, b
#### Use Setcap to Safely Grant User Permissions
**NOTE:** This option is only available to Linux users
1. You can use the `setcap` command to change the capabilities of the `node` binary file to specifically allow the Express webserver to bind to a port less than 1024 (this one-time cmd requires root privileges):
```
@@ -516,6 +519,8 @@ You should now be able to browse to the explorer by IP address or domain name wi
#### Use Another Webserver as a Reverse Proxy
**NOTE:** The following instructions are for Linux users only, but installing and configuring another webserver should be possible on any OS
A few steps are involved in setting up another webserver that can bind to port 80 and forward all incoming traffic to the eIquidus node.js app. Any commercial webserver can be used to create the reverse proxy, but in this case, Nginx will be used as an example:
1. Install Nginx with the following terminal cmd:
@@ -573,6 +578,8 @@ Similar to [the problem with binding to port 80](#run-express-webserver-on-port-
#### Prerequisites
**NOTE:** The following instructions are for Linux users only, but installing and configuring certbot should be possible on any OS
There are a few common steps that must be completed before TLS/SSL certificates can be generated:
1. Install snapd:
@@ -601,6 +608,8 @@ sudo ln -s /snap/bin/certbot /usr/bin/certbot
#### Manually Link TLS/SSL Certificates to the Explorer
**NOTE:** The following instructions are for Linux users only, but installing and configuring certbot should be possible on any OS
Follow the steps below to configure the Express webserver for use with TLS/SSL:
1. If you haven't already done so, run the `setcap` cmd from the [Use Setcap to Safely Grant User Permissions Instructions](#use-setcap-to-safely-grant-user-permissions) which will allow node.js to bind to port 443 without needing root permissions.
@@ -645,6 +654,8 @@ Ensure that `webserver.tls.enabled` = true and that you specify the exact path t
#### Use Nginx as a Reverse Proxy
**NOTE:** The following instructions are for Linux users only, but installing and configuring certbot and nginx should be possible on any OS
1. If you haven't already done so, first follow through the [Use Another Webserver as a Reverse Proxy Instructions](#use-another-webserver-as-a-reverse-proxy) and then continue with step #2 below.
2. Generate a new TLS/SSL certificate via certbot which will automatically edit your Nginx configuration files and enable https at the same time:
@@ -708,47 +719,51 @@ jQuery(document).ready(function($) {
#### Backup Database Script
Make a complete backup of an eIquidus mongo database collection and save to compressed tar.gz file. Please note that you must ensure that the explorer is NOT running at the time of backup to prevent corrupting the backup data. The following backup scenarios are supported:
Make a complete backup of an eIquidus mongo database collection and save to compressed file. Please note that you must ensure that the explorer is NOT running at the time of backup to prevent corrupting the backup data. The following backup scenarios are supported:
**Backup Database (No filename specified)**
`sh scripts/create_backup.sh`: Backs up to the explorer/backups directory by default with the current date as the filename in the format yyyy-MMM-dd.tar.gz
`npm run create-backup`: Backs up to the explorer/backups directory by default with the current date as the filename in the format yyyy-MMM-dd.bak
**Backup Database (Partial filename specified)**
`sh scripts/create_backup.sh test`: Backs up the the explorer/backups directory by default with the filename test.tar.gz
`npm run create-backup test`: Backs up the the explorer/backups directory by default with the filename test.bak
**Backup Database (Full filename specified)**
`sh scripts/create_backup.sh today.tar.gz`: Backs up the the explorer/backups directory by default with the filename today.tar.gz
`npm run create-backup today.bak`: Backs up the the explorer/backups directory by default with the filename today.bak
**Backup Database (Full path with partial filename specified)**
`sh scripts/create_backup.sh /usr/local/bin/abc`: Backs up the the /usr/local/bin directory with the filename abc.tar.gz
`npm run create-backup /usr/local/bin/abc`: Backs up the the /usr/local/bin directory with the filename abc.bak
**Backup Database (Full path and filename specified)**
`sh scripts/create_backup.sh ~/new.tar.gz`: Backs up the the users home directory with the filename new.tar.gz
`npm run create-backup ~/new.bak`: Backs up the the users home directory with the filename new.bak
#### Restore Database Script
Restore a previously saved eIquidus mongo database collection backup. :warning: **WARNING:** This will completely overwrite your existing eIquidus mongo database, so be sure to make a full backup before proceeding. Please note that the explorer should NOT be running at the time of restore to prevent problems restoring the database. The following restore scenarios are supported:
Restore a previously saved eIquidus mongo database collection backup. :warning: **WARNING:** This will completely overwrite your existing eIquidus mongo database, so be sure to make a full backup before proceeding. Please note that the explorer should NOT be running at the time of restore to prevent problems restoring the database.
**NOTE:** Older v1.x eIquidus database backups were compressed into tar.gz files. These older tar.gz backups can still be restored, but you must specifically add the .tar.gz suffix. Example: `npm run restore-backup /path/to/old_backup.tar.gz`
The following restore scenarios are supported:
**Restore Database (Partial filename specified)**
`sh scripts/restore_backup.sh old`: Restores the explorer/scripts/backups/old.tar.gz file
`npm run restore-backup old`: Restores the explorer/scripts/backups/old.bak file
**Restore Database (Full filename specified)**
`sh scripts/restore_backup.sh working.tar.gz`: Restores the explorer/scripts/backups/working.tar.gz file
`npm run restore-backup working.bak`: Restores the explorer/scripts/backups/working.bak file
**Restore Database (Full path with partial filename specified)**
`sh scripts/restore_backup.sh /home/explorer/backup`: Restores the /home/explorer/backup.tar.gz file
`npm run restore-backup /home/explorer/backup`: Restores the /home/explorer/backup.bak file
**Restore Database (Full path and filename specified)**
`sh scripts/restore_backup.sh ~/archive.tar.gz`: Restores the ~/archive.tar.gz file
`npm run restore-backup ~/archive.bak`: Restores the ~/archive.bak file
#### Delete Database Script
@@ -756,7 +771,7 @@ Completely wipe the eIquidus mongo database collection clean to start again from
**Delete Database**
`sh scripts/delete_database.sh`
`npm run delete-database`
### Known Issues
@@ -766,7 +781,7 @@ Completely wipe the eIquidus mongo database collection clean to start again from
RangeError: Maximum call stack size exceeded
```
Nodes default stack size may be too small to index addresses with many tx's. If you experience the above error while running sync.sh the stack size needs to be increased.
Nodes default stack size may be too small to index addresses with many tx's. If you experience the above error while running sync.js the stack size needs to be increased.
To determine the default setting run:
+14 -2
View File
@@ -1,5 +1,6 @@
var cluster = require('cluster');
var fs = require('fs');
const isWinOS = process.platform == 'win32';
if (cluster.isMaster) {
console.log('Starting cluster with pid: ' + process.pid);
@@ -11,7 +12,11 @@ if (cluster.isMaster) {
// send kill cmd to all workers
for (var id in cluster.workers) {
console.log('Worker (' + id + ') shutting down...');
process.kill(cluster.workers[id]['process']['pid'], 'SIGINT');
if (!isWinOS) {
// only kill the worker if not on windows (otherwise an error is displayed)
process.kill(cluster.workers[id]['process']['pid'], 'SIGINT');
}
}
function waitForWorkerShutdown () {
@@ -21,6 +26,13 @@ if (cluster.isMaster) {
} else {
// all worker threads have closed
// now exit the master process
if (isWinOS) {
// command line in windows doesn't seem to release itself
// show a message that the app has finished
console.log('The application is now safe to close');
}
process.exit(0);
}
}
@@ -39,7 +51,7 @@ if (cluster.isMaster) {
cluster.on('exit', function (worker, code, signal) {
if (worker['process']['exitCode'] === 0) {
console.log('Worker (' + worker['id'] + ') shutdown complete');
} else if ((signal != 'SIGINT') && (worker['process']['exitCode'] !== 0) && (worker.exitedAfterDisconnect !== true)) {
} else if (signal != 'SIGINT' && worker['process']['exitCode'] !== 0 && worker['process']['exitCode'] !== 999 && worker.exitedAfterDisconnect !== true) {
console.log('Cluster restarting...');
cluster.fork();
}
+1 -1
View File
@@ -219,7 +219,7 @@ module.exports = {
if (err) {
console.log('Unable to connect to database: %s', database);
console.log('Aborting');
process.exit(1);
process.exit(999);
}
return cb();
+2 -2
View File
@@ -1088,9 +1088,9 @@ exports.sync = {
// If you sync using more than 1 parallel task, then historical balance data for wallet addresses can possibly be saved out-of-order and there is currently no workaround for this.
// Therefore, it is recommended to keep this setting to 1 parallel task for now until a proper solution can be procured for the historical balance issue.
"block_parallel_tasks": 1,
// update_timeout: The amount of time to wait (in milliseconds) before moving to the next block or transaction during blockchain sync or reindex (scripts/sync.sh /path/to/node update or scripts/sync.sh /path/to/node reindex)
// update_timeout: The amount of time to wait (in milliseconds) before moving to the next block or transaction during blockchain sync or reindex (/path/to/node scripts/sync.js update or /path/to/node scripts/sync.js reindex)
"update_timeout": 10,
// check_timeout: The amount of time to wait (in milliseconds) before moving to the next block or transaction during a check sync (scripts/sync.sh /path/to/node check)
// check_timeout: The amount of time to wait (in milliseconds) before moving to the next block or transaction during a check sync (/path/to/node scripts/sync.js check)
"check_timeout": 250,
// save_stats_after_sync_blocks: During index syncronization, stats are saved after processing this many blocks to save time by not having to save after each block
"save_stats_after_sync_blocks": 100,
+24 -22
View File
@@ -3,25 +3,28 @@
"version": "1.99.0",
"private": true,
"scripts": {
"start": "npm run prestart && $(which node) --stack-size=10000 ./bin/cluster",
"stop": "sh ./scripts/stop_explorer.sh",
"start-instance": "npm run prestart && $(which node) --stack-size=10000 ./bin/instance",
"start-forever": "npm run prestart \"forever\" && $(which node) $(which forever) start ./bin/cluster",
"stop-forever": "$(which node) $(which forever) stop ./bin/cluster",
"start-pm2": "npm run prestart \"pm2\" && $(which pm2) start ./bin/instance -i 0 --node-args=\"--stack-size=10000\"",
"start-pm2-debug": "npm run prestart \"pm2\" && $(which pm2) start ./bin/instance -i 0 --node-args=\"--stack-size=10000\" && $(which pm2) logs",
"stop-pm2": "$(which pm2) stop ./bin/instance",
"test": "$(which node) ./node_modules/jasmine/bin/jasmine.js test/*Spec.js",
"prestart": "sh ./scripts/prestart.sh",
"sync-blocks": "sh ./scripts/sync.sh $(which node) update",
"sync-markets": "sh ./scripts/sync.sh $(which node) market",
"sync-peers": "sh ./scripts/sync.sh $(which node) peers",
"sync-masternodes": "sh ./scripts/sync.sh $(which node) masternodes",
"check-blocks": "sh ./scripts/sync.sh $(which node) check",
"reindex": "sh ./scripts/sync.sh $(which node) reindex",
"reindex-rich": "sh ./scripts/sync.sh $(which node) reindex-rich",
"reindex-txcount": "sh ./scripts/sync.sh $(which node) reindex-txcount",
"reindex-last": "sh ./scripts/sync.sh $(which node) reindex-last"
"start": "npm run prestart && node --stack-size=10000 ./bin/cluster",
"stop": "node ./scripts/stop_explorer.js",
"start-instance": "npm run prestart && node --stack-size=10000 ./bin/instance",
"start-forever": "npm run prestart \"forever\" && forever start ./bin/cluster",
"stop-forever": "forever stop ./bin/cluster",
"start-pm2": "npm run prestart \"pm2\" && pm2 start ./bin/instance -i 0 --node-args=\"--stack-size=10000\"",
"start-pm2-debug": "npm run prestart \"pm2\" && pm2 start ./bin/instance -i 0 --node-args=\"--stack-size=10000\" && pm2 logs",
"stop-pm2": "pm2 stop ./bin/instance",
"test": "node ./node_modules/jasmine/bin/jasmine.js test/*Spec.js",
"prestart": "node ./scripts/prestart.js",
"sync-blocks": "node ./scripts/sync.js index update",
"sync-markets": "node ./scripts/sync.js market",
"sync-peers": "node ./scripts/sync.js peers",
"sync-masternodes": "node ./scripts/sync.js masternodes",
"check-blocks": "node ./scripts/sync.js index check",
"reindex": "node ./scripts/sync.js index reindex",
"reindex-rich": "node ./scripts/sync.js index reindex-rich",
"reindex-txcount": "node ./scripts/sync.js index reindex-txcount",
"reindex-last": "node ./scripts/sync.js index reindex-last",
"create-backup": "node ./scripts/create_backup.js",
"restore-backup": "node ./scripts/restore_backup.js",
"delete-database": "node ./scripts/delete_database.js"
},
"dependencies": {
"express": ">=4.17.1",
@@ -40,9 +43,8 @@
"mongoose": "^6.0.14",
"qr-image": "^3.2.0",
"sass": "^1.44.0",
"json": "^11.0.0",
"strip-json-comments-cli": "^2.0.1",
"bad-words": "^3.0.4"
"bad-words": "^3.0.4",
"readline-sync": "^1.4.10"
},
"devDependencies": {
"jasmine": ">=3.6.3"
+76
View File
@@ -0,0 +1,76 @@
const fs = require('fs');
const path = require('path');
const archiveSuffix = '.bak';
var backupPath = path.join(path.dirname(__dirname), 'backups');
var backupFilename;
// check if a backup filename was passed into the script
if (process.argv[2] != null && process.argv[2] != '') {
// use the backup filename passed into this script
backupFilename = process.argv[2];
} else {
const systemDate = new Date();
const monthName = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
// no backup filename passed in. use todays date as the backup filename
backupFilename = `${systemDate.getFullYear()}-${monthName[systemDate.getMonth()]}-${systemDate.getDate()}`;
}
// check if backup filename has the archive suffix already
if (backupFilename.endsWith(archiveSuffix)) {
// remove the archive suffix from the backup filename
backupFilename = backupFilename.substring(0, backupFilename.length - archiveSuffix.length);
}
// check if the backup filename already has a path
if (path.isAbsolute(backupFilename)) {
// the backup filename is a full path
// split out the path and filename
backupPath = path.dirname(backupFilename);
backupFilename = path.basename(backupFilename);
}
// check if the backup directory exists
if (!fs.existsSync(backupPath)) {
// attempt to create the directory
fs.mkdirSync(backupPath);
}
// check if backup file already exists
if (!fs.existsSync(path.join(backupPath, `${backupFilename}${archiveSuffix}`))) {
const { exec } = require('child_process');
const settings = require('../lib/settings');
const randomDirectoryName = Math.random().toString(36).substring(2, 15) + Math.random().toString(23).substring(2, 5);
// execute backup
const backupProcess = exec(`mongodump --host="${settings.dbsettings.address}" --port="${settings.dbsettings.port}" --username="${settings.dbsettings.user}" --password="${settings.dbsettings.password}" --db="${settings.dbsettings.database}" --archive="${path.join(backupPath, backupFilename + archiveSuffix)}" --gzip`);
backupProcess.stdout.on('data', (data) => {
console.log(data);
});
backupProcess.stderr.on('data', (data) => {
console.log(Buffer.from(data).toString());
});
backupProcess.on('error', (error) => {
console.log(error);
});
backupProcess.on('exit', (code, signal) => {
if (code) {
console.log(`Process exit with code: ${code}`);
process.exit(1);
} else if (signal) {
console.log(`Process killed with signal: ${signal}`);
process.exit(1);
} else {
console.log(`Backup saved successfully to ${path.join(backupPath, backupFilename + archiveSuffix)}`);
process.exit(0);
}
});
} else {
// backup already exists
console.log(`A backup named ${backupFilename}${archiveSuffix} already exists`);
process.exit(1);
}
-41
View File
@@ -1,41 +0,0 @@
#!/bin/bash
ends_with() { case $2 in *"$1") true;; *) false;; esac; }
BACKUP_PATH="$(dirname $(dirname $(readlink -f "$0")))/backups"
ARCHIVE_SUFFIX=".tar.gz"
if [ -n "${1}" ]; then
# use the backup filename passed into this script
BACKUP_FILENAME="${1}"
else
# no backup filename passed in, use todays date as the backup filename
BACKUP_FILENAME=$(date +"%Y-%b-%d")
fi
if ends_with "${ARCHIVE_SUFFIX}" "${BACKUP_FILENAME}"; then
# remove the archive suffix from the backup filename
BACKUP_FILENAME=${BACKUP_FILENAME%"${ARCHIVE_SUFFIX}"}
fi
if [ $(dirname "${BACKUP_FILENAME}") != "." ]; then
# The backup filename is a full path
# Split out the path and filename
BACKUP_DIR="$(dirname ${BACKUP_FILENAME})"
TEMP_FILENAME=${BACKUP_FILENAME#"${BACKUP_DIR}/"}
BACKUP_PATH=${BACKUP_FILENAME%"/${TEMP_FILENAME}"}
BACKUP_FILENAME="${TEMP_FILENAME}"
fi
if [ ! -f "${BACKUP_PATH}/${BACKUP_FILENAME}${ARCHIVE_SUFFIX}" ]; then
# execute backup
eval "mongodump -d explorerdb -o ${BACKUP_PATH}/${BACKUP_FILENAME}"
# archive the backup
cd "${BACKUP_PATH}" && tar -cvzf "${BACKUP_PATH}/${BACKUP_FILENAME}${ARCHIVE_SUFFIX}" "${BACKUP_FILENAME}"
# delete the uncompressed backup directory
rm -rf "${BACKUP_PATH}/${BACKUP_FILENAME}"
# finished msg
echo "Backup saved successfully to ${BACKUP_PATH}/${BACKUP_FILENAME}${ARCHIVE_SUFFIX}."
else
# backup already exists
echo "A backup named ${BACKUP_FILENAME}${ARCHIVE_SUFFIX} already exists."
fi
+101
View File
@@ -0,0 +1,101 @@
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
function drop_collection(mongoose, colName, cb) {
// attempt to delete the collection
mongoose.connection.db.dropCollection(colName, function(err, result) {
if (err || !result) {
console.log(`Unable to delete the ${colName} collection`);
console.log('Aborting');
process.exit(1);
} else
return cb(true);
});
}
function finished_deleting(mongoose) {
console.log('Finished deleting database');
// disconnect from mongo database
mongoose.disconnect();
// delete database complete
process.exit(0);
}
console.log('You are about to delete the entire eIquidus database.');
// prompt for deleting explorer database
rl.question('Are you sure you want to do this? [y/n]: ', function (deleteAnswer) {
// stop prompting
rl.close();
// determine if the explorer database should be deleted
switch (deleteAnswer) {
case 'y':
case 'Y':
case 'yes':
case 'YES':
case 'Yes':
const settings = require('../lib/settings');
const mongoose = require('mongoose');
const dbString = `mongodb://${settings.dbsettings.user}:${settings.dbsettings.password}@${settings.dbsettings.address}:${settings.dbsettings.port}/${settings.dbsettings.database}`;
console.log('Connecting to database..');
// connect to mongo database
mongoose.connect(dbString, function(err) {
if (err) {
console.log('Unable to connect to database: %s', dbString);
console.log('Aborting');
process.exit(1);
} else {
// get the list of collections
mongoose.connection.db.listCollections().toArray(function (err, collections) {
if (err) {
console.log('Unable to list collections in database: %s', err);
console.log('Aborting');
process.exit(1);
} else {
// check if there are any collections
if (collections.length > 0) {
var counter = 0;
// loop through all collections
collections.forEach((collection) => {
console.log(`Deleting ${collection.name}..`);
// delete this collection
drop_collection(mongoose, collection.name, function(retVal) {
// check if the collection was successfully deleted
if (retVal)
counter++;
// check if the last collection was deleted
if (counter == collections.length) {
// finish the delete process
finished_deleting(mongoose);
}
});
});
} else {
// nothing to delete
console.log('Nothing to delete, the database is already empty..');
// finish the delete process
finished_deleting(mongoose);
}
}
});
}
});
break;
default:
console.log('Process aborted. Nothing was deleted.');
process.exit(1);
}
});
-40
View File
@@ -1,40 +0,0 @@
#!/bin/bash
# Find the absolute path to this script file
SCRIPT_PATH=`dirname "$0"`
SCRIPT_PATH=`( cd "$SCRIPT_PATH" && pwd )`
# Remove temp file if it exists from last time
if [ -f "${SCRIPT_PATH}/del.tmp" ]; then
rm -f "${SCRIPT_PATH}/del.tmp"
fi
# Prompt for deleting database
echo "You are about to delete the entire eIquidus database."
echo "Are you sure you want to do this? [y/n]: ";
read -p "" DELETE_ANSWER
# Determine if the database should be deleted
case "$DELETE_ANSWER" in
y|Y|yes|Yes|YES) ;;
*) echo "Process aborted. Nothing was deleted." && exit ;;
esac
# Erase entire database
sudo touch "${SCRIPT_PATH}/del.tmp" && mongo <<EOF
use explorerdb
db.addresses.drop()
db.addresstxes.drop()
db.networkhistories.drop()
db.coinstats.drop()
db.heavies.drop()
db.markets.drop()
db.masternodes.drop()
db.peers.drop()
db.richlists.drop()
db.txes.drop()
exit
EOF
# Check if the temp file exists to determine if the delete was successful or not
if [ -f "${SCRIPT_PATH}/del.tmp" ]; then
rm -f "${SCRIPT_PATH}/del.tmp"
echo "Finished deleting database."
else
echo "Process aborted. Nothing was deleted."
fi
-27
View File
@@ -1,27 +0,0 @@
#!/bin/sh
# this super hack will sync the explorer within the specified block height range
forcesync() {
blockcount=$1
echo "╒══════════════════<<"
echo "| height : $blockcount"
blockhash=`curl -s https://explorer.exor.io/api/getblockhash?height=$blockcount`
echo "| ଓ hash : $blockhash"
curl -s https://explorer.exor.io/block/$blockhash > /dev/null
echo "╘═══════════════════════════════>>"
}
main() {
if [ $currentblockcount -ne $endingblockcount ]; then
forcesync $currentblockcount
currentblockcount=$((currentblockcount + 1))
else
exit;
fi
main
}
startingblockcount=1213133
endingblockcount=1213143
echo "Syncing..."
currentblockcount=$startingblockcount
main
-28
View File
@@ -1,28 +0,0 @@
#!/bin/sh
# this super hack will sync the explorer from the newest block as they occur
forcesync() {
blockcount=$1
echo "╒══════════════════<<"
echo "| height : $blockcount"
blockhash=`curl -s https://explorer.exor.io/api/getblockhash?height=$blockcount`
echo "| ଓ hash : $blockhash"
curl -s https://explorer.exor.io/block/$blockhash > /dev/null
echo "╘═══════════════════════════════>>"
}
main() {
echo "Checking for new block..."
previousblockcount=$currentblockcount
currentblockcount=`curl -s https://explorer.exor.io/api/getblockcount`
if [ $currentblockcount -ne $previousblockcount ]; then
echo "New block found. Syncing..."
forcesync $currentblockcount
else
echo "No new block found. Sleeping...";
fi
sleep 20
main
}
currentblockcount=0
main
+108
View File
@@ -0,0 +1,108 @@
const minNodeVersionMajor = '14';
const minNodeVersionMinor = '13';
const minNodeVersionRevision = '1';
// get the nodejs version
var nodeVersion = process.version;
var nodeVersionMajor = '0';
var nodeVersionMinor = '0';
var nodeVersionRevision = '0';
// check if the nodejs version # is blank or a very long string as that would usually indicate a problem
if (nodeVersion != null && nodeVersion != '' && nodeVersion.length < 16) {
// Remove the 'v' from the beginning of the version string
if (nodeVersion.indexOf('v') == 0)
nodeVersion = nodeVersion.slice(1);
// split node version string into major, minor and revision
var splitVersion = nodeVersion.split('.');
nodeVersionMajor = splitVersion[0];
if (splitVersion.length > 1)
nodeVersionMinor = splitVersion[1];
if (splitVersion.length > 2)
nodeVersionRevision = splitVersion[2];
}
// check if the installed nodejs is an older version than supported by the explorer
if (!(nodeVersionMajor > minNodeVersionMajor || (nodeVersionMajor == minNodeVersionMajor && (nodeVersionMinor > minNodeVersionMinor || (nodeVersionMinor == minNodeVersionMinor && nodeVersionRevision >= minNodeVersionRevision))))) {
console.log(`Please install an updated version of nodejs.\n\nInstalled: ${nodeVersion}\nRequired: ${minNodeVersionMajor}.${minNodeVersionMinor}.${minNodeVersionRevision}`);
process.exit(0);
}
function check_argument_passed(cb) {
// check 1st argument
if (process.argv[2] != null) {
const { exec } = require('child_process');
// determine which argument was passed
switch (process.argv[2]) {
case 'pm2':
// windows pm2 has problem loading locally, but other os's should work fine
const isWinOS = process.platform == 'win32';
// run a cmd to check if pm2 is installed
exec(`npm list${(isWinOS ? ' -g' : '')} pm2`, (err, stdout, stderr) => {
// split stdout string by new line
var splitResponse = (stdout == null ? '' : stdout).split('\n').filter(element => element);
// check if the cmd result contains an @ symbol
if (splitResponse[splitResponse.length - 1].indexOf('@') == -1) {
console.log('Installing pm2 module.. Please wait..');
// install pm2
exec(`npm install pm2@latest${(isWinOS ? ' -g' : '')}`, (err, stdout, stderr) => {
// always return true for now without checking results
return cb(true);
});
} else
return cb(true);
});
break;
case 'forever':
// run a cmd to check if forever is installed
exec('npm list forever', (err, stdout, stderr) => {
// split stdout string by new line
var splitResponse = (stdout == null ? '' : stdout).split('\n').filter(element => element);
// check if the cmd result contains an @ symbol
if (splitResponse[splitResponse.length - 1].indexOf('@') == -1) {
console.log('Installing forever module.. Please wait..');
// install forever
exec('npm install forever', (err, stdout, stderr) => {
// always return true for now without checking results
return cb(true);
});
} else
return cb(true);
});
break;
default:
// argument not passed or unknown argument
return cb(true);
}
} else
return cb(true);
}
// check if an argument was passed into this script
check_argument_passed(function(retVal) {
const fs = require('fs');
const settings = require('../lib/settings');
// ensure the selected theme is properly installed
fs.writeFile('./public/css/_theme-selector.scss', `$theme-name: "${settings.shared_pages.theme}";`, function (err) {
const sass = require('sass');
// generate minified css from scss file
const minified = sass.compile('./public/css/style.scss', {style: 'compressed'});
// save the minified css to file
fs.writeFile('./public/css/style.min.css', minified.css, function (err) {
// Finished pre-loading
});
});
});
-67
View File
@@ -1,67 +0,0 @@
#!/bin/bash
readonly MIN_NODE_VERSION_MAJOR="14"
readonly MIN_NODE_VERSION_MINOR="13"
readonly MIN_NODE_VERSION_REVISION="1"
readonly NONE="\033[00m"
readonly RED="\033[01;31m"
begins_with() { case $2 in "$1"*) true;; *) false;; esac; }
error_message() { echo "${RED}Error:${NONE} $1" && echo && exit 1; }
# Get the nodejs version
NODE_VERSION="$(node -v)"
NODE_VERSION_MAJOR="0"
NODE_VERSION_MINOR="0"
NODE_VERSION_REVISION="0"
# Check if the nodejs version # is blank or a very long string as that would usually indicate a problem
if [ "${#NODE_VERSION}" -gt 0 ] && [ "${#NODE_VERSION}" -lt 16 ]; then
# Remove the 'v' from the beginning of the version string
if begins_with "v" "${NODE_VERSION}"; then
NODE_VERSION=$(echo "${NODE_VERSION}" | cut -c2-${#NODE_VERSION})
fi
# Split node version string into major, minor and revision
NODE_VERSION_MAJOR="$(echo $NODE_VERSION | cut -d'.' -f1)"
NODE_VERSION_MINOR="$(echo $NODE_VERSION | cut -d'.' -f2)"
NODE_VERSION_REVISION="$(echo $NODE_VERSION | cut -d'.' -f3)"
fi
# Check if the installed nodejs is an older version than supported by the explorer
if !([ "${NODE_VERSION_MAJOR}" -gt "${MIN_NODE_VERSION_MAJOR}" ] || ([ "${NODE_VERSION_MAJOR}" -eq "${MIN_NODE_VERSION_MAJOR}" ] && ([ "${NODE_VERSION_MINOR}" -gt "${MIN_NODE_VERSION_MINOR}" ] || ([ "${NODE_VERSION_MINOR}" -eq "${MIN_NODE_VERSION_MINOR}" ] && [ "${NODE_VERSION_REVISION}" -ge "${MIN_NODE_VERSION_REVISION}" ])))); then
error_message "Please install an updated version of nodejs.\n\nInstalled: $NODE_VERSION\nRequired: $MIN_NODE_VERSION_MAJOR.$MIN_NODE_VERSION_MINOR.$MIN_NODE_VERSION_REVISION"
fi
## Check if new module directory exists
#if [ ! -d ./node_modules/change_to_module_dir_name ]; then
# # Install updated packages
# npm update
#fi
# Check if an argument was passed into this script
if [ -n "${1}" ]; then
# Determine which argument was passed
case "${1}" in
"pm2")
# Check if pm2 is installed
if [ -z "$(which pm2)" ]; then
# Install pm2
npm install pm2@latest -g
fi
;;
"forever")
# Check if forever is installed
if [ -z "$(which forever)" ]; then
# Install forever
npm install forever -g
fi
;;
esac
fi
# Ensure that selected theme is properly installed
sh ./scripts/sass_theme_reader.sh
# Run sass module to generate minified css from scss file
./node_modules/.bin/sass --no-source-map --style=compressed ./public/css/style.scss ./public/css/style.min.css
+244
View File
@@ -0,0 +1,244 @@
const fs = require('fs');
const path = require('path');
const archiveSuffix = '.bak';
const oldArchiveSuffix = '.tar.gz';
const defaultBackupPath = path.join(path.dirname(__dirname), 'backups');
function check_module_directory_exists(dirName, cb) {
// check if module directory exists
if (!fs.existsSync(`./node_modules/${dirName}`)) {
const { exec } = require('child_process');
console.log('Installing tar package.. Please wait..');
// install tar module
exec('npm install tar', (err, stdout, stderr) => {
// always return true for now without checking results
return cb(true);
});
} else
return cb(true);
}
function drop_collection(mongoose, colName, cb) {
// attempt to delete the collection
mongoose.connection.db.dropCollection(colName, function(err, result) {
if (err || !result) {
console.log(`Unable to delete the ${colName} collection`);
console.log('Aborting');
process.exit(1);
} else
return cb(true);
});
}
function delete_database(settings, cb) {
const mongoose = require('mongoose');
const dbString = `mongodb://${settings.dbsettings.user}:${settings.dbsettings.password}@${settings.dbsettings.address}:${settings.dbsettings.port}/${settings.dbsettings.database}`;
console.log('Connecting to database..');
// connect to mongo database
mongoose.connect(dbString, function(err) {
if (err) {
console.log('Unable to connect to database: %s', dbString);
console.log('Aborting');
process.exit(1);
} else {
// get the list of collections
mongoose.connection.db.listCollections().toArray(function (err, collections) {
if (err) {
console.log('Unable to list collections in database: %s', err);
console.log('Aborting');
process.exit(1);
} else {
// check if there are any collections
if (collections.length > 0) {
var counter = 0;
// loop through all collections
collections.forEach((collection) => {
console.log(`Deleting ${collection.name}..`);
// delete this collection
drop_collection(mongoose, collection.name, function(retVal) {
// check if the collection was successfully deleted
if (retVal)
counter++;
// check if the last collection was deleted
if (counter == collections.length) {
// disconnect from mongo database
mongoose.disconnect();
// finished the delete process
return cb(true);
}
});
});
} else {
// nothing to delete
// disconnect from mongo database
mongoose.disconnect();
return cb(true);
}
}
});
}
});
}
function restore_backup(settings, backupPath, extractedPath, gZip) {
const { exec } = require('child_process');
console.log('Restoring backup.. Please wait..');
// restore mongo database from backup
const restoreProcess = exec(`mongorestore --host="${settings.dbsettings.address}" --port="${settings.dbsettings.port}" --username="${settings.dbsettings.user}" --password="${settings.dbsettings.password}" --authenticationDatabase="${settings.dbsettings.database}" ${(gZip ? `--gzip --archive="${backupPath}"` : `"${extractedPath}"`)}`);
restoreProcess.stdout.on('data', (data) => {
console.log(data);
});
restoreProcess.stderr.on('data', (data) => {
console.log(Buffer.from(data).toString());
});
restoreProcess.on('error', (error) => {
console.log(error);
});
restoreProcess.on('exit', (code, signal) => {
if (code) {
console.log(`Process exit with code: ${code}`);
process.exit(1);
} else if (signal) {
console.log(`Process killed with signal: ${signal}`);
process.exit(1);
} else {
// check if gZip is enabled
if (!gZip) {
// try to remove the backup directory
try {
fs.rmSync(extractedPath, { recursive: true });
} catch {
// do nothing
}
}
// restore backup complete
console.log(`Backup restored from ${path.basename(backupPath)} successfully`);
process.exit(0);
}
});
}
// check if a backup filename was passed into the script
if (process.argv[2] != null && process.argv[2] != '') {
var backupPath = process.argv[2];
// check if the backup filename already has a path
if (!fs.existsSync(`${backupPath}`)) {
// check if the backup is valid by adding the archive suffix
if (fs.existsSync(`${backupPath}${archiveSuffix}`)) {
// the backup file is valid after adding the archive suffix
backupPath = `${backupPath}${archiveSuffix}`;
} else {
// prepend the default backup path
backupPath = path.join(defaultBackupPath, backupPath);
}
}
// check for the backup file (again)
if (!fs.existsSync(`${backupPath}`)) {
// append the default archive suffix
backupPath = `${backupPath}${archiveSuffix}`;
}
// check for the backup file (last time)
if (fs.existsSync(`${backupPath}`)) {
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
console.log('You are about to delete the current eIquidus database and restore from backup.');
// prompt for restoring explorer database
rl.question('Are you sure you want to do this? [y/n]: ', function (restoreAnswer) {
// stop prompting
rl.close();
// determine if the explorer database should be restored
switch (restoreAnswer) {
case 'y':
case 'Y':
case 'yes':
case 'YES':
case 'Yes':
const settings = require('../lib/settings');
// check if this is a tar.gz (older explorer backup format)
if (!backupPath.endsWith(oldArchiveSuffix)) {
// newer backup format (.bak)
// delete all collections from existing database
delete_database(settings, function(retVal) {
if (retVal) {
// move on to the restore process
restore_backup(settings, backupPath, backupPath, true);
}
});
} else {
// older backup format (.tar.gz)
// check if the tar module is already installed
check_module_directory_exists('tar', function(retVal) {
const tar = require('tar');
console.log('Extracting backup files.. Please wait..');
// extract the backup archive
tar.x({ file: backupPath, cwd: defaultBackupPath, gzip: true }, function() {
var extractedPath = path.join(defaultBackupPath, path.basename(backupPath).replace(oldArchiveSuffix, ''));
// check if this is a valid backup archive now that the files have been extracted
if (fs.existsSync(`${path.join(extractedPath, settings.dbsettings.database)}`)) {
// delete all collections from existing database
delete_database(settings, function(retVal) {
if (retVal) {
// move on to the restore process
restore_backup(settings, backupPath, extractedPath, false);
}
});
} else {
// backup file is not a valid mongo database backup
// try to remove the backup directory
try {
fs.rmSync(extractedPath, { recursive: true });
} catch {
// do nothing
} finally {
console.log(`${path.basename(backupPath)} is not a valid backup file`);
process.exit(1);
}
}
});
});
}
break;
default:
console.log('Process aborted. Nothing was restored.');
process.exit(1);
}
});
} else {
// backup does not exist
console.log(`${backupPath} cannot be found`);
process.exit(1);
}
} else {
console.log('No backup file specified');
process.exit(1);
}
-63
View File
@@ -1,63 +0,0 @@
#!/bin/bash
ARCHIVE_SUFFIX=".tar.gz"
# Check if a backup file was specified
if [ -n "${1}" ]; then
BACKUP_PATH="${1}"
# Check if the backup file exists as a full path
if [ ! -f "${BACKUP_PATH}" ]; then
# Check if the backup is valid by adding the archive suffix
if [ -f "${BACKUP_PATH}${ARCHIVE_SUFFIX}" ]; then
# The backup file is valid after adding the archive suffix
BACKUP_PATH="${BACKUP_PATH}${ARCHIVE_SUFFIX}"
else
# Prepend the default backup path
BACKUP_PATH="$(dirname $(dirname $(readlink -f "$0")))/backups/${BACKUP_PATH}"
fi
fi
# Check for the backup file (again)
if [ ! -f "${BACKUP_PATH}" ]; then
# Append the default archive suffix
BACKUP_PATH="${BACKUP_PATH}${ARCHIVE_SUFFIX}"
fi
# Check for the backup file (last time)
if [ -f "${BACKUP_PATH}" ]; then
# Extract the backup archive
DIR_NAME=$(dirname "${BACKUP_PATH}")
tar -zxvf "${BACKUP_PATH}" -C "${DIR_NAME}"
# Check if this is a valid backup archive now that the files have been extracted
if [ -d ${BACKUP_PATH%"${ARCHIVE_SUFFIX}"}/explorerdb ]; then
BACKUP_DIR=${BACKUP_PATH%"${ARCHIVE_SUFFIX}"}
# Erase entire database
sudo mongo <<EOF
use explorerdb
db.addresses.drop()
db.addresstxes.drop()
db.networkhistories.drop()
db.coinstats.drop()
db.heavies.drop()
db.markets.drop()
db.masternodes.drop()
db.peers.drop()
db.richlists.drop()
db.txes.drop()
exit
EOF
# Restore mongo database from the backup directory
eval "mongorestore -d explorerdb ${BACKUP_DIR}/explorerdb"
# Remove the backup directory
rm -rf "${BACKUP_DIR}"
# Finished msg
echo "Backup restored from ${BACKUP_PATH} successfully."
else
# Backup file is not a valid mongo database backup
echo "${BACKUP_PATH} is not a valid backup file."
fi
else
# Backup does not exist
echo "${BACKUP_PATH} cannot be found."
fi
else
echo "no backup file specified."
fi
-7
View File
@@ -1,7 +0,0 @@
#!/bin/bash
if [ -f ./settings.json ]; then
echo "\$theme-name: \"$(./node_modules/.bin/strip-json-comments settings.json | ./node_modules/.bin/json shared_pages.theme)\";" > ./public/css/_theme-selector.scss
else
echo "\$theme-name: \"Exor\";" > ./public/css/_theme-selector.scss
fi
+60
View File
@@ -0,0 +1,60 @@
const settings = require('../lib/settings');
const { exec } = require('child_process');
function validate_port(port) {
if (port == null || typeof port !== 'number' || port < 1 || port > 65535)
return false;
else
return true;
}
function check_webserver_running(cb) {
// determine operating system
switch (process.platform) {
case 'win32':
// windows
exec(`for /f "tokens=5" %a in ('netstat -aon ^| findstr :${settings.webserver.port} ^| findstr LISTENING') do @echo %~nxa`, (err, stdout, stderr) => {
// check if the port is open
if (stdout != null && stdout != '') {
// split the results in case there are multiple (usually because of ipv4 and ipv6)
split = stdout.split('\n');
// return the kill cmd
return cb(`taskkill /f /pid ${split[0]}`);
} else
return cb(null);
});
break;
default:
// linux, macos, etc.
exec(`lsof -t -i:${settings.webserver.port}`, (err, stdout, stderr) => {
// check if the port is open
if (stdout != null && stdout != '') {
// return the kill cmd
return cb(`kill -2 ${stdout.trim()}`);
} else
return cb(null);
});
}
}
// check if the webserver.port value is a valid port #
if (validate_port(settings.webserver.port) == true) {
// check if the server is currently running
check_webserver_running(function(killcmd) {
// check return value
if (killcmd != null) {
// send a kill signal to the process that is currently using the explorer's server port
exec(killcmd, (err, stdout, stderr) => {
// show shutdown msg
console.log('Explorer shutting down... Please wait...');
});
} else {
// webserver is not running
console.log('Error: Cannot stop explorer because it is not currently running');
}
});
} else {
// invalid port number
console.log('Error: webserver.port value not found in settings.json.');
}
-32
View File
@@ -1,32 +0,0 @@
#!/bin/bash
validate_port() {
if [ -z "$1" ] || ([ -n "$1" ] && ((echo $1 | egrep -q '^[0-9]+$' && ([ $1 -lt 1 ] || [ $1 -gt 65535 ])) || ! test "$1" -gt 0 2> /dev/null)); then
echo "err"
fi
}
# Check if the settings.json file exists
if [ -f ./settings.json ]; then
# Read the webserver.port value from settings.json file
readonly SERVER_PORT="$(./node_modules/.bin/strip-json-comments settings.json | ./node_modules/.bin/json -q webserver.port)"
# Check if the webserver.port value is a valid port #
if [ -z "$(validate_port $SERVER_PORT)" ]; then
# Check if the server is currently running
if [ -n "$(lsof -t -i:${SERVER_PORT} 2> /dev/null)" ]; then
# Send a SIGINT kill signal to the process that is currently using the explorer's server port
kill -2 $(lsof -t -i:${SERVER_PORT})
# Show shutdown msg
echo "Explorer shutting down... Please wait..."
else
# Webserver is not running
echo "Error: Cannot stop explorer because it is not currently running"
fi
else
# Invalid port number
echo "Error: webserver.port value not found in settings.json. webserver.port value is missing or file is not valid json."
fi
else
# Missing settings file
echo "Error: Cannot find settings.json"
fi
+101 -33
View File
@@ -13,7 +13,7 @@ var block_start = 1;
// displays usage and exits
function usage() {
console.log('Usage: scripts/sync.sh /path/to/node [mode]');
console.log('Usage: /path/to/node scripts/sync.js [mode]');
console.log('');
console.log('Mode: (required)');
console.log('update Updates index from last sync to current block');
@@ -37,41 +37,109 @@ function usage() {
}
// check options
if (process.argv[2] == 'index') {
if (process.argv.length < 3)
usage();
else {
switch (process.argv[3]) {
case 'update':
mode = 'update';
break;
case 'check':
mode = 'check';
if (process.argv[2] == null || process.argv[2] == 'index' || process.argv[2] == 'update') {
mode = null;
// check if the block start value was passed in and is an integer
if (!isNaN(process.argv[4]) && Number.isInteger(parseFloat(process.argv[4]))) {
// Check if the block start value is less than 1
if (parseInt(process.argv[4]) < 1)
block_start = 1;
else
block_start = parseInt(process.argv[4]);
}
switch (process.argv[3]) {
case undefined:
case null:
case 'update':
mode = 'update';
break;
case 'check':
mode = 'check';
break;
case 'reindex':
// check if the block start value was passed in and is an integer
if (!isNaN(process.argv[4]) && Number.isInteger(parseFloat(process.argv[4]))) {
// Check if the block start value is less than 1
if (parseInt(process.argv[4]) < 1)
block_start = 1;
else
block_start = parseInt(process.argv[4]);
}
break;
case 'reindex':
// check if readlinesync module is installed
if (!db.fs.existsSync('./node_modules/readline-sync')) {
const { execSync } = require('child_process');
console.log('Installing missing packages.. Please wait..');
// install updated packages
execSync('npm update');
}
const readlineSync = require('readline-sync');
console.log('You are about to delete all blockchain data (transactions and addresses)');
console.log('and resync from the genesis block.');
// prompt for the reindex
if (readlineSync.keyInYN('Are you sure you want to do this? ')) {
// set mode to 'reindex'
mode = 'reindex';
break;
case 'reindex-rich':
mode = 'reindex-rich';
break;
case 'reindex-txcount':
mode = 'reindex-txcount';
break;
case 'reindex-last':
mode = 'reindex-last';
break;
default:
usage();
} else {
console.log('Process aborted. Nothing was deleted');
process.exit(0);
}
break;
case 'reindex-rich':
mode = 'reindex-rich';
break;
case 'reindex-txcount':
mode = 'reindex-txcount';
break;
case 'reindex-last':
mode = 'reindex-last';
break;
default:
usage();
}
// check if mode is set
if (mode != null) {
const path = require('path');
const pidFile = path.join(path.dirname(__dirname), 'tmp', `${database}.pid`);
// check if the script is already running (tmp/index.pid file already exists)
if (db.fs.existsSync(pidFile)) {
const { execSync } = require('child_process');
var deactivateLock = false;
// the tmp/index.pid file exists
// determine the operating system
switch (process.platform) {
case 'win32':
// windows
// run a cmd that will determine if the lock should still be active
var cmdResult = execSync(`tasklist /FI "PID eq ${db.fs.readFileSync(pidFile).toString()}"`);
// check if the process that created the lock is actually still running (crude check by testing for # of carriage returns or node.exe process running, but should work universally across different systems and languages)
if (cmdResult.toString().split('\n').length < 4 || cmdResult.toString().toLowerCase().indexOf('\nnode.exe') == -1) {
// lock should be deactivated
deactivateLock = true;
}
break;
default:
// linux or other
// run a cmd that will determine if the lock should still be active
try {
var cmdResult = execSync('ps -p `cat ' + pidFile + '` > /dev/null');
} catch (err) {
// if an error occurs, the process is NOT running and therefore the lock should be deactivated
deactivateLock = true;
}
}
// check if the lock should be deactivated
if (deactivateLock) {
// script is not actually running so the lock file can be deleted
db.fs.rmSync(pidFile);
}
}
}
} else if (process.argv[2] == 'market')
-161
View File
@@ -1,161 +0,0 @@
#!/bin/bash
readonly EXPLORER_PATH=$(dirname $(dirname $(readlink -f "$0")))
NODE_PATH=""
MODE=""
# Check if parameters were passed into the script
if [ -n "${1}" ]; then
# At least one parameter has been passed in
case ${1} in
"update")
# Index update
MODE="index update"
;;
"check")
# Index check
MODE="index check"
# Check if the next parameter exists
if [ -n "${2}" ]; then
# Add onto the check cmd
MODE="${MODE} ${2}"
fi
;;
"reindex")
# Index reindex
MODE="index reindex"
;;
"reindex-rich")
# Index reindex-rich
MODE="index reindex-rich"
;;
"reindex-txcount")
# Index reindex-txcount
MODE="index reindex-txcount"
;;
"reindex-last")
# Index reindex-last
MODE="index reindex-last"
;;
"market")
# Market update
MODE="market"
;;
"peers")
# Peers update
MODE="peers"
;;
"masternodes")
# Masternodes update
MODE="masternodes"
;;
*)
# Check if this is a file that exists on the filesystem
if [ -f ${1} ]; then
# The file exists. Assume this is the path to node
NODE_PATH="${1}"
fi
;;
esac
# Check if the mode is already set
if [ -z "${MODE}" ]; then
# Mode is not set so check if the next parameter exists
if [ -n "${2}" ]; then
# Determine which mode this last parameter is
case ${2} in
"update")
# Index update
MODE="index update"
;;
"check")
# Index check
MODE="index check"
# Check if the next parameter exists
if [ -n "${3}" ]; then
# Add onto the check cmd
MODE="${MODE} ${3}"
fi
;;
"reindex")
# Index reindex
MODE="index reindex"
;;
"reindex-rich")
# Index reindex-rich
MODE="index reindex-rich"
;;
"reindex-txcount")
# Index reindex-txcount
MODE="index reindex-txcount"
;;
"reindex-last")
# Index reindex-last
MODE="index reindex-last"
;;
"market")
# Market update
MODE="market"
;;
"peers")
# Peers update
MODE="peers"
;;
"masternodes")
# Masternodes update
MODE="masternodes"
;;
esac
elif [ -n "${NODE_PATH}" ]; then
# Node path was specified but no mode, so default to 'index update' mode
MODE="index update"
fi
fi
else
# No parameters specified so default to 'index update' mode
MODE="index update"
fi
# Check if the mode is set
if [ -n "${MODE}" ]; then
# Mode is set
# Check if the desired mode requires a lock
if [ "${MODE}" != "peers" ] && [ "${MODE}" != "masternodes" ]; then
# A lock is required
# Check if this is a reindex
if [ "${MODE}" = "index reindex" ]; then
# Prompt for the reindex
echo "You are about to delete all blockchain data (transactions and addresses)"
echo "and resync from the genesis block."
echo "Are you sure you want to do this? [y/n]: ";
read -p "" REINDEX_ANSWER
# Determine if the reindex should proceed
case "$REINDEX_ANSWER" in
y|Y|yes|Yes|YES) ;;
*) echo "Process aborted. Nothing was deleted." && exit ;;
esac
fi
# Check if the script is already running (tmp/index.pid file already exists)
if [ -f "${EXPLORER_PATH}/tmp/index.pid" ]; then
# The tmp/index.pid file exists. Check if the process is actually still running
ps -p `cat ${EXPLORER_PATH}/tmp/index.pid` > /dev/null
if [ $? -eq 0 ]; then
# Script is running so the data is locked and we must exit now and try again later
echo "Script already running.."
exit 1
else
# Script is not actually running so we can delete the lock file
rm "${EXPLORER_PATH}/tmp/index.pid"
fi
fi
fi
# Check if the node path was specified
if [ -z "${NODE_PATH}" ]; then
# Node path not specified so lookup using the 'which' cmd
eval "cd ${EXPLORER_PATH} && $(which node) scripts/sync.js ${MODE}"
else
# Node path specified
eval "cd ${EXPLORER_PATH} && ${NODE_PATH} scripts/sync.js ${MODE}"
fi
else
# Mode not set so load the sync script without specifying the mode to return the usage options
eval "cd ${EXPLORER_PATH} && $(which node) scripts/sync.js"
fi
+2 -2
View File
@@ -1172,9 +1172,9 @@
// If you sync using more than 1 parallel task, then historical balance data for wallet addresses can possibly be saved out-of-order and there is currently no workaround for this.
// Therefore, it is recommended to keep this setting to 1 parallel task for now until a proper solution can be procured for the historical balance issue.
"block_parallel_tasks": 1,
// update_timeout: The amount of time to wait (in milliseconds) before moving to the next block or transaction during blockchain sync or reindex (scripts/sync.sh /path/to/node update or scripts/sync.sh /path/to/node reindex)
// update_timeout: The amount of time to wait (in milliseconds) before moving to the next block or transaction during blockchain sync or reindex (/path/to/node scripts/sync.js update or /path/to/node scripts/sync.js reindex)
"update_timeout": 10,
// check_timeout: The amount of time to wait (in milliseconds) before moving to the next block or transaction during a check sync (scripts/sync.sh /path/to/node check)
// check_timeout: The amount of time to wait (in milliseconds) before moving to the next block or transaction during a check sync (/path/to/node scripts/sync.js check)
"check_timeout": 250,
// save_stats_after_sync_blocks: During index syncronization, stats are saved after processing this many blocks to save time by not having to save after each block
"save_stats_after_sync_blocks": 100,