1 21 22 package org.continuent.sequoia.controller.backup; 23 24 import java.io.BufferedInputStream ; 25 import java.io.BufferedOutputStream ; 26 import java.io.File ; 27 import java.io.FileInputStream ; 28 import java.io.FileOutputStream ; 29 import java.io.IOException ; 30 import java.io.InputStream ; 31 import java.io.ObjectInputStream ; 32 import java.io.ObjectOutputStream ; 33 import java.io.OutputStream ; 34 import java.net.InetAddress ; 35 import java.net.InetSocketAddress ; 36 import java.net.ServerSocket ; 37 import java.net.Socket ; 38 import java.util.HashMap ; 39 import java.util.Iterator ; 40 import java.util.Set ; 41 42 import org.continuent.sequoia.common.exceptions.BackupException; 43 import org.continuent.sequoia.common.log.Trace; 44 import org.continuent.sequoia.common.xml.DatabasesXmlTags; 45 import org.continuent.sequoia.common.xml.XmlComponent; 46 47 54 public class BackupManager implements XmlComponent 55 { 56 static Trace logger = Trace.getLogger(BackupManager.class.getName()); 57 58 61 private HashMap backupers; 62 63 66 public BackupManager() 67 { 68 backupers = new HashMap (); 69 } 70 71 78 public synchronized Backuper getBackuperByName(String name) 79 { 80 return (Backuper) backupers.get(name); 81 } 82 83 90 public synchronized String [] getBackuperNames() 91 { 92 Set backuperNames = backupers.keySet(); 93 return (String []) backuperNames.toArray(new String [backuperNames.size()]); 94 } 95 96 103 public synchronized Backuper getBackuperByFormat(String format) 104 { 105 if (format == null) 106 return null; 107 for (Iterator iter = backupers.values().iterator(); iter.hasNext();) 108 { 109 Backuper b = (Backuper) iter.next(); 110 if (format.equals(b.getDumpFormat())) 111 return b; 112 } 113 return null; 114 } 115 116 124 public synchronized void registerBackuper(String name, Backuper backuper) 125 throws BackupException 126 { 127 if (backupers.containsKey(name)) 129 throw new BackupException( 130 "A backuper has already been registered with name " + name); 131 if (backuper == null) 132 throw new BackupException( 133 "Trying to register a null backuper under name " + name); 134 String dumpFormat = backuper.getDumpFormat(); 135 if (dumpFormat == null) 136 throw new BackupException("Invalid null dump format for backuper " + name); 137 138 for (Iterator iter = backupers.values().iterator(); iter.hasNext();) 140 { 141 Backuper b = (Backuper) iter.next(); 142 if (b.getDumpFormat().equals(dumpFormat)) 143 throw new BackupException("Backuper " + b.getClass() 144 + " already handles " + dumpFormat + " dump format"); 145 } 146 147 if (logger.isInfoEnabled()) 148 logger.info("Registering backuper " + name + " to handle format " 149 + dumpFormat); 150 151 backupers.put(name, backuper); 152 } 153 154 161 public synchronized boolean unregisterBackuper(String name) 162 { 163 Object backuper = backupers.remove(name); 164 165 if (logger.isInfoEnabled() && (backuper != null)) 166 logger.info("Unregistering backuper " + name + " that handled format " 167 + ((Backuper) backuper).getDumpFormat()); 168 169 return backuper != null; 170 } 171 172 175 public synchronized String getXml() 176 { 177 StringBuffer sb = new StringBuffer ("<" + DatabasesXmlTags.ELT_Backup + "> "); 178 for (Iterator iter = backupers.keySet().iterator(); iter.hasNext();) 179 { 180 String backuperName = (String ) iter.next(); 181 Backuper b = (Backuper) backupers.get(backuperName); 182 sb.append("<" + DatabasesXmlTags.ELT_Backuper + " " 183 + DatabasesXmlTags.ATT_backuperName + "=\"" + backuperName + "\" " 184 + DatabasesXmlTags.ATT_className + "=\"" + b.getClass().getName() 185 + "\" " + DatabasesXmlTags.ATT_options + "=\"" + b.getOptions() 186 + "\" />"); 187 } 188 sb.append("</" + DatabasesXmlTags.ELT_Backup + ">"); 189 return sb.toString(); 190 } 191 192 206 public static void fetchDumpFile(DumpTransferInfo info, String path, 207 String dumpName) throws IOException , BackupException 208 { 209 logger.info("Dump fetch starting from " + info.getBackuperServerAddress()); 213 214 Socket soc = new Socket (); 215 216 soc.connect(info.getBackuperServerAddress()); 217 218 ObjectOutputStream oos = new ObjectOutputStream (soc.getOutputStream()); 219 220 oos.writeLong(info.getSessionKey()); 221 oos.writeObject(path); 222 oos.writeObject(dumpName); 223 224 InputStream is = new BufferedInputStream (soc.getInputStream()); 226 int response = is.read(); 227 if (response != 0xEC) throw new BackupException("bad response from dump server"); 229 230 logger.info("Dump fetch authentication ok. Fetching " + path); 234 235 File thePath = new File (path); 236 if (!thePath.exists()) 237 thePath.mkdirs(); 238 239 File theFile = new File (path + File.separator + dumpName); 240 theFile.createNewFile(); 241 242 OutputStream os = new BufferedOutputStream (new FileOutputStream (theFile)); 243 int c = is.read(); 244 while (c != -1) 245 { 246 os.write(c); 247 c = is.read(); 248 } 249 os.flush(); 250 os.close(); 251 252 logger.info("Dump fetch done."); 253 } 254 255 263 public static DumpTransferInfo setupDumpFileServer(String dumpServerIpAddress) 264 throws IOException  265 { 266 ServerSocket soc = new ServerSocket (); 267 soc.bind(null); 268 269 InetSocketAddress dumpServerAddress; 270 if (dumpServerIpAddress != null) 271 { 272 logger.info("Using provided dump-server address: " + dumpServerIpAddress); 273 dumpServerAddress = new InetSocketAddress (dumpServerIpAddress, soc 274 .getLocalPort()); 275 } 276 else 277 { 278 logger.info("Using InetAddress.getLocalHost() as dump-server address: " 279 + InetAddress.getLocalHost()); 280 dumpServerAddress = new InetSocketAddress (InetAddress.getLocalHost(), soc 281 .getLocalPort()); 282 } 283 284 if (dumpServerAddress.getAddress() == null) 285 throw new IOException ( 286 "Cannot resolve provided IP address for dump server (" 287 + dumpServerAddress + ")"); 288 else if (dumpServerAddress.getAddress().isLoopbackAddress()) 289 throw new IOException ( 290 "NOT setting-up a dump server on a loopback address.\n" 291 + "Please update your network configuration " 292 + "or specify option dumpServer in vdb.xml <Backuper ... option=/>"); 293 294 long sessionKey = soc.hashCode(); 295 new DumpTransferServerThread(soc, sessionKey).start(); 296 297 return new DumpTransferInfo(dumpServerAddress, sessionKey); 304 } 305 306 313 public static DumpTransferInfo setupDumpFileServer() throws IOException  314 { 315 return setupDumpFileServer(null); 316 } 317 318 static class DumpTransferServerThread extends Thread  319 { 320 private ServerSocket serverSocket; 321 private long sessionKey; 322 323 public void run() 324 { 325 try 326 { 327 logger.info("Dump server started @ " 328 + serverSocket.getLocalSocketAddress()); 329 Socket soc = serverSocket.accept(); 333 334 logger.info("Client connected to dump server from " 335 + soc.getRemoteSocketAddress()); 336 337 ObjectInputStream ois = new ObjectInputStream (soc.getInputStream()); 338 339 long key = ois.readLong(); 343 344 if (key != this.sessionKey) 345 { 346 logger.error("Bad session key from client: " 347 + soc.getRemoteSocketAddress()); 348 soc.close(); 349 return; } 351 352 String path = (String ) ois.readObject(); 353 String dumpName = (String ) ois.readObject(); 354 355 File theFile = new File (path + File.separator + dumpName); 356 357 if (!theFile.exists()) 358 { 359 logger.error("Requested dump does not exist: " + theFile.getPath()); 360 soc.close(); 361 return; 362 } 363 364 InputStream is = new BufferedInputStream (new FileInputStream (theFile)); 365 OutputStream os = new BufferedOutputStream (soc.getOutputStream()); 366 367 os.write(0xEC); 370 371 int c = is.read(); 375 while (c != -1) 376 { 377 os.write(c); 378 c = is.read(); 379 } 380 os.flush(); 381 os.close(); 382 383 logger.info("Dump server terminated."); 384 } 385 catch (Exception e) 386 { 387 logger.error(e); 388 } 389 } 390 391 DumpTransferServerThread(ServerSocket serverSocket, long sessionKey) 392 { 393 setName("DumpTransfer server thread"); 394 this.serverSocket = serverSocket; 395 this.sessionKey = sessionKey; 396 } 397 } 398 399 } | Popular Tags |