001/* 002 * HA-JDBC: High-Availability JDBC 003 * Copyright (c) 2004-2007 Paul Ferraro 004 * 005 * This library is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU Lesser General Public License as published by the 007 * Free Software Foundation; either version 2.1 of the License, or (at your 008 * option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, but WITHOUT 011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License 013 * for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public License 016 * along with this library; if not, write to the Free Software Foundation, 017 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 018 * 019 * Contact: ferraro@users.sourceforge.net 020 */ 021package net.sf.hajdbc.local; 022 023import java.util.ArrayList; 024import java.util.Arrays; 025import java.util.Collections; 026import java.util.List; 027import java.util.Set; 028import java.util.TreeSet; 029import java.util.prefs.BackingStoreException; 030import java.util.prefs.Preferences; 031 032import net.sf.hajdbc.Database; 033import net.sf.hajdbc.DatabaseCluster; 034import net.sf.hajdbc.DatabaseEvent; 035import net.sf.hajdbc.Messages; 036import net.sf.hajdbc.StateManager; 037import net.sf.hajdbc.util.Strings; 038 039import org.slf4j.Logger; 040import org.slf4j.LoggerFactory; 041 042/** 043 * @author Paul Ferraro 044 */ 045public class LocalStateManager implements StateManager 046{ 047 private static Preferences preferences = Preferences.userNodeForPackage(LocalStateManager.class); 048 private static Logger logger = LoggerFactory.getLogger(LocalStateManager.class); 049 050 private DatabaseCluster<?> databaseCluster; 051 052 /** 053 * @param databaseCluster 054 */ 055 public LocalStateManager(DatabaseCluster<?> databaseCluster) 056 { 057 this.databaseCluster = databaseCluster; 058 } 059 060 /** 061 * @see net.sf.hajdbc.StateManager#getInitialState() 062 */ 063 @Override 064 public Set<String> getInitialState() 065 { 066 String state = preferences.get(this.statePreferenceKey(), null); 067 068 if (state == null) 069 { 070 logger.info(Messages.getMessage(Messages.INITIAL_CLUSTER_STATE_NONE)); 071 072 return null; 073 } 074 075 Set<String> databaseSet = Collections.emptySet(); 076 077 if (state.length() > 0) 078 { 079 databaseSet = new TreeSet<String>(Arrays.asList(state.split(Strings.COMMA))); 080 } 081 082 logger.info(Messages.getMessage(Messages.INITIAL_CLUSTER_STATE_LOCAL, databaseSet)); 083 084 return databaseSet; 085 } 086 087 /** 088 * @see net.sf.hajdbc.Lifecycle#start() 089 */ 090 @Override 091 public void start() throws Exception 092 { 093 preferences.sync(); 094 } 095 096 /** 097 * @see net.sf.hajdbc.Lifecycle#stop() 098 */ 099 @Override 100 public void stop() 101 { 102 // Nothing to do 103 } 104 105 private String statePreferenceKey() 106 { 107 return this.databaseCluster.getId(); 108 } 109 110 /** 111 * @see net.sf.hajdbc.StateManager#isMembershipEmpty() 112 */ 113 @Override 114 public boolean isMembershipEmpty() 115 { 116 return false; 117 } 118 119 /** 120 * @see net.sf.hajdbc.DatabaseActivationListener#activated(net.sf.hajdbc.DatabaseEvent) 121 */ 122 @Override 123 public void activated(DatabaseEvent event) 124 { 125 this.storeState(); 126 } 127 128 /** 129 * @see net.sf.hajdbc.DatabaseDeactivationListener#deactivated(net.sf.hajdbc.DatabaseEvent) 130 */ 131 @Override 132 public void deactivated(DatabaseEvent event) 133 { 134 this.storeState(); 135 } 136 137 private void storeState() 138 { 139 List<String> databaseList = new ArrayList<String>(); 140 141 for (Database<?> database: this.databaseCluster.getBalancer().all()) 142 { 143 databaseList.add(database.getId()); 144 } 145 146 preferences.put(this.statePreferenceKey(), Strings.join(databaseList, Strings.COMMA)); 147 148 try 149 { 150 preferences.flush(); 151 } 152 catch (BackingStoreException e) 153 { 154 throw new RuntimeException(Messages.getMessage(Messages.CLUSTER_STATE_STORE_FAILED, this.databaseCluster), e); 155 } 156 } 157}