Как создать функцию автоматического резервного копирования в моем приложении Java на платформе Netbeans? - PullRequest
1 голос
/ 23 марта 2012

Не так много кода, так как я немного растерялся, как начать.

Я пытаюсь создать приложение, которое создает резервную копию базы данных Derby и сохраняет данные пользователей.У меня есть код для самой резервной копии, которая может быть запущена вручную.Я хочу создать функцию, которая будет проверять файл настроек и выполнять резервное копирование в надлежащее расписание (ежедневно, еженедельно, ежемесячно).Я думаю, что смогу проверить это при запуске, но есть проблема, если приложение работает, я бы хотел, чтобы оно периодически проверяло время.Существует хорошая вероятность, что это приложение будет работать несколько дней подряд.

Я также хочу разрешить пользователям "спать" резервное копирование на несколько часов, если наступило запланированное время.

У меня может быть Thread.Sleep (), вызываемый при загрузке, и он должен проверяться каждые X минут / часов.Точно так же, если они хотят спать резервное копирование.Я не уверен, что это лучший способ сделать это.Я предполагаю, что любой вызов API, вероятно, будет делать то же самое, но мне интересно, если я что-то упускаю при обработке такого потока.

Есть ли какие-либо функции / библиотеки в IDE и платформе Netbeans, которые ям, что я мог бы использовать, чтобы помочь мне построить эту функциональность?

Спасибо

1 Ответ

0 голосов
/ 29 марта 2012

Вот как я это реализовал. Я немного изменил способ реализации, так что этот ответ не совсем так, как был сформулирован вопрос. Я удалил функцию «сна», но используя код, который я предоставляю, вы можете легко реализовать его. У меня это частично реализовано, и я покажу код ниже. В основном это включает в себя создание нескольких классов, которые реализуют Runnable. Фактический код для запуска резервного копирования не отображается. В любом случае, это будет зависеть от платформы, так что обращайтесь с ней, как с ней. Мы используем Derby, поэтому наши резервные копии обрабатываются.

Я разделю его по классам и функциям:

DatabaseBackupReminder. Этот класс обрабатывает запрос для пользователя, который сообщает ему, сколько времени прошло с момента последнего резервного копирования, и позволяет ему перевести напоминание в течение X часов. Он сам по себе является потоком, поэтому его можно вызывать где-то еще и также спать, поэтому он не постоянно проверяет базу данных, чтобы узнать, когда было запущено последнее резервное копирование.

public class DatabaseBackupReminder extends Thread

/*****************Variables ****************/
String backupFrequency; //How often to backup? Daily, Monthly, Weekly, or Never
String backupTimeOfDay; //I don't use this, but the idea was to autobackup morning,  
                        //day, or night
boolean backupIsSet = false;    //Have they set a schedule?
Timestamp lastBackupRunTime; //Pulled from our Derby database to see when the backup was run
Timestamp backupScheduleSetTime; //Pulled from the DB to see when the user set the schedule
                                //This is so, if they set it to daily, we will check 24hrs from the set date for
                                //backup validity
Period periodSinceLastBackup; //Using the Joda library, we use this to calculate
boolean backupEverRan; //We check to see if they've ever backed up
                                    //Useful logic for clear dialog purposes.
public enum enumBackupFrequencies {DAILY, WEEKLY, MONTHLY, NEVER} //use a valueOf with the backupFrequency.
//We're using java 1.7, no Switch on strings, this is a workaround
   Herd herd;//Herd is a custom datatype we use, it's basically a wrapper around a Derby table.
/*******************methods***************************************/                                     
    public DatabaseBackupReminder(String backupFrequency, String backupTimeOfDay, Timestamp lastBackupRunTime, Timestamp backupScheduleSetTime, Herd herd) 
    //Constructor
    //Herd is a custom datatype we use, it's basically a wrapper around a Derby table.
    boolean getBackupStillValid() //Checks based on lastBackupRunTime, and backupEverRan to see
    //if we have a valid backup

    public void promptForBackup(Period duration, boolean backupEverRunx) 
        //Take's the duration & has it ever run and displays a message.
        //Something like "It's been 2 weeks, 1 days since your last backup"
        //Not fully implemented, this was scrapped, but I'll explain how I think it should have worked below

    public void run()
    //Main thread for this reminder
    public String timeSinceLastBackupString()
    //Calls it based on objects values, not specific values, see method below
    public String timeSinceLastBackupString(Period duration, boolean backupEverRunx)
    //Constructs the string used in promptForBackup



/********full method code**********/
public DatabaseBackupReminder(String backupFrequency, String backupTimeOfDay, Timestamp lastBackupRunTime, Timestamp backupScheduleSetTime, Herd herd) {
    this.herd = herd;
    if (backupFrequency == null) {
        backupFrequency = "";
    }
    if (backupTimeOfDay == null) {
        backupTimeOfDay = "";
    }
    if (backupScheduleSetTime == null) {
        this.backupScheduleSetTime = new Timestamp(0);
    } else {
        this.backupScheduleSetTime = backupScheduleSetTime;
    }
    this.backupFrequency = backupFrequency;
    this.backupTimeOfDay = backupTimeOfDay;
    if (lastBackupRunTime == null) {
        this.lastBackupRunTime = new Timestamp(0);
    } else {
        this.lastBackupRunTime = lastBackupRunTime;
    }
    periodSinceLastBackup = new Period(this.lastBackupRunTime.getTime(), Calendar.getInstance().getTimeInMillis());
    if (backupFrequency.trim().length() > 1) {
        backupIsSet = true;
    }
    backupEverRan = false;
    if (this.lastBackupRunTime.getTime() != 0) {
        backupEverRan = true;
    }
}

 boolean getBackupStillValid() {
    if (lastBackupRunTime.getTime() > 0) {
        backupEverRan = true;

    } else {
        return false;
    }
    if (backupFrequency.trim().length() > 1) {
        backupIsSet = true;

    }


    if (backupIsSet) {
        switch (enumBackupFrequencies.valueOf(backupFrequency.trim().toUpperCase())) {
            case DAILY:
                if (periodSinceLastBackup.getYears() > 1 || periodSinceLastBackup.getMonths() > 1 || periodSinceLastBackup.getWeeks() > 1 || periodSinceLastBackup.getDays() >= 1) {

                    return false;
                }
                break;
            case WEEKLY:
                if (periodSinceLastBackup.getYears() > 1 || periodSinceLastBackup.getMonths() > 1 || periodSinceLastBackup.getWeeks() >= 1) {
                    return false;

                }
                break;
            case MONTHLY:
                if (periodSinceLastBackup.getYears() > 1 || periodSinceLastBackup.getMonths() >= 1) {
                    return false;

                }
                break;
            case NEVER:
        }
    }
    if (backupEverRan) {
        return true;
    } else {
        return false;
    }

}

public void run() {

    if (backupIsSet) {
        switch (enumBackupFrequencies.valueOf(backupFrequency.trim().toUpperCase())) {
            case DAILY:
                if (periodSinceLastBackup.getYears() > 1 || periodSinceLastBackup.getMonths() > 1 || periodSinceLastBackup.getWeeks() > 1 || periodSinceLastBackup.getDays() > 1) {

                    promptForBackup(periodSinceLastBackup, backupEverRan);

                }
                break;
            case WEEKLY:
                if (periodSinceLastBackup.getYears() > 1 || periodSinceLastBackup.getMonths() > 1 || periodSinceLastBackup.getWeeks() > 1) {
                    promptForBackup(periodSinceLastBackup, backupEverRan);

                }
                break;
            case MONTHLY:
                if (periodSinceLastBackup.getYears() > 1 || periodSinceLastBackup.getMonths() > 1) {
                    promptForBackup(periodSinceLastBackup, backupEverRan);

                }
                break;
            case NEVER:
        }
    }



}
public void promptForBackup(Period duration, boolean backupEverRun) {
    int response;
    long delay = 0;

    response = JOptionPane.showConfirmDialog(null, timeSinceLastBackupString(duration, backupEverRun));
    if (response == JOptionPane.NO_OPTION) {
        //TODO: open "how long to remind" dialog
        BackupSnoozePanel snoozePanel = new BackupSnoozePanel();

        JOptionPane.showMessageDialog(null, snoozePanel);

        switch (snoozePanel.BackupDelayInterval.getSelectedIndex()) {
            case 0:
                delay = 5000; //5 seconds, for testing
                //delay = 60 * 60 * 1000; // 1 hour
                break;
            case 1:
                delay = 10000; //10 seconds, for testing
                //delay = 4 * 60 * 60 * 1000; // 4 hours
                break;
            case 2:
                delay = 15000; //15 seconds, for testing
                //delay = 8 * 60 * 60 * 1000; // 8 hours
                break;
            case 3:
                delay = 20000; //20 seconds, for testing
                ///delay = 12 * 60 * 60 * 1000; // 12 hours
                break;
            case 4:
                delay = 0; //next boot
                break;
        }


    } else {
        //TODO: run backup    
    }
    try {

        if (delay > 0) {
        //TODO: Code to sleep this reminder. Thread.sleep(delay) probably

        }
    } catch (Exception ex) {
        //TODO: something to handle exceptions
    }

}//end promptForBackup

 public String timeSinceLastBackupString(Period duration, boolean backupEverRunx) {

    if (!backupEverRunx) {
        return "The backup has never been run. Would you like to run one?";
    }


    String durationString = "It has been ";
    if (duration.getYears() >= 1) {
        durationString += duration.getYears() + " years";
    }
    if (duration.getMonths() >= 1) {
        durationString += duration.getMonths() + " months";
    }
    if (duration.getWeeks() >= 1) {
        durationString += duration.getWeeks() + " weeks ";
    }
    if (duration.getDays() >= 1) {
        durationString += duration.getDays() + " days";
    }
    durationString += " since your last backup. Would you like to run one?";
    return durationString;
}

public String timeSinceLastBackupString() {
    return timeSinceLastBackupString(periodSinceLastBackup, backupEverRan);



}

DatabaseBackupController. Этот класс, как он называется, контролирует весь процесс. От напоминания до фактического выполнения резервного кода.

public class DatabaseBackupController
/***********variables*************/
String scheduleText; //Daily, Weekly, Monthy, or Never. It's set in our options panel.
String timeText; //Time of day to run the backup, morning, day, or night. As 04:00-12:00 etc…
Timestamp lastBackupRun; //Timestamp from DB (Herd is our abstracted class) from when it was last run.
Timestamp lastBackupRunScheduleSetTime; //Timestamp from DB when the backup was set.
Herd herd; //Herd is a custom datatype we use, it's basically a wrapper around a Derby table.

/***********Method Headers**********/
public DatabaseBackupController(Herd herd) //Constructor
//Sets global variables, based on values in DB
public void setupBackupReminder() 
//calls DatabaseBackupReminder, passes global variables.
public boolean checkBackupReminder()
//Checks to make sure the current backup is valid within the duration since last backup
public void runBackupPrompt() 
//When we are in fact going to backup, calls BackupRunner instance.


/**********full method code****************/
    public DatabaseBackupController(Herd herd) {
    this.herd = herd;
    scheduleText = herd.getBackupSchedule();
    timeText = herd.getBackupTime();
    lastBackupRun = herd.getBackupScheduledLastRun();
    lastBackupRunScheduleSetTime = herd.getBackupScheduledDatetime();
}

public void setupBackupReminder() {
    DatabaseBackupReminder dbReminder = new DatabaseBackupReminder(scheduleText, timeText, lastBackupRun, lastBackupRunScheduleSetTime, herd);
    Thread dbBackupThread = new Thread(dbReminder);

    dbBackupThread.start();
}//end setupBackupReminder

public boolean checkBackupReminder() {
    DatabaseBackupReminder dbReminder = new DatabaseBackupReminder(scheduleText, timeText, lastBackupRun, lastBackupRunScheduleSetTime, herd);
    return dbReminder.getBackupStillValid();
}

public void runBackupPrompt() {
    DatabaseBackupReminder dbReminder = new DatabaseBackupReminder(scheduleText, timeText, lastBackupRun, lastBackupRunScheduleSetTime, herd);
    int response = JOptionPane.showConfirmDialog(null, dbReminder.timeSinceLastBackupString());
    if (response == JOptionPane.YES_OPTION) {
        //NbPreferences.forModule(BackupSettingsPanel.class).putLong("databaseschedullastrun", Calendar.getInstance().getTimeInMillis());
        LoadStatusDialog lsd;
        lsd = null;
        lsd = new LoadStatusDialog(WindowManager.getDefault().getMainWindow(), false, true);
        lsd.setVisible(true);
        Thread br = new Thread(new BackupRunner(herd,lsd));
        br.start();
    }
}
}//end class

Класс DbBackupAction обрабатывает локальный аспект резервного копирования. Мы выполняем локальное резервное копирование, а затем отправляем этот файл за границу в другой класс. Это реализует работоспособный, поэтому он будет обрабатывать резервное копирование асинхронно и не приведет к зависанию всей программы.

class DbBackupAction implements Runnable {

private boolean backupSuccess;

public DbBackupAction() {
    this.backupSuccess = false;
}

public void runBackup() {
}

@Override
public void run() {
    Connection connection = JDBCUtils.getConnection();
    String dbName = NbPreferences.forModule(DatabasePanel.class).get("dbName", "");
    try {
        DerbyUtils.backUpDatabase(connection, dbName);
    } catch (SQLException ex) {
        Exceptions.printStackTrace(ex);
    }
    setBackupSuccess(true);
}

/**
 * @return the backupSuccess
 */
public boolean isBackupSuccess() {
    return backupSuccess;
}

/**
 * @param backupSuccess the backupSuccess to set
 */
public void setBackupSuccess(boolean backupSuccess) {
    this.backupSuccess = backupSuccess;
}
}

BackupRunner обрабатывает резервные копии как на месте, так и за его пределами. Использует DbBackupAction && RemoteBackupAction

class BackupRunner implements Runnable {

Herd herd;
LoadStatusDialog lsd; 

BackupRunner(Herd herd, LoadStatusDialog lsd) {
    this.herd = herd;
    this.lsd = lsd;
}

@Override
public void run() {



    DbBackupAction dba = new DbBackupAction();
    Thread dbaThread = new Thread(dba);

    dbaThread.start();
    while (dbaThread.isAlive()) {
        try {
            dbaThread.join();
        } catch (InterruptedException ex) {
            Exceptions.printStackTrace(ex);
        }
    }


    if (dba.isBackupSuccess()) {

        RemoteBackupAction rba = new RemoteBackupAction();
        lsd.setProgressBarIndeterminate(true);
        Thread rbaThread = new Thread(rba);
        rbaThread.start();
        while (rbaThread.isAlive()) {
            try {
                rbaThread.join();
            } catch (InterruptedException ex) {
                Exceptions.printStackTrace(ex);
            }
        }



        if (rba.isBackupSuccess()) {


            herd.setBackupScheduledLastRun(new Timestamp(Calendar.getInstance().getTimeInMillis()));
            HerdService hs = new HerdDaoService();
            hs.update(herd);

            EventBus.publish(new RefreshStartScreenEvent());
        }
    }
}
}

RemoteBackupAction управляет удаленным резервным копированием по FTP.

class RemoteBackupAction implements Runnable {

Thread thread;
LoadStatusDialog lsd;
File backupFile;
Pref pref;
private boolean backupSuccess;

public RemoteBackupAction() {
    backupSuccess = false;
}

public void runThread() {

                backupSuccess = true;

                try {
                    DerbyUtils.remoteBackupDatabase(backupFile);
                } catch (SQLException ex) {
                    JOptionPane.showMessageDialog(null,
                            "This option is not available when working offline.");
                    System.out.println("SQLExcption: " + ex);
                    backupSuccess = false;
                } catch (Exception ex) {
                    JOptionPane.showMessageDialog(null,
                            "Unable to connection to ftp site for remote backup.");
                    System.out.println("IOExcption: " + ex);
                    backupSuccess = false;
                }



}

public void startOffsiteBackup() {
    pref = CentralLookup.getDefault().lookup(Pref.class);
    System.out.println("pref.isOnline(): " + pref.isOnline());
    if (!pref.isOnline()) {
        JOptionPane.showMessageDialog(null,
                "This option is not available when working offline.");
        return;
    }

    File[] files = DerbyUtils.getListOfBackups();
    if ((files == null) || (files.length < 1)) {
        JOptionPane.showMessageDialog(null,
                "There are no backup files available for upload. "
                + "Please create a local backup.");
        return;
    }
    Backup[] backups = new Backup[files.length];
    if (files.length > 0) {
        Date[] dates = new Date[files.length];
        String[] herdCodes = new String[files.length];
        SimpleDateFormat inFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm");
        for (int i = 0; i < files.length; i++) {
            try {
                String[] splitFileName = files[i].getName().split("_");
                herdCodes[i] = splitFileName[0];
                dates[i] = inFormat.parse(splitFileName[1].split("//.")[0]);
                backups[i] = new Backup(herdCodes[i], files[i], files[i].getName(), dates[i]);
            } catch (ParseException ex) {
                Exceptions.printStackTrace(ex);
            }
        }
    } else {
        System.out.println("no backup files yet");
    }

    Arrays.sort(backups, Collections.reverseOrder());

    if (backups[0] != null) {

        this.backupFile = backups[0].getFile();
    } else {
        // Cancel button selected
        return;
    }

    runThread();
}

/**
 * @return the backupSuccess
 */
public boolean isBackupSuccess() {
    return backupSuccess;
}

@Override
public void run() {
    startOffsiteBackup();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...