package cc.blynk.server.workers; import cc.blynk.server.core.dao.FileManager; import cc.blynk.server.core.dao.UserDao; import cc.blynk.server.core.model.DashBoard; import cc.blynk.server.core.model.auth.User; import cc.blynk.server.db.DBManager; import cc.blynk.utils.JsonParser; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.io.Closeable; import java.nio.file.Path; import java.util.ArrayList; /** * Background thread that once a minute stores all user DB to disk in case profile was changed since last saving. * * The Blynk Project. * Created by Dmitriy Dumanskiy. * Created on 2/12/2015. */ public class ProfileSaverWorker implements Runnable, Closeable { private static final Logger log = LogManager.getLogger(ProfileSaverWorker.class); //1 min private final UserDao userDao; private final FileManager fileManager; private final DBManager dbManager; private long lastStart; private long backupTs; public ProfileSaverWorker(UserDao userDao, FileManager fileManager, DBManager dbManager) { this.userDao = userDao; this.fileManager = fileManager; this.dbManager = dbManager; this.lastStart = System.currentTimeMillis(); this.backupTs = 0; } private static boolean isUpdated(long lastStart, User user) { return (lastStart <= user.lastModifiedTs) || isDashUpdated(lastStart, user); } private static boolean isDashUpdated(long lastStart, User user) { for (DashBoard dashBoard : user.profile.dashBoards) { if (lastStart <= dashBoard.updatedAt) { return true; } } return false; } @Override public void run() { try { log.debug("Starting saving user db."); final long now = System.currentTimeMillis(); ArrayList<User> users = saveModified(); dbManager.saveUsers(users); //backup only for local mode if (!dbManager.isDBEnabled() && users.size() > 0) { archiveUser(now); } lastStart = now; log.debug("Saving user db finished. Modified {} users.", users.size()); } catch (Throwable t) { log.error("Error saving users.", t); } } private void archiveUser(long now) { if (now - backupTs > 86_400_000) { //it is time for backup, once per day. backupTs = now; for (User user : userDao.users.values()) { try { Path path = fileManager.generateBackupFileName(user.email, user.appName); JsonParser.writeUser(path.toFile(), user); } catch (Exception e) { //ignore } } } } private ArrayList<User> saveModified() { ArrayList<User> users = new ArrayList<>(); for (User user : userDao.getUsers().values()) { if (isUpdated(lastStart, user)) { try { fileManager.overrideUserFile(user); users.add(user); } catch (Exception e) { log.error("Error saving : {}.", user); } } } return users; } @Override public void close() { run(); } }