Jump to content
  • 0

Adapt automatic backup Acis to Frozen


Question

Posted

hi guys! anyone can help me to adapt this code for jfrozen rev 1132?

 

Index: net.sf.l2j;Config.JAVA
===================================================================
--- net.sf.l2j;Config.JAVA (revision)
+++ net.sf.l2j;Config.JAVA (working copy)

+   /** Auto Save Data Base */
+   public static boolean ENABLE_BACKUP_BOOLEAN;
+   public static String NAME_DATA_BASE;


+   ENABLE_BACKUP_BOOLEAN = Boolean.parseBoolean(aCis.getProperty("AutoSaveDB", "True"));
+   NAME_DATA_BASE = aCis.getProperty("URL_DB", "aCis");




Index: Dev.AutoBackup;BackupDBSave.JAVA
===================================================================
--- Dev.AutoBackup;BackupDBSave.JAVA (revision)
+++ Dev.AutoBackup;BackupDBSave.JAVA (working copy)

+   package Dev.AutoBackup;
+
+   import java.io.BufferedReader;
+   import java.io.File;
+   import java.io.FileInputStream;
+   import java.io.FileOutputStream;
+   import java.io.IOException;
+   import java.io.InputStreamReader;
+   import java.net.URL;
+   import java.sql.Connection;
+   import java.sql.PreparedStatement;
+   import java.sql.ResultSet;
+   import java.text.DateFormat;
+   import java.text.SimpleDateFormat;
+   import java.util.Date;
+   import java.util.zip.ZipEntry;
+   import java.util.zip.ZipOutputStream;
+
+   import net.sf.l2j.commons.concurrent.ThreadPool;
+
+   import net.sf.l2j.Config;
+   import net.sf.l2j.L2DatabaseFactory;
+   import net.sf.l2j.util.Mysql;
+
+
+   /**
+    * @author COMBATE
+    *
+    * note to RESTORE
+    * Unzip the file
+    * Then go to database via navicat and run Execute SQL File
+    * Then declick the option "Run multiple queries in each execution" to avoid conflict with locks of tables
+    */
+   public class BackupDBSave
+   {
+       private String database_name = Config.NAME_DATA_BASE;
+       private boolean DEBUG_SYSTEM = false;
+       private long initializeAfterTime = 1000 * 60 * 60 * 1; // Start in 2 hour
+       private long checkEveryTime = 1000 * 60 * 60 * 1; // Every 6 hours
+    
+       protected BackupDBSave()
+       {
+           ThreadPool.scheduleAtFixedRate(() -> BackupDBToSql(), initializeAfterTime, checkEveryTime);
+        
+           System.out.println("Database Backup Manager: Loaded");
+       }
+
+       public void BackupDBToSql()
+       {
+           String pathOfMysql = "\"";
+        
+           Connection con = null;
+           PreparedStatement statement = null;
+           ResultSet rs = null;
+        
+           try
+           {
+               con = L2DatabaseFactory.getInstance().getConnection();
+               statement = con.prepareStatement("SELECT @@basedir");
+               rs = statement.executeQuery();
+            
+               while (rs.next())
+               {
+                   pathOfMysql += rs.getString(1);
+               }
+           }
+           catch (Exception e)
+           {
+               e.printStackTrace();
+           }
+           finally
+           {
+               Mysql.closeQuietly(con, statement, rs);
+           }
+        
+           if (pathOfMysql.isEmpty())
+           {
+               System.out.println("Error on backup database. Empty path of mysql.");
+               return;
+           }
+        
+           // Give the specific path (pathOfMysql out = C:\Program Files\MySQL\MySQL Server 5.7\)
+           pathOfMysql += "bin\\mysqldump" + "\"";
+        
+           if(DEBUG_SYSTEM) System.out.println("Path of mysql: " + pathOfMysql);
+        
+           // Initialize code for backup
+           try
+           {
+               // Section for path of system
+               URL applicationRootPathURL = getClass().getProtectionDomain().getCodeSource().getLocation();
+               File applicationRootPath = new File(applicationRootPathURL.getPath());
+               File myFile = new File(applicationRootPath.getParent());
+               File lastMyFile = new File(myFile.getParent());
+
+               String dbUser = Config.DATABASE_LOGIN;
+               String dbPass = Config.DATABASE_PASSWORD;
+            
+               String commandOfMysqlDump = " " + database_name + " --single-transaction -u" + dbUser + " -p" + dbPass + " --skip-create-options --skip-comments --disable-keys > ";
+            
+               /* NOTE: Creating Path Constraints for folder saving */
+               /* NOTE: Here the backup folder is created for saving inside it */
+               String folderPath = "backup";
+            
+               /* NOTE: Creating Folder if it does not exist */
+               File f1 = new File(folderPath);
+               f1.mkdir();
+            
+               /* NOTE: Creating Path Constraints for backup saving */
+               /* NOTE: Here the backup is saved in a folder called backup with the name backup.sql */
+               String pathUntilDirectory = (lastMyFile.getAbsolutePath() + "\\backup\\").replaceAll("%20", " ");
+               String savePath = ("\""+pathUntilDirectory + "backup.sql\"").replaceAll("%20", " ");
+
+               /* NOTE: Used to create a cmd command */
+               String commandToExecute = "cmd /c "+ pathOfMysql + commandOfMysqlDump + savePath;
+            
+               if (DEBUG_SYSTEM)
+               {
+                   System.out.println("Save path of sql file: " + savePath);
+                   System.out.println("Command To Execute: " + commandToExecute);
+               }
+            
+               /* NOTE: Executing the command here */
+               Process runtimeProcess = Runtime.getRuntime().exec(new String[] {"cmd", "/c", commandToExecute });
+            
+               if (DEBUG_SYSTEM)
+               {
+                   BufferedReader stdInput = new BufferedReader(new InputStreamReader(runtimeProcess.getInputStream()));
+                   BufferedReader stdError = new BufferedReader(new InputStreamReader(runtimeProcess.getErrorStream()));
+                
+                   // read the output from the command
+                   System.out.println("Here is the standard output of the command:\n");
+                   String s = null;
+                   while ((s = stdInput.readLine()) != null) {
+                       System.out.println(s);
+                   }
+                
+                   // read any errors from the attempted command
+                   System.out.println("Here is the standard error of the command (if any):\n");
+                   while ((s = stdError.readLine()) != null) {
+                       System.out.println(s);
+                   }
+               }
+            
+               int processComplete = runtimeProcess.waitFor();
+            
+               /* NOTE: processComplete=0 if correctly executed, will contain other values if not */
+               if (processComplete == 0)
+               {
+                   System.out.println("Backup to SQL Complete");
+                
+                   // Zip the sql file
+                   zipAFile(pathUntilDirectory);
+                
+                   // Delete the backup.sql file
+                   deleteAFile(savePath.replaceAll("\"", ""));
+               }
+               else
+               {
+                   System.out.println("Backup to SQL Failure");
+               }
+           }
+           catch (IOException | InterruptedException ex)
+           {
+               System.out.println("Error at Backuprestore" + ex.getMessage());
+           }
+       }
+    
+       @SuppressWarnings("resource")
+       private static void zipAFile(String pathToSave)
+       {
+           byte[] buffer = new byte[1024];
+        
+           try
+           {
+               DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH-mm-ss");
+               Date date = new Date();
+            
+               FileOutputStream fos = new FileOutputStream(pathToSave + "Backup_"+dateFormat.format(date)+".zip");
+               ZipOutputStream zos = new ZipOutputStream(fos);
+               ZipEntry ze = new ZipEntry("backup.sql");
+               zos.putNextEntry(ze);
+               FileInputStream in = new FileInputStream(pathToSave + "\\backup.sql");
+            
+               int len;
+               while ((len = in.read(buffer)) > 0)
+               {
+                   zos.write(buffer, 0, len);
+               }
+            
+               in.close();
+               zos.closeEntry();
+            
+               // remember close it
+               zos.close();
+            
+               System.out.println("Done the zip of backup.");
+            
+           }
+           catch (IOException ex)
+           {
+               ex.printStackTrace();
+           }
+        
+       }
+    
+       private static void deleteAFile(String path) {
+           try{
+               File file = new File(path);
+               System.out.println(file.delete() ? (file.getName() + " is deleted!") : ("Delete operation is failed."));
+            
+           }catch(Exception e){
+
+               e.printStackTrace();
+
+           }
+       }
+
+       public static BackupDBSave getInstance()
+       {
+           return SingletonHolder._instance;
+       }
+    
+       private static class SingletonHolder
+       {
+           protected static final BackupDBSave _instance = new BackupDBSave();
+       }
+   }
+    

Index: Dev.AutoBackup;Mysql.JAVA
===================================================================
--- Dev.AutoBackup;Mysql.JAVA (revision)
+++ Dev.AutoBackup;Mysql.JAVA (working copy)

+   package Dev.AutoBackup;
+
+
+   import java.sql.Connection;
+   import java.sql.PreparedStatement;
+   import java.sql.ResultSet;
+   import java.sql.SQLException;
+   import java.sql.Statement;
+   import java.util.logging.Logger;
+
+   import net.sf.l2j.L2DatabaseFactory;
+
+   /**
+    * @author COMBATE
+    *
+    */
+   public abstract class Mysql
+   {
+       private static final Logger _log = Logger.getLogger(Mysql.class.getName());
+
+       /**
+        * Performs a simple sql queries where unnecessary control parameters <BR>
+        * NOTE: In this method, the parameters passed are not valid for SQL-injection!
+        * @param db
+        * @param query
+        * @param vars
+        * @return
+        */
+       public static boolean setEx(L2DatabaseFactory db, String query, Object... vars)
+       {
+           Connection con = null;
+           Statement statement = null;
+           PreparedStatement pstatement = null;
+           boolean successed = true;
+        
+           try
+           {
+               if(db == null)
+                   db = L2DatabaseFactory.getInstance();
+
+               con = db.getConnection();
+               if(vars.length == 0)
+               {
+                   statement = con.createStatement();
+                   statement.executeUpdate(query);
+                   statement.close();
+               }
+               else
+               {
+                   pstatement = con.prepareStatement(query);
+                   setVars(pstatement, vars);
+                   pstatement.executeUpdate();
+                   pstatement.close();
+               }
+               con.close();
+           }
+           catch(Exception e)
+           {
+               _log.warning("Could not execute update '" + query + "': " + e);
+               e.printStackTrace();
+               successed = false;
+           }
+           finally
+           {
+               closeQuietly(con, pstatement);
+               closeQuietly(statement);
+           }
+           return successed;
+       }
+
+       public static void setVars(PreparedStatement statement, Object... vars) throws SQLException
+       {
+           Number n;
+           long long_val;
+           double double_val;
+           for(int i = 0; i < vars.length; i++)
+               if(vars[i] instanceof Number)
+               {
+                   n = (Number) vars[i];
+                   long_val = n.longValue();
+                   double_val = n.doubleValue();
+                   if(long_val == double_val)
+                       statement.setLong(i + 1, long_val);
+                   else
+                       statement.setDouble(i + 1, double_val);
+               }
+               else if(vars[i] instanceof String)
+                   statement.setString(i + 1, (String) vars[i]);
+       }
+
+       public static boolean set(String query, Object... vars)
+       {
+           return setEx(null, query, vars);
+       }
+
+       public static boolean set(String query)
+       {
+           return setEx(null, query);
+       }
+    
+       public static void closeQuietly(Connection conn)
+       {
+           try {
+               close(conn);
+           } catch (SQLException e) { // NOPMD
+               // quiet
+           }
+       }
+
+       public static void closeQuietly(Connection conn, Statement stmt, ResultSet rs) {
+
+           try {
+               closeQuietly(rs);
+           } finally {
+               try {
+                   closeQuietly(stmt);
+               } finally {
+                   closeQuietly(conn);
+               }
+           }
+       }
+    
+       public static void closeQuietly(Connection conn, Statement stmt)
+       {
+           try {
+               closeQuietly(stmt);
+           } finally {
+               closeQuietly(conn);
+           }
+       }
+
+       public static void closeQuietly(ResultSet rs) {
+           try {
+               close(rs);
+           } catch (SQLException e) { // NOPMD
+               // quiet
+           }
+       }
+
+       public static void closeQuietly(Statement stmt) {
+           try {
+               close(stmt);
+           } catch (SQLException e) { // NOPMD
+               // quiet
+           }
+       }
+
+       public static void close(Connection conn) throws SQLException {
+           if (conn != null) {
+               conn.close();
+           }
+       }
+
+       public static void close(ResultSet rs) throws SQLException {
+           if (rs != null) {
+               rs.close();
+           }
+       }
+
+       public static void close(Statement stmt) throws SQLException {
+           if (stmt != null) {
+               stmt.close();
+           }
+       }
+   }
+

Index: net.sf.l2j.gameserver;GameServer.JAVA
===================================================================
--- net.sf.l2j.gameserver;GameServer.JAVA (revision)
+++ net.sf.l2j.gameserver;GameServer.JAVA (working copy)

+   import Dev.AutoBackup.BackupDBSave;

+   StringUtil.printSection("DataBase Auto Save");
+   if (Config.ENABLE_BACKUP_BOOLEAN) {
+       BackupDBSave.getInstance();
+       LOGGER.info("[DataBase Auto Save]: Enabled");
+   }else
+   {
+       LOGGER.info("[DataBase Auto Save]: Desatived");
+   }

Index: gameserver.config.aCis.aCis.properties
===================================================================
--- gameserver.config.aCis.aCis.properties (revision)
+++ gameserver.config.aCis.aCis.properties (working copy)

# Enable Auto Save DataBase
AutoSaveDB = True

#Name DataBase
#Ex: l2jdb
URL_DB = aCis

 

4 answers to this question

Recommended Posts

  • 0
Posted

Make backup database with runned server it's stupid idea. Backup will always is outdated. Better add to bat/sh scripts the dump task for saving database snapshot with relevant data.

  • 0
Posted
5 hours ago, Rootware said:

Make backup database with runned server it's stupid idea. Backup will always is outdated. Better add to bat/sh scripts the dump task for saving database snapshot with relevant data.

Hi @Rootware ! thanks for answer. can, maybe if u have some time, tell me how can i do it that?

  • 0
Posted (edited)

"mysql generate backup" on Google. And yes, it is kinda stupid to save during runtime since some data is stored only when server shutdowns, or when player shutdowns. If you save in middle of nowhere, then data integrity will be different than when server is currently closing.

 

Properly close your server, then use mysqldump.

 

It's the typical sort of code which "sounds cool", but is at best pointless, at worst dangerous (since you can save things in middle of something, and got no guarantee the actual engine properly ended).

 

An "ok" move would be to generate it only when server actually shutdowned, after all server operations ended.

Edited by Tryskell
  • 0
Posted
5 hours ago, Tryskell said:

"mysql generate backup" on Google. And yes, it is kinda stupid to save during runtime since some data is stored only when server shutdowns, or when player shutdowns. If you save in middle of nowhere, then data integrity will be different than when server is currently closing.

 

Properly close your server, then use mysqldump.

 

It's the typical sort of code which "sounds cool", but is at best pointless, at worst dangerous (since you can save things in middle of something, and got no guarantee the actual engine properly ended).

 

An "ok" move would be to generate it only when server actually shutdowned, after all server operations ended.

@Tryskell hi man! so, you say make a sincronized backup with mysql when the server restart?

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Posts

    • --- Interlude Faction/GvE PvP grand opening 2025-11-15 19:00 GMT+2 ---   Gameplay: Chronicle: Interlude Type: Faction/GvE (Angels vs Nature vs Demons) GM Shop: B-S grade Buff slots: 20+4 Starting level: 74 + rebirth system   New Features: Client: Modern interface based on Essence Balance: New class skills for better balance Achievement Rewards: Daily, Weekly, One-time TOP rankings: PvP, Event PvP, Map PvP, Clan PvP, Event MvP, Map MvP Zones: 70 different PvP zones,  18 different events (8 map events | 10 main events) 12 Grand/raid bosses. Castle siege Olympiad Clan Hall challenge Custom Enchant System: Dynamic success chance (greater enchant level or item grade less enchanting success chance) Enchant rate: Blessed scrolls dynamic from 100% to 25%. Crystal Scrolls: 100%; Max enchant weapon +12 Max enchant armor +8 Safe point enchant system Extra Features: PvP items with level upgrade Weapon/Armor upgrade (from B grade to S) system Attributes system   Website: https://l2cygnus.com Community: Discord Facebook: https://www.facebook.com/l2cygnus Youtube:   
    • More fluid combat, not 100% yet, but I think it's acceptable. I put the following logic in movetopawn, moveto, maybemovetopawn, validatelocation, movetolocation: If Config.GeoData is active, it applies the coordinates using geodata; if disabled, use setdistanceplansq to measure the distance of things! Fix for reflected damage (if the attacker is null, it will not be calculated). Minor improvements to the Day/Night item generation manager. Fix to not punish players who destroy items with a count = 0... Fix for when a player tried to use a resurrection scroll while seated, it disappeared without effect. Fix for when it was possible to equip armor while paralyzed. Cleanup of System message. Rework of PathNodes. Fixed the ia for mobs attack range when chasing the player (test) Fixed Pathnodes loading Added # ------------------------ #Show Red Name for Aggressive Mobs # ------------------------ ShowRedName = True Which was missing in the configs
    • ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ⚔️ L2JOmen High Five - SERVIDOR 100% RETAIL ⚔️ 📢 SOLICITAMOS APOYO PARA TESTING 📢 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ¡Saludos, comunidad de Lineage II! Estamos desarrollando un proyecto ambicioso y de calidad: L2JOmen High Five, un servidor  100% RETAIL que busca ofrecer la experiencia más auténtica de High Five.  Nos encontramos en la fase de desarrollo y testing, y necesitamos tu ayuda para hacerlo  grande. Si eres un amante del retail, disfrutas probar nuevas funciones y quieres formar  parte de un proyecto serio desde sus inicios, ¡tu apoyo es invaluable! ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 🎮 CARACTERÍSTICAS PRINCIPALES 🎮 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ✅ SERVIDOR 100% RETAIL    • Experiencia auténtica de High Five    • Geodata PTS Official    • Plataforma Premium 2025 ✅ SISTEMA DE RATES DINÁMICO (Progresión Retail x1 con ayuda x5 -> x1)    • XP: 1-20 (5.0x) | 21-40 (3.0x) | 41-60 (2.0x) | 61-75 (1.5x) | 76-85 (1.0x)    • SP: 1-20 (5.0x) | 21-40 (3.0x) | 41-60 (2.0x) | 61-75 (1.5x) | 76-85 (1.0x)    • Adena: x2.0 (Retail con pequeño ajuste)    • Drop y Spoil: x1.0 (Mobs, Raids y Epics) ✅ SISTEMA DE ENCANTAMIENTO PROFESIONAL    • Enchant Safe: +6 (100% seguro hasta +6)    • Enchant Máximo: +30    • Tasas de encantamiento balanceadas:      * 0-3: 100% | 4: 80% | 5: 75% | 6: 70% | 7: 65% | 8: 60%      * 9: 55% | 10: 50% | 11: 45% | 12: 40%      * 13: 10% | 14-25: 5-9% | 26-30: 1-4%    • Sistema Blessed Enchant habilitado ✅ INICIO DE PERSONAJE    • Dynasty Masterwork Set completo +12    • 1 Ticket para Weapon S +12    • Duración: 7 días ✅ CONFIGURACIÓN RETAIL    • Element Limit: Nivel 4    • Buffs: Duración de 1 hora    • Nobless: Obtenible mediante quest    • Subclass Máxima: 10 (Certificación para cada Subclass) ✅ SISTEMA DE FARM Y ECONOMÍA    • Múltiples monedas de farm (Adena, Ancient Adena, Coin of Luck, PC Bang Points, Farm Coins)    • Varias zonas de farm disponibles    • Zona de Party Farm (se habilita cada 3 horas por 1 hora)    • 4 Raids diarias programadas ✅ SISTEMA PC BANG POINTS    • Aproximadamente 10,000 puntos por 24 horas conectado    • Entrega cada 10 minutos    • Jugadores Normales: 60-72 puntos/intervalo    • Jugadores Premium: 96-116 puntos/intervalo    • 5% probabilidad de doble puntos ✅ SHOPS COMPLETOS    • Shop Normal (Adena y Farm Coins)    • Shop Donate (con opciones premium)    • Armaduras y Armas hasta Grado Dynasty, Moirai, S84    • Joyas completas, no incluye Epics    • Scrolls (Normales, Blessed, Divine, Ancient)    • Elementos hasta nivel 4-7    • Accesorios y consumibles ✅ SISTEMA VIP    • 5 niveles de VIP disponibles    • Bonificaciones progresivas de XP/SP/Drop    • Recompensas diarias exclusivas ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 🤝 ¿QUÉ NECESITAMOS DE TI? 🤝 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 🔍 TESTERS ACTIVOS    • Jugadores que prueben todas las funciones del servidor    • Feedback constructivo sobre bugs, balance y mejoras    • Reporte de problemas encontrados 🎮 JUGADORES DEDICADOS    • Amantes del retail que valoren la experiencia auténtica    • Personas dispuestas a ayudar a mejorar el proyecto    • Comunidad comprometida con el crecimiento del servidor 📊 REPORTES DETALLADOS    • Bugs y errores encontrados    • Sugerencias de balance    • Opiniones sobre el gameplay    • Feedback sobre sistemas implementados ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 💎 ¿POR QUÉ UNIRTE A L2JOmen? 💎 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 🌟 PROYECTO SERIO Y COMPROMETIDO    • Desarrollo constante y mejoras continuas    • Atención a la comunidad activa    • Transparencia en todas las decisiones 🎯 EXPERIENCIA 100% RETAIL    • Sin modificaciones que rompan el juego original    • Balance auténtico de High Five    • Gameplay puro y tradicional ⚡ TECNOLOGÍA DE VANGUARDIA    • Servidor optimizado y estable    • Geodata oficial de PTS    • Sistema robusto y sin lag    • Sistema Anticheat Premium 🎁 RECOMPENSAS PARA TESTERS    • Participación activa en el desarrollo    • Reconocimiento especial en el lanzamiento    • Beneficios exclusivos para early testers ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 📞 CONTACTO E INFORMACIÓN 📞 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Si estás interesado en formar parte de este proyecto y ayudarnos a crear el mejor  servidor retail de High Five, contáctanos. Tu apoyo es fundamental para hacer realidad  este grandioso proyecto. 💬 Únete a nuestro grupo de testing 🌐 WhatsApp: https://chat.whatsapp.com/Km6uRtFsoUq2tNZZalo5HB?mode=wwt ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 🏆 ¡Juntos construimos el mejor servidor retail! 🏆 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━  
    • any server used these files? if yes let me know in pm.
    • L2Net is an in-game (IG) bot. I already have Adrenaline for that. I'm looking for an out-of-game (OOG) bot - one that doesn’t require the Lineage 2 client to run.
  • Topics

×
×
  • Create New...

AdBlock Extension Detected!

Our website is made possible by displaying online advertisements to our members.

Please disable AdBlock browser extension first, to be able to use our community.

I've Disabled AdBlock