com.netflix.dynomitemanager.sidecore.backup.SnapshotTask.java Source code

Java tutorial

Introduction

Here is the source code for com.netflix.dynomitemanager.sidecore.backup.SnapshotTask.java

Source

/**
 * Copyright 2016 Netflix, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.netflix.dynomitemanager.sidecore.backup;

import java.io.File;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.joda.time.DateTime;

import com.google.common.collect.Lists;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.google.inject.name.Named;

import com.netflix.dynomitemanager.InstanceState;
import com.netflix.dynomitemanager.sidecore.IConfiguration;
import com.netflix.dynomitemanager.sidecore.ICredential;
import com.netflix.dynomitemanager.identity.InstanceIdentity;
import com.netflix.dynomitemanager.sidecore.scheduler.SimpleTimer;
import com.netflix.dynomitemanager.sidecore.scheduler.Task;
import com.netflix.dynomitemanager.sidecore.scheduler.TaskTimer;
import com.netflix.dynomitemanager.sidecore.storage.StorageProxy;
import com.netflix.dynomitemanager.sidecore.utils.ThreadSleeper;
import com.netflix.dynomitemanager.sidecore.scheduler.CronTimer;
import com.netflix.dynomitemanager.sidecore.scheduler.CronTimer.DayOfWeek;

/**
 * Task for taking snapshots
 */
@Singleton
public class SnapshotTask extends Task {
    public static final String TaskName = "SnapshotTask";
    private static final Logger logger = LoggerFactory.getLogger(SnapshotTask.class);
    private final ThreadSleeper sleeper = new ThreadSleeper();
    private final ICredential cred;
    private final InstanceIdentity iid;
    private final InstanceState state;
    private final StorageProxy storageProxy;
    private final Backup backup;

    private final int storageRetries = 5;

    @Inject
    public SnapshotTask(IConfiguration config, InstanceIdentity id, ICredential cred, InstanceState state,
            StorageProxy storageProxy, Backup backup) {
        super(config);
        this.cred = cred;
        this.iid = id;
        this.state = state;
        this.storageProxy = storageProxy;
        this.backup = backup;
    }

    public void execute() throws Exception {
        this.state.setFirstBackup(false);
        if (!state.isRestoring() && !state.isBootstrapping()) {
            /** Iterate five times until storage (Redis) is ready.
             *  We need storage to be ready to dumb the data,
             *  otherwise we may backup older data. Another case,
             *  is that the thread that starts Dynomite has not 
             *  started Redis yet.
             */
            int i = 0;
            for (i = 0; i < this.storageRetries; i++) {
                if (!this.state.isStorageAlive()) {
                    //sleep 2 seconds to make sure Dynomite process is up, Storage process is up.
                    sleeper.sleepQuietly(2000);
                } else {
                    this.state.setBackingup(true);
                    /** 
                     * Set the status of the backup to false every time we start a backup.
                     * This will ensure that prior to backup we recapture the status of the backup.
                     */
                    this.state.setBackUpStatus(false);

                    // the storage proxy takes a snapshot or compacts data
                    boolean snapshot = this.storageProxy.takeSnapshot();
                    File file = null;
                    if (config.isAof()) {
                        file = new File(config.getPersistenceLocation() + "/appendonly.aof");
                    } else {
                        file = new File(config.getPersistenceLocation() + "/nfredis.rdb");
                    }
                    // upload the data to S3
                    if (file.length() > 0 && snapshot == true) {
                        DateTime now = DateTime.now();
                        DateTime todayStart = now.withTimeAtStartOfDay();
                        this.state.setBackupTime(todayStart);

                        if (this.backup.upload(file, todayStart)) {
                            this.state.setBackUpStatus(true);
                            logger.info("S3 backup status: Completed!");
                        } else {
                            logger.error("S3 backup status: Failed!");
                        }
                    } else {
                        logger.warn("S3 backup: Redis AOF file length is zero - nothing to backup");
                    }
                    break;
                }
            }

            if (i == this.storageRetries) {
                logger.error("S3 backup Failed: Redis was not up after " + this.storageRetries + " retries");
            }
            this.state.setBackingup(false);
        } else {
            logger.error("S3 backup Failed: Restore is happening");
        }

    }

    @Override
    public String getName() {
        return TaskName;
    }

    /**
     * Returns a timer that enables this task to run on a scheduling basis defined by FP
     * if the BackupSchedule == week, it runs on Monday
     * if the BackupSchedule == day, it runs everyday.
     * @return TaskTimer
     */
    public static TaskTimer getTimer(IConfiguration config) {
        int hour = config.getBackupHour();
        if (config.getBackupSchedule().equals("week")) {
            return new CronTimer(DayOfWeek.MON, hour, 1, 0);
        }
        return new CronTimer(hour, 1, 0);

    }

}