0001: /**
0002: * LibreSource
0003: * Copyright (C) 2004-2008 Artenum SARL / INRIA
0004: * http://www.libresource.org - contact@artenum.com
0005: *
0006: * This file is part of the LibreSource software,
0007: * which can be used and distributed under license conditions.
0008: * The license conditions are provided in the LICENSE.TXT file
0009: * at the root path of the packaging that enclose this file.
0010: * More information can be found at
0011: * - http://dev.libresource.org/home/license
0012: *
0013: * Initial authors :
0014: *
0015: * Guillaume Bort / INRIA
0016: * Francois Charoy / Universite Nancy 2
0017: * Julien Forest / Artenum
0018: * Claude Godart / Universite Henry Poincare
0019: * Florent Jouille / INRIA
0020: * Sebastien Jourdain / INRIA / Artenum
0021: * Yves Lerumeur / Artenum
0022: * Pascal Molli / Universite Henry Poincare
0023: * Gerald Oster / INRIA
0024: * Mariarosa Penzi / Artenum
0025: * Gerard Sookahet / Artenum
0026: * Raphael Tani / INRIA
0027: *
0028: * Contributors :
0029: *
0030: * Stephane Bagnier / Artenum
0031: * Amadou Dia / Artenum-IUP Blois
0032: * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0033: */package org.libresource.so6.core;
0034:
0035: import org.libresource.so6.core.client.ClientI;
0036: import org.libresource.so6.core.command.Command;
0037: import org.libresource.so6.core.command.fs.AddBinaryFile;
0038: import org.libresource.so6.core.command.fs.AddDir;
0039: import org.libresource.so6.core.command.fs.Remove;
0040: import org.libresource.so6.core.command.fs.UpdateBinaryFile;
0041: import org.libresource.so6.core.command.text.AddTxtFile;
0042: import org.libresource.so6.core.command.xml.AddXmlFile;
0043: import org.libresource.so6.core.compress.CompressUtil;
0044: import org.libresource.so6.core.engine.DBType;
0045: import org.libresource.so6.core.engine.FileParser;
0046: import org.libresource.so6.core.engine.FilterIgnoreFile;
0047: import org.libresource.so6.core.engine.OpVector;
0048: import org.libresource.so6.core.engine.OpVectorFsImpl;
0049: import org.libresource.so6.core.engine.PatchFile;
0050: import org.libresource.so6.core.engine.PatchRepository;
0051: import org.libresource.so6.core.engine.RefCopy;
0052: import org.libresource.so6.core.engine.util.Base64;
0053: import org.libresource.so6.core.engine.util.FileUtils;
0054: import org.libresource.so6.core.engine.util.ObjectCloner;
0055: import org.libresource.so6.core.report.CVSReportMaker;
0056: import org.libresource.so6.core.tf.TransformationFunctions;
0057:
0058: import java.io.BufferedOutputStream;
0059: import java.io.File;
0060: import java.io.FileInputStream;
0061: import java.io.FileOutputStream;
0062: import java.io.FileWriter;
0063: import java.io.IOException;
0064: import java.io.OutputStreamWriter;
0065:
0066: import java.lang.reflect.Constructor;
0067:
0068: import java.util.Iterator;
0069: import java.util.ListIterator;
0070: import java.util.Properties;
0071: import java.util.Vector;
0072: import java.util.logging.Logger;
0073:
0074: /*
0075: class Workspace:
0076: Responsability:
0077: manage the persistence of workspace data
0078: Collaboration:
0079: Log
0080: */
0081:
0082: /**
0083: * The <code>WsConnection</code> class represents a connection to a So6 Queue.
0084: * This class is used to manage the synchronisation process.
0085: *
0086: * @author Smack
0087: * @version 1.0, 26/05/04
0088: * @see org.libresource.so6.core.Workspace
0089: * @see org.libresource.so6.core.client.ClientI
0090: * @since JDK1.4
0091: */
0092: public class WsConnection implements java.io.Serializable {
0093: /** Name of the file where the WsConnection meta data will be stored */
0094: public static final String SO6_WSC_FILE = "so6.properties";
0095:
0096: /** Name of last patch file sent during the commit */
0097: public static final String SO6_LAST_COMMIT_PATCH_FILE = "lastPatch.commit";
0098:
0099: /**
0100: * Property used in the SO6_WSC_FILE property file to represente the
0101: * worskpace base path
0102: */
0103: public static final String PATH = "so6.path";
0104:
0105: /**
0106: * Property used in the SO6_WSC_FILE property file to represente the data
0107: * path of that connection
0108: */
0109: public static final String DATAPATH = "so6.connection.path";
0110:
0111: /**
0112: * Property used in the SO6_WSC_FILE property file to represente the name of
0113: * the concrete class of the ClientI interface that need to be used for that
0114: * connection
0115: */
0116: public static final String SYNC_CLIENT_NAME = "so6.clienti.name";
0117:
0118: /**
0119: * Property used in the SO6_WSC_FILE property file to represente the name of
0120: * that connection in order to know who did what?
0121: */
0122: public static final String WS_NAME = "so6.wsc.name";
0123:
0124: /**
0125: * Property used in the SO6_WSC_FILE propertie file is use to set the XML
0126: * merge (true/false)
0127: */
0128: public static final String XML_AUTO_DETECTION = "so6.xml.autodetect";
0129:
0130: /**
0131: * Property used in the SO6_WSC_FILE property file to represente the current
0132: * corrupted state
0133: */
0134: public static final String CORRUPTION_STATE = "so6.corruption.state";
0135:
0136: /**
0137: * Property used in the SO6_WSC_FILE property file to represente the last
0138: * integrated ticket before any corruption
0139: */
0140: public static final String LAST_TICKET_BEFORE_CORRUPTION = "so6.last.ticket.before.corruption";
0141:
0142: /**
0143: * Property used in the SO6_WSC_FILE property file to represente the list of
0144: * the binary extension
0145: */
0146: public static final String LAST_BIN_EXT = "so6.binary.ext";
0147:
0148: /** Constant for the corruption property : WsConnection not corrupted */
0149: public static final int NO_CORRUPTION = -1;
0150:
0151: /**
0152: * Constant for the corruption property : WsConnection corrupted while
0153: * patching local copy
0154: */
0155: public static final int UPDATE_CORRUPTION_PATCH_LOCAL_COPY = 1;
0156:
0157: /**
0158: * Constant for the corruption property : WsConnection corrupted while
0159: * patching the local reference copy after an update
0160: */
0161: public static final int UPDATE_CORRUPTION_PATCH_REF_COPY = 2;
0162:
0163: /**
0164: * Constant for the corruption property : WsConnection corrupted while
0165: * saving patch in the applied patch directory after an update
0166: */
0167: public static final int UPDATE_CORRUPTION_SAVE_PATCH = 3;
0168:
0169: /**
0170: * Constant for the corruption property : WsConnection corrupted while
0171: * removing the applied patch in the received directory after an update
0172: */
0173: public static final int UPDATE_CORRUPTION_REMOVE_PATCH = 4;
0174:
0175: /**
0176: * Constant for the corruption property : WsConnection corrupted while
0177: * patching the local reference copy after a commit
0178: */
0179: public static final int COMMIT_CORRUPTION_PATCH_REF_COPY = 11;
0180:
0181: /**
0182: * Constant for the corruption property : WsConnection corrupted while
0183: * saving patch in the applied patch directory after a commit
0184: */
0185: public static final int COMMIT_CORRUPTION_SAVE_PATCH = 12;
0186:
0187: /**
0188: * Constant for the corruption property : WsConnection corrupted while
0189: * updating the received ticket
0190: */
0191: public static final int COMMIT_CORRUPTION_UPDATE_RECEIVED_TICKET = 13;
0192:
0193: /**
0194: * Constant for the corruption property: WsConnection corrupted while trying
0195: * to replace the local dbType by the ref dbType
0196: */
0197: public static final int COMMIT_CORRUPTION_UPDATE_LOCAL_DBTYPE = 14;
0198: private ClientI clienti;
0199: private TransformationFunctions de;
0200: private PatchRepository appliedPatch;
0201: private PatchRepository receivedPatch;
0202: private DBType dbtype;
0203: private RefCopy refcopy;
0204: private Vector patchFilter;
0205:
0206: //
0207: private StringBuffer report;
0208:
0209: //
0210: private OpVector mergedOp;
0211: private long mergedTime;
0212: private String wscPath; // path of property file...
0213: private Properties prop = new Properties();
0214: private boolean loaded = false;
0215: private boolean needToCheckLocalOp = true;
0216:
0217: // For simulation
0218: private boolean simulationMode = false;
0219: private String simulationOutputDir = null;
0220:
0221: /**
0222: * Load an EXISTING <code>WsConnection</code> object in order to access to
0223: * the synchronisation process.
0224: *
0225: * @param wscPath
0226: * <code>SO6_WSC_FILE<code> file path
0227: */
0228: public WsConnection(String wscPath) throws IOException {
0229: this .wscPath = wscPath;
0230: load(wscPath);
0231: FileUtils.createDirIfNotExist(getDataPath());
0232: FileUtils.createDirIfNotExist(getDBTypePath());
0233: FileUtils.createDirIfNotExist(getRefCopyPath());
0234: this .de = new TransformationFunctions(this );
0235: this .refcopy = new RefCopy(this );
0236: this .dbtype = new DBType(this .getDBTypePath() + File.separator
0237: + "local.dbtype", getLastBinExt());
0238: this .appliedPatch = new PatchRepository(this , "APPLIED");
0239: this .receivedPatch = new PatchRepository(this , "RECEIVED");
0240: }
0241:
0242: /**
0243: * Return the workspace connection
0244: *
0245: * @return The workspace of that connection
0246: */
0247: public Workspace getWorkspace() throws Exception {
0248: return new Workspace(getPath());
0249: }
0250:
0251: /**
0252: * The logger is used to monitor what it's going on an update or commit
0253: * operation. The logger follow the XML syntaxe in order to represent the
0254: * current state of the current Job.
0255: * <p>
0256: * To get more information look at the
0257: * org.libresource.so6.engine.log.monitoring.XMLLogHandler source code
0258: *
0259: * @return The monitoring XML logger
0260: */
0261: /**
0262: * Return the base path where the DbType are stored (local.dbtype /
0263: * refcopy.dbtype)
0264: *
0265: * @return path of the directory
0266: */
0267: public String getDBTypePath() {
0268: return getDataPath() + File.separator + "DBTYPE";
0269: }
0270:
0271: /**
0272: * Return the base path where the local command are temporary stored when
0273: * they are computed from the diff beetwen the refcopy and the local copy.
0274: *
0275: * @return path of the directory
0276: */
0277: public String getLocalCmdPath() {
0278: return getDataPath() + File.separator + "LOCALS";
0279: }
0280:
0281: /**
0282: * Return the base path where the attachement of the local command are
0283: * temporary stored.
0284: *
0285: * @return path of the directory
0286: */
0287: public String getAttachFilePath() {
0288: return getDataPath() + File.separator + "ATTACH";
0289: }
0290:
0291: /**
0292: * Return the base path where the local reference copy is stored.
0293: *
0294: * @return path of the directory
0295: */
0296: public String getRefCopyPath() {
0297: return getDataPath() + File.separator + "REFCOPY";
0298: }
0299:
0300: /**
0301: * Return the base path where the merged commands are stored.
0302: *
0303: * @return path of the directory
0304: */
0305: public String getMergedOpBasePath() {
0306: return getDataPath() + File.separator + "MERGED_OP";
0307: }
0308:
0309: /**
0310: * Return the current path of the merged commands.
0311: *
0312: * @return path of the directory
0313: */
0314: public String getMergedOpPath() {
0315: return getMergedOpBasePath() + File.separator + "op_"
0316: + mergedTime;
0317: }
0318:
0319: /**
0320: * The current path of the attachement of the merged commands.
0321: *
0322: * @return path of the directory
0323: */
0324: public String getMergedAttachPath() {
0325: return getMergedOpBasePath() + File.separator + "attach_"
0326: + mergedTime;
0327: }
0328:
0329: /**
0330: * The temp working directory
0331: *
0332: * @return path of the directory
0333: */
0334: public String getTempDir() {
0335: return System.getProperty("java.io.tmpdir") + File.separator
0336: + "so6_compress_" + System.currentTimeMillis();
0337: }
0338:
0339: /**
0340: * Load meta data from the filesystem. (Need to be used when concurrent
0341: * update on the file systeme.)
0342: *
0343: * @param path
0344: * The path of the workspace connection property file
0345: *
0346: * @throws Exception
0347: */
0348: public void load(String path) throws IOException {
0349: File propfile = new File(path);
0350:
0351: if (propfile.exists() && (!propfile.isDirectory())) {
0352: try {
0353: FileInputStream fis = new FileInputStream(propfile);
0354: prop.load(fis);
0355: fis.close();
0356: } catch (Exception e) {
0357: throw new IOException("Cannot read property file:"
0358: + path);
0359: }
0360: } else {
0361: throw new IOException("Cannot find property file: " + path
0362: + "\n The workspace might not be on this computer.");
0363: }
0364:
0365: loaded = true;
0366: }
0367:
0368: /**
0369: * Save the data in the property file
0370: */
0371: public void save() {
0372: if (wscPath == null) { // true for testing...
0373:
0374: return;
0375: }
0376:
0377: try {
0378: // remove password
0379: Properties propToSave = (Properties) prop.clone();
0380:
0381: //propToSave.remove(ClientI.SO6_PASSWORD);
0382: FileOutputStream fos = new FileOutputStream(wscPath);
0383: propToSave.store(fos, "do not edit");
0384: fos.close();
0385: } catch (Exception e) {
0386: throw new RuntimeException("Cannot save property file"
0387: + wscPath);
0388: }
0389: }
0390:
0391: /**
0392: * Automaticaly instantiate the class specified for property
0393: * <code>SYNC_CLIENT_NAME<code>
0394: * with the default constructor that take the <code>SO6_WSC_FILE<code> property file as parameter.
0395: *
0396: * @return The ClientI of that connection
0397: */
0398: public ClientI getClient() throws Exception {
0399: if (clienti == null) {
0400: Constructor construct = Class.forName(
0401: prop.getProperty(SYNC_CLIENT_NAME)).getConstructor(
0402: new Class[] { Properties.class });
0403: setClient((ClientI) construct
0404: .newInstance(new Object[] { prop }));
0405: }
0406:
0407: return clienti;
0408: }
0409:
0410: /**
0411: * Set a property in the <code>SO6_WSC_FILE<code> property file
0412: * @param key The key of the property
0413: * @param value The value associated to that key
0414: */
0415: public void setProperty(String key, String value) {
0416: prop.setProperty(key, value);
0417: save();
0418: }
0419:
0420: /**
0421: * Return the property value for the key passed in parameter.
0422: *
0423: * @param propName
0424: * key name
0425: * @return The property value for the key passed in parameter.
0426: */
0427: public String getProperty(String propName) {
0428: return prop.getProperty(propName);
0429: }
0430:
0431: private String getSynchronizeClientName() {
0432: return getProperty(WsConnection.SYNC_CLIENT_NAME);
0433: }
0434:
0435: /**
0436: * Return the current connection ticket. The ticket is equivalent to a
0437: * timestamp in the shared data history.
0438: *
0439: * @return The current connection ticket.
0440: *
0441: */
0442: public long getNs() {
0443: return appliedPatch.getLastTicket();
0444: }
0445:
0446: /**
0447: * Return the name of that connection
0448: *
0449: * @return The name of that connection
0450: */
0451: public String getWsName() {
0452: return getProperty(WsConnection.WS_NAME);
0453: }
0454:
0455: /**
0456: * Return the base path of the workspace
0457: *
0458: * @return The base path of the workspace
0459: */
0460: public String getPath() {
0461: return getProperty(WsConnection.PATH);
0462: }
0463:
0464: /**
0465: * The data path is the place where the WsConnection store all the important
0466: * data to manage the synchronisation process.
0467: *
0468: * @return The base path of the WsConnection data path
0469: */
0470: public String getDataPath() {
0471: return getProperty(WsConnection.DATAPATH);
0472: }
0473:
0474: /**
0475: * Reload the binary extention definition from the ClientI interface.
0476: */
0477: public void updateBinExt() throws Exception {
0478: String binExt = getClient().getBinExt();
0479: dbtype.updateBinExt(binExt);
0480: refcopy.getDBType().updateBinExt(binExt);
0481: setLastBinExt(binExt);
0482: }
0483:
0484: /**
0485: * Set the ClientI for that connection and update the binary extention. This
0486: * methode won't update the property file. This is just for the current run
0487: * time.
0488: *
0489: * @param clientI
0490: */
0491: public void setClient(ClientI clientI) throws Exception {
0492: this .clienti = clientI;
0493: updateBinExt();
0494: }
0495:
0496: /**
0497: * Return the refCopy object that represent the reference copy of the local
0498: * workspace
0499: *
0500: * @return The refCopy object
0501: */
0502: public RefCopy getRefCopy() {
0503: return refcopy;
0504: }
0505:
0506: /**
0507: * Automaticaly update and commit on the current connection.
0508: *
0509: * @param comment
0510: * The comment of the commit.
0511: *
0512: * @throws Exception
0513: */
0514: public void updateAndCommit(String comment) throws Exception {
0515: update();
0516: commit(comment);
0517: }
0518:
0519: /**
0520: * Automaticaly update and commit on the current connection. Without any
0521: * comment.
0522: *
0523: * @throws Exception
0524: */
0525: public void updateAndCommit() throws Exception {
0526: updateAndCommit("No comment...");
0527: }
0528:
0529: /**
0530: * This methode is used to simulate actions. It means that the local data
0531: * won't be modified, but a report will be made in the specified directory
0532: * in order to explain what would happen if it wasn't a simulation.
0533: *
0534: * @param simulation
0535: * To set or unset the simulation mode
0536: * @param outputDir
0537: * The output directory where will be stored the report.
0538: */
0539: public void setSimulationMode(boolean simulation, String outputDir) {
0540: this .simulationMode = simulation;
0541: this .simulationOutputDir = outputDir;
0542: }
0543:
0544: /**
0545: * Commit the local changes with the specified comment.
0546: *
0547: * @param comment
0548: * The comment for that commit
0549: *
0550: * @throws Exception
0551: */
0552: public void commit(String comment) throws Exception {
0553: // check corruption
0554: if (isCorrupted()) {
0555: throw new WorkspaceCorruptedException(
0556: "The local workspace is corrupted");
0557: }
0558:
0559: report = new StringBuffer();
0560: StateMonitoring.getInstance().setXMLMonitoringStartAction(
0561: "COMMIT");
0562: StateMonitoring.getInstance().setXMLMonitoringStartSubCall(4,
0563: null);
0564: StateMonitoring.getInstance().setXMLMonitoringComment(
0565: "Start the commit process");
0566:
0567: //
0568: long ticket = this .getNs() + 1;
0569: cleanLocalOp();
0570:
0571: File tmp = new File(getLocalCmdPath());
0572: tmp.mkdirs();
0573:
0574: //
0575: StateMonitoring.getInstance().setXMLMonitoringStartSubCall(1,
0576: "Compute local operations");
0577:
0578: //
0579: OpVectorFsImpl opv = new OpVectorFsImpl(tmp.getPath());
0580: FileParser fp = new FileParser(this );
0581: fp.compute(opv);
0582: StateMonitoring.getInstance().setXMLMonitoringEndSubCall();
0583:
0584: if (opv.size() == 0) {
0585: StateMonitoring.getInstance().setXMLMonitoringComment(
0586: false, "No local operation found");
0587: StateMonitoring.getInstance().setXMLMonitoringEndSubCall();
0588: StateMonitoring.getInstance().setXMLMonitoringComment(true,
0589: "Commit process finished");
0590: StateMonitoring.getInstance().setXMLMonitoringEndAction(
0591: "COMMIT");
0592:
0593: return; // Nothing to commit
0594: }
0595:
0596: // check partial for commit
0597: long lastticket = -1;
0598:
0599: if (patchFilter == null) {
0600: lastticket = (ticket + opv.size()) - 1;
0601: } else {
0602: // check nb command that need to be sent
0603: lastticket = (ticket + computeNbCommandToSend(opv)) - 1;
0604:
0605: // System.out.println("Op to send with filter: " +
0606: // computeNbCommandToSend(opv) + "/" + opv.size());
0607: }
0608:
0609: StateMonitoring.getInstance().setXMLMonitoringStartSubCall(1,
0610: "");
0611: StateMonitoring.getInstance().setXMLMonitoringComment(true,
0612: "Building patch file");
0613: StateMonitoring.getInstance().setXMLMonitoringComment(false,
0614: "Inserting local command");
0615:
0616: //
0617: File f = new File(getDataPath(), SO6_LAST_COMMIT_PATCH_FILE);
0618: OutputStreamWriter osw = new OutputStreamWriter(
0619: new BufferedOutputStream(new FileOutputStream(f
0620: .getPath())), "UTF-8");
0621: PatchFile.makePatch(opv, osw, patchFilter, ticket, lastticket,
0622: getWsName(), comment);
0623: osw.close();
0624:
0625: //
0626: StateMonitoring.getInstance().setXMLMonitoringEndSubCall();
0627: StateMonitoring.getInstance().setXMLMonitoringStartSubCall(1,
0628: "");
0629: StateMonitoring.getInstance().setXMLMonitoringComment(true,
0630: "Connecting to the server");
0631:
0632: CVSReportMaker reportMaker = new CVSReportMaker(
0633: getLocalCmdPath());
0634: reportMaker.buildIndexTable();
0635: report.append(reportMaker.getReport());
0636:
0637: if (simulationMode) {
0638: FileUtils.copy(f.getPath(), simulationOutputDir
0639: + File.separator + "commit-"
0640: + System.currentTimeMillis() + ".xml");
0641: StateMonitoring.getInstance().setXMLMonitoringEndSubCall();
0642: StateMonitoring.getInstance().setXMLMonitoringStartSubCall(
0643: 1, "");
0644: StateMonitoring.getInstance().setXMLMonitoringComment(true,
0645: "Patch local reference");
0646: StateMonitoring.getInstance().setXMLMonitoringEndSubCall();
0647: StateMonitoring.getInstance().setXMLMonitoringEndSubCall();
0648: StateMonitoring.getInstance().setXMLMonitoringComment(
0649: false, "Finished");
0650: StateMonitoring.getInstance().setXMLMonitoringComment(true,
0651: "Commit process finished (simulation mode)");
0652: StateMonitoring.getInstance().setXMLMonitoringEndAction(
0653: "COMMIT");
0654: } else {
0655: getClient().sendPatch(getNs() + 1, lastticket, f.getPath(),
0656: true);
0657: StateMonitoring.getInstance().setXMLMonitoringEndSubCall();
0658: StateMonitoring.getInstance().setXMLMonitoringStartSubCall(
0659: 1, "");
0660: StateMonitoring.getInstance().setXMLMonitoringComment(true,
0661: "Patch local reference");
0662: setCorrupted(COMMIT_CORRUPTION_PATCH_REF_COPY);
0663: StateMonitoring.getInstance()
0664: .setXMLMonitoringStartCriticalPart();
0665: refcopy.patch(f.getPath());
0666: setCorrupted(COMMIT_CORRUPTION_SAVE_PATCH);
0667: StateMonitoring.getInstance()
0668: .setXMLMonitoringStartCriticalPart();
0669: appliedPatch.add(f.getPath());
0670: setCorrupted(COMMIT_CORRUPTION_UPDATE_RECEIVED_TICKET);
0671: StateMonitoring.getInstance()
0672: .setXMLMonitoringStartCriticalPart();
0673: receivedPatch.setLastTicket(getNs());
0674:
0675: // update local db type
0676: setCorrupted(COMMIT_CORRUPTION_UPDATE_LOCAL_DBTYPE);
0677: StateMonitoring.getInstance()
0678: .setXMLMonitoringStartCriticalPart();
0679: getDBType().updateFromDBType(refcopy.getDBType());
0680: setCorrupted(NO_CORRUPTION);
0681: StateMonitoring.getInstance().setXMLMonitoringEndSubCall();
0682: StateMonitoring.getInstance().setXMLMonitoringEndSubCall();
0683: StateMonitoring.getInstance().setXMLMonitoringComment(
0684: false, "Finished");
0685: StateMonitoring.getInstance().setXMLMonitoringComment(true,
0686: "Commit process finished");
0687: StateMonitoring.getInstance().setXMLMonitoringEndAction(
0688: "COMMIT");
0689: }
0690: }
0691:
0692: private void update(String patchfile) throws Exception {
0693: FileParser fp = new FileParser(this );
0694: cleanLocalOp();
0695:
0696: File localOpDir = new File(getLocalCmdPath());
0697: File mergedOpDir = new File(getMergedOpPath());
0698: StateMonitoring.getInstance().setXMLMonitoringStartSubCall(3,
0699: "");
0700: StateMonitoring.getInstance().setXMLMonitoringStartSubCall(1,
0701: "");
0702: StateMonitoring.getInstance().setXMLMonitoringComment(true,
0703: "Check local operartions");
0704:
0705: OpVector locals = new OpVectorFsImpl(localOpDir.getPath());
0706:
0707: if (needToCheckLocalOp) {
0708: fp.compute(locals);
0709: }
0710:
0711: if (locals.size() == 0) {
0712: needToCheckLocalOp = false;
0713: }
0714:
0715: StateMonitoring.getInstance().setXMLMonitoringEndSubCall();
0716: StateMonitoring.getInstance().setXMLMonitoringStartSubCall(1,
0717: "");
0718: StateMonitoring.getInstance().setXMLMonitoringComment(true,
0719: "Patch local path");
0720: mergedOp = new OpVectorFsImpl(mergedOpDir.getPath());
0721: this .merge(patchfile, locals);
0722: StateMonitoring.getInstance().setXMLMonitoringEndSubCall();
0723: StateMonitoring.getInstance().setXMLMonitoringStartSubCall(1,
0724: "");
0725: StateMonitoring.getInstance().setXMLMonitoringComment(true,
0726: "Patch ref copy");
0727:
0728: if (!simulationMode) {
0729: File lastPatch = new File(getDataPath() + File.separator
0730: + SO6_LAST_COMMIT_PATCH_FILE);
0731:
0732: if (!lastPatch.exists()
0733: || !FileUtils.compareBinFile(lastPatch.getPath(),
0734: patchfile)) {
0735: setCorrupted(UPDATE_CORRUPTION_PATCH_LOCAL_COPY);
0736:
0737: // System.out.println("UPDATE_CORRUPTION_PATCH_LOCAL_COPY : "
0738: // +UPDATE_CORRUPTION_PATCH_LOCAL_COPY);
0739: StateMonitoring.getInstance()
0740: .setXMLMonitoringStartCriticalPart();
0741:
0742: ListIterator iterator = mergedOp.getCommands();
0743: Command cmd = null;
0744:
0745: while ((cmd = (Command) iterator.next()) != null) {
0746: // execute remote cmd
0747: Logger.getLogger("ui.log").info("executing:" + cmd);
0748: cmd.execute(this .getPath(), this .getDBType());
0749: }
0750: } else {
0751: // System.out.println("Same patch do not apply it localy !!!");
0752: }
0753:
0754: setCorrupted(UPDATE_CORRUPTION_PATCH_REF_COPY);
0755:
0756: // System.out.println("UPDATE_CORRUPTION_PATCH_REF_COPY : "
0757: // +UPDATE_CORRUPTION_PATCH_REF_COPY);
0758: StateMonitoring.getInstance()
0759: .setXMLMonitoringStartCriticalPart();
0760: this .getRefCopy().patch(patchfile);
0761: setCorrupted(UPDATE_CORRUPTION_SAVE_PATCH);
0762:
0763: // System.out.println("UPDATE_CORRUPTION_SAVE_PATCH : "
0764: // +UPDATE_CORRUPTION_SAVE_PATCH);
0765: StateMonitoring.getInstance()
0766: .setXMLMonitoringStartCriticalPart();
0767: this .appliedPatch.add(patchfile);
0768: setCorrupted(UPDATE_CORRUPTION_REMOVE_PATCH);
0769:
0770: // System.out.println("UPDATE_CORRUPTION_REMOVE_PATCH : "
0771: // +UPDATE_CORRUPTION_REMOVE_PATCH);
0772: StateMonitoring.getInstance()
0773: .setXMLMonitoringStartCriticalPart();
0774: this .receivedPatch.remove(patchfile);
0775: setCorrupted(NO_CORRUPTION);
0776: }
0777:
0778: StateMonitoring.getInstance().setXMLMonitoringEndSubCall();
0779: StateMonitoring.getInstance().setXMLMonitoringEndSubCall();
0780:
0781: // Save patch report
0782: CVSReportMaker reportMaker = new CVSReportMaker(
0783: getMergedOpPath());
0784: reportMaker.buildIndexTable();
0785: report.append("Merging patch file: " + patchfile + "\n");
0786: report.append(reportMaker.getReport());
0787: report.append("\n");
0788: }
0789:
0790: /**
0791: * Update the local workspace in order to integrate the concurrent change.
0792: *
0793: * @throws Exception
0794: */
0795: public void update() throws Exception {
0796: // check corruption
0797: if (isCorrupted()) {
0798: throw new WorkspaceCorruptedException(
0799: "The local workspace is corrupted");
0800: }
0801:
0802: report = new StringBuffer();
0803: needToCheckLocalOp = true;
0804: StateMonitoring.getInstance().setXMLMonitoringStartAction(
0805: "UPDATE");
0806: StateMonitoring.getInstance().setXMLMonitoringStartSubCall(4,
0807: "");
0808: StateMonitoring.getInstance().setXMLMonitoringComment(true,
0809: "Start the update process");
0810: StateMonitoring.getInstance().setXMLMonitoringStartSubCall(1,
0811: "");
0812: StateMonitoring.getInstance().setXMLMonitoringComment(true,
0813: "Download all patch");
0814: receive();
0815: StateMonitoring.getInstance().setXMLMonitoringEndSubCall();
0816:
0817: File[] patches = receivedPatch.list();
0818: StateMonitoring.getInstance().setXMLMonitoringStartSubCall(
0819: patches.length, "Updating...");
0820: StateMonitoring.getInstance().setXMLMonitoringComment(true,
0821: "Merging");
0822:
0823: for (int i = 0; i < patches.length; i++) {
0824: StateMonitoring.getInstance().setXMLMonitoringStartSubCall(
0825: 1, "");
0826: this .update(patches[i].getPath());
0827: StateMonitoring.getInstance().setXMLMonitoringEndSubCall();
0828: }
0829:
0830: StateMonitoring.getInstance().setXMLMonitoringEndSubCall();
0831: StateMonitoring.getInstance().setXMLMonitoringEndSubCall();
0832: StateMonitoring.getInstance().setXMLMonitoringComment(false,
0833: "Finished update");
0834: StateMonitoring.getInstance().setXMLMonitoringComment(true,
0835: "Update process finished");
0836: StateMonitoring.getInstance().setXMLMonitoringEndAction(
0837: "UPDATE");
0838: getDBType().updateFromDBType(refcopy.getDBType());
0839: }
0840:
0841: /**
0842: * Download the remote patch without applying them localy.
0843: *
0844: * @throws Exception
0845: */
0846: public void receive() throws Exception {
0847: // check corruption
0848: if (isCorrupted()) {
0849: throw new WorkspaceCorruptedException(
0850: "The local workspace is corrupted");
0851: }
0852:
0853: int nbPatchToDownload = 0;
0854: int currentPatchNumber = 1;
0855: long[][] patchList = getClient().listPatch();
0856:
0857: for (int i = 0; i < patchList.length; i++) {
0858: if (patchList[i][0] > receivedPatch.getLastTicket()) {
0859: nbPatchToDownload++;
0860: }
0861: }
0862:
0863: while (getClient().getLastTicket() > receivedPatch
0864: .getLastTicket()) {
0865: StateMonitoring.getInstance().setXMLMonitoringState(
0866: 0,
0867: nbPatchToDownload,
0868: currentPatchNumber,
0869: "Downloading patch " + currentPatchNumber + " / "
0870: + nbPatchToDownload);
0871: currentPatchNumber++;
0872:
0873: String fname = getClient().getPatch(
0874: receivedPatch.getLastTicket() + 1);
0875: receivedPatch.add(fname);
0876: }
0877: }
0878:
0879: private void setCorrupted(int b) {
0880: prop.setProperty(CORRUPTION_STATE, Integer.toString(b));
0881: prop.setProperty(LAST_TICKET_BEFORE_CORRUPTION, Long
0882: .toString(getNs()));
0883: save();
0884: }
0885:
0886: /**
0887: * Return the corrupted state
0888: *
0889: * @return The corrupted state
0890: */
0891: public int getCorruptedState() {
0892: String value = prop.getProperty(CORRUPTION_STATE);
0893:
0894: if (value == null) {
0895: return -1;
0896: }
0897:
0898: return Integer.parseInt(value);
0899: }
0900:
0901: private long getLastTicketBeforeCorruption() {
0902: return Long.parseLong(prop
0903: .getProperty(LAST_TICKET_BEFORE_CORRUPTION));
0904: }
0905:
0906: /**
0907: * Return true if the connection is corrupted
0908: *
0909: * @return True if the connection is corrupted
0910: */
0911: public boolean isCorrupted() {
0912: return getCorruptedState() > 0;
0913: }
0914:
0915: /**
0916: * Restore the local corrupted connection
0917: * <p>
0918: * If the connection is not corrupted, throw an Excpetion
0919: *
0920: * @throws Exception
0921: */
0922: public void restore() throws Exception {
0923: String patchFileName;
0924: String tmpBasePath;
0925: String tmpDataPath;
0926: File src;
0927: File dst;
0928:
0929: // check corruption
0930: if (!isCorrupted()) {
0931: throw new Exception(
0932: "The local workspace is NOT corrupted !!!");
0933: }
0934:
0935: // check locks
0936: File[] children = new File(getPath()).listFiles();
0937:
0938: for (int i = 0; i < children.length; i++) {
0939: if (FileUtils.isLocked(children[i])) {
0940: throw new FileLockedException(children[i]);
0941: }
0942: }
0943:
0944: switch (getCorruptedState()) {
0945: // For update
0946: // - exec merged op
0947: // - patch refcopy
0948: // - save patch (appliedPatch.add)
0949: // - remove patch (receivedPatch.remove)
0950: // For commit
0951: // - patch refcopy
0952: // - save patch (appliedPatch.add)
0953: // - update last ticket (receivedPatch.setLastTicket)
0954: // - update local dbType
0955: // (getDBType().updateFromDBType(refcopy.getDBType()))
0956: case UPDATE_CORRUPTION_PATCH_REF_COPY:
0957:
0958: // clean ref copy
0959: FileUtils.remove(getRefCopyPath());
0960: FileUtils.createDirIfNotExist(getRefCopyPath());
0961:
0962: // Rebuild REFCOPY
0963: File[] patch = appliedPatch.list();
0964:
0965: for (int i = 0; i < patch.length; i++) {
0966: if (Long.parseLong(patch[i].getName().split("\\.")[1]) <= getLastTicketBeforeCorruption()) {
0967: getRefCopy().patch(patch[i].getAbsolutePath());
0968: System.out.println(patch[i].getName());
0969: }
0970: }
0971:
0972: case UPDATE_CORRUPTION_PATCH_LOCAL_COPY:
0973:
0974: // clean local files
0975: FileUtils.remove(getPath(), new FilterIgnoreFile(this ),
0976: false);
0977:
0978: // Rebuild local state
0979: src = new File(getRefCopyPath());
0980: dst = new File(getPath());
0981: FileUtils.copy(src, dst);
0982: System.out.println("Copy ok !");
0983:
0984: OpVectorFsImpl localOp = new OpVectorFsImpl(
0985: getLocalCmdPath());
0986: localOp.load();
0987:
0988: ListIterator i = localOp.getCommands();
0989: Command cmd = null;
0990: DBType localDBType = new DBType(getDataPath()
0991: + File.separator + "DBTYPE" + File.separator
0992: + "local.dbtype", "");
0993:
0994: while ((cmd = (Command) i.next()) != null) {
0995: System.out.println("execute: " + cmd);
0996: cmd.execute(getPath(), localDBType);
0997: }
0998:
0999: setCorrupted(NO_CORRUPTION);
1000:
1001: break;
1002:
1003: case COMMIT_CORRUPTION_PATCH_REF_COPY:
1004: FileUtils.remove(getRefCopyPath());
1005: FileUtils.createDir(getRefCopyPath());
1006:
1007: // rebuild patch copy state
1008: File[] patchList = appliedPatch.list();
1009:
1010: for (int index = 0; index < patchList.length; index++) {
1011: if (Long.parseLong(patchList[index].getName().split(
1012: "\\.")[1]) <= getLastTicketBeforeCorruption()) {
1013: PatchFile pf = new PatchFile(appliedPatch
1014: .getBaseDataPath()
1015: + File.separator
1016: + patchList[index].getName());
1017: pf.patch(getRefCopyPath(), new DBType(
1018: getDBTypePath() + File.separator
1019: + "refcopy.dbtype", ""));
1020: }
1021: }
1022:
1023: // rebuild patch and update refcopy
1024: localOp = new OpVectorFsImpl(getLocalCmdPath());
1025: localOp.load();
1026:
1027: ListIterator li = localOp.getCommands();
1028: cmd = null;
1029:
1030: //
1031: File dir = FileUtils.createTmpDir();
1032: File f = File.createTempFile("commit_", null, dir);
1033: OutputStreamWriter osw = new OutputStreamWriter(
1034: new BufferedOutputStream(new FileOutputStream(f
1035: .getPath())));
1036: osw.write("<?xml version=\"1.0\"?>");
1037: osw.write("<patch>");
1038: osw.write("<name>"
1039: + Base64.encodeBytes(getWsName().getBytes("UTF-8"))
1040: + "</name>");
1041: osw.write("<begin>" + localOp.getFromTicket() + "</begin>");
1042: osw.write("<end>" + localOp.getToTicket() + "</end>");
1043: osw.write("<comment>"
1044: + Base64.encodeBytes("Patch rebuild from a restore"
1045: .getBytes("UTF-8")) + "</comment>");
1046:
1047: while ((cmd = (Command) li.next()) != null) {
1048: osw.write("<command>");
1049: osw.write("<class>" + cmd.getClass().getName()
1050: + "</class>");
1051: cmd.toXML(osw);
1052: cmd.execute(getRefCopyPath(), new DBType(
1053: getDBTypePath() + File.separator
1054: + "refcopy.dbtype", ""));
1055: osw.write("</command>");
1056: }
1057:
1058: osw.write("</patch>");
1059: osw.flush();
1060: osw.close();
1061:
1062: // save patch
1063: appliedPatch.add(f.getPath());
1064: setCorrupted(COMMIT_CORRUPTION_UPDATE_RECEIVED_TICKET);
1065: receivedPatch.setLastTicket(appliedPatch.getLastTicket());
1066: setCorrupted(NO_CORRUPTION);
1067:
1068: break;
1069:
1070: case UPDATE_CORRUPTION_REMOVE_PATCH:
1071: patchFileName = receivedPatch.findPatchNameWithToTicket(
1072: getLastTicketBeforeCorruption()).getPath();
1073: receivedPatch.remove(patchFileName);
1074: setCorrupted(NO_CORRUPTION);
1075:
1076: break;
1077:
1078: case UPDATE_CORRUPTION_SAVE_PATCH:
1079: patchFileName = receivedPatch.findPatchNameWithFromTicket(
1080: getLastTicketBeforeCorruption() + 1).getPath();
1081: appliedPatch.add(patchFileName);
1082: setCorrupted(UPDATE_CORRUPTION_REMOVE_PATCH);
1083: receivedPatch.remove(patchFileName);
1084: setCorrupted(NO_CORRUPTION);
1085:
1086: break;
1087:
1088: case COMMIT_CORRUPTION_SAVE_PATCH:
1089:
1090: String patchFile = getClient().getPatch(
1091: getLastTicketBeforeCorruption() + 1);
1092: appliedPatch.add(patchFile);
1093: setCorrupted(NO_CORRUPTION);
1094:
1095: break;
1096:
1097: case COMMIT_CORRUPTION_UPDATE_LOCAL_DBTYPE:
1098: getDBType().updateFromDBType(refcopy.getDBType());
1099: setCorrupted(NO_CORRUPTION);
1100:
1101: break;
1102:
1103: case COMMIT_CORRUPTION_UPDATE_RECEIVED_TICKET:
1104: receivedPatch.setLastTicket(getNs());
1105: setCorrupted(NO_CORRUPTION);
1106:
1107: break;
1108: }
1109: }
1110:
1111: private void merge(String patchfile, OpVector locals)
1112: throws Exception {
1113: PatchFile pf = new PatchFile(patchfile);
1114: pf.merge(this , locals);
1115: }
1116:
1117: /**
1118: * Methode called by the MergePatchHandler
1119: *
1120: * @param cmd
1121: * @param local
1122: * @throws Exception
1123: */
1124: public void merge(Command cmd, OpVector local) throws Exception {
1125: Command origcmd = (Command) ObjectCloner.deepCopy(cmd);
1126: Command opl;
1127:
1128: // for root node
1129: // ca sert a rien...
1130:
1131: /*
1132: * iterator = localop.getNodeCommands("");
1133: * System.out.println("1============ (rien)"); while ((opl =
1134: * iterator.next()) != null) { System.out.println("opl " + opl );
1135: * Command oplt = de.transp(opl, cmd); if (!oplt.equals(opl)) {
1136: * iterator.update(oplt); } cmd = de.transp(cmd, opl); }
1137: * iterator.close();
1138: */
1139:
1140: // for each parent node
1141: /*
1142: *
1143: * String cmdPath = cmd.getPath(); System.out.println("cmd="+cmd);
1144: * StringTokenizer tokenizer = new StringTokenizer(cmdPath, "/"); String
1145: * nodeName = ""; while (tokenizer.hasMoreTokens()) { nodeName =
1146: * nodeName + tokenizer.nextToken(); iterator =
1147: * localop.getNodeCommands(nodeName); System.out.println("2============ " +
1148: * nodeName); while ((opl = iterator.next()) != null) {
1149: * System.out.println("opl " + opl); Command oplt = de.transp(opl, cmd);
1150: * if (!oplt.equals(opl)) { iterator.update(oplt); } cmd =
1151: * de.transp(cmd, opl); } nodeName = nodeName + "/"; iterator.close(); } //
1152: * For cascade rename while (!cmdPath.equals(cmd.getPath())) {
1153: * System.out.println("cmd="+cmd); cmdPath = cmd.getPath(); iterator =
1154: * localop.getNodeCommands(cmdPath); System.out.println("2'============ " +
1155: * cmdPath); while ((opl = iterator.next()) != null) {
1156: * System.out.println("opl " + opl); Command oplt = de.transp(opl, cmd);
1157: * if (!oplt.equals(opl)) { iterator.update(oplt); } cmd =
1158: * de.transp(cmd, opl); } iterator.close(); }
1159: *
1160: */
1161:
1162: // for each child
1163: // iterator = localop.getSubTreeCommands(cmd.getPath());
1164: ListIterator iterator = local.getCommands();
1165:
1166: while ((opl = (Command) iterator.next()) != null) {
1167: Command oplt = de.transp(opl, cmd);
1168:
1169: if (!oplt.equals(opl)) {
1170: iterator.set(oplt);
1171: }
1172:
1173: cmd = de.transp(cmd, opl);
1174: }
1175:
1176: // insert in merged op vector for deffered execution
1177: mergedOp.add(cmd);
1178: }
1179:
1180: /**
1181: * Return the local DBType
1182: *
1183: * @return The local DBType
1184: */
1185: public DBType getDBType() {
1186: return dbtype;
1187: }
1188:
1189: /**
1190: * Return the applied patch repository
1191: *
1192: * @return The applied patch repository
1193: */
1194: public PatchRepository getAppliedPatch() {
1195: return appliedPatch;
1196: }
1197:
1198: /**
1199: * Return the received patch repository
1200: *
1201: * @return The received patch repository
1202: */
1203: public PatchRepository getReceivedPatch() {
1204: return receivedPatch;
1205: }
1206:
1207: /**
1208: * Remove the local computed command
1209: *
1210: * @throws Exception
1211: */
1212: public void cleanLocalOp() throws Exception {
1213: FileUtils.remove(getAttachFilePath());
1214: FileUtils.remove(getLocalCmdPath());
1215: FileUtils.createDir(getAttachFilePath());
1216: FileUtils.createDir(getLocalCmdPath());
1217:
1218: //
1219: mergedTime = System.currentTimeMillis();
1220: FileUtils.createDir(getMergedOpPath());
1221: FileUtils.createDir(getMergedAttachPath());
1222: }
1223:
1224: /**
1225: * Set a commit filter.
1226: * <p>
1227: * To allow a commit of limited set of files. The vector filter must contain
1228: * all the relative file path that you want to commit.
1229: *
1230: * @param filter
1231: */
1232: public void setFilter(Vector filter) {
1233: this .patchFilter = filter;
1234: }
1235:
1236: /**
1237: * Return the number of commands that are kept with the current filter in
1238: * the localOpVector.
1239: *
1240: * @param localOp
1241: * The command vector.
1242: *
1243: * @return The number of operation kept with that filter
1244: *
1245: * @throws Exception
1246: * On dependency error or if no filter set.
1247: */
1248: public long computeNbCommandToSend(OpVector localOp)
1249: throws Exception {
1250: long nbCommandToKeep = 0;
1251:
1252: if (patchFilter == null) {
1253: throw new Exception("No filter set !!!");
1254: }
1255:
1256: ListIterator iterator = localOp.getCommands();
1257: Command cmd = null;
1258:
1259: while ((cmd = (Command) iterator.next()) != null) {
1260: String path = cmd.getPath();
1261:
1262: if (patchFilter.contains(path)) {
1263: nbCommandToKeep++;
1264: } else {
1265: for (Iterator i = patchFilter.iterator(); i.hasNext();) {
1266: File pathFiltered = new File((String) i.next());
1267:
1268: if ((pathFiltered.getParent() != null)
1269: && pathFiltered.getParent()
1270: .startsWith(path)) {
1271: throw new Exception("Dependency error: " + path);
1272: }
1273: }
1274: }
1275: }
1276:
1277: //
1278: return nbCommandToKeep;
1279: }
1280:
1281: /**
1282: * Return if the connection merge XML data
1283: *
1284: * @return if the connection merge XML data
1285: */
1286: public boolean getXmlAutoDetection() {
1287: return prop.getProperty(XML_AUTO_DETECTION, "false")
1288: .toLowerCase().equals("true");
1289: }
1290:
1291: /**
1292: * Return the last set of binary extention
1293: *
1294: * @return The last set of binary extention
1295: */
1296: public String getLastBinExt() {
1297: return prop.getProperty(LAST_BIN_EXT, "");
1298: }
1299:
1300: private void setLastBinExt(String binExt) {
1301: prop.setProperty(LAST_BIN_EXT, binExt);
1302: }
1303:
1304: /**
1305: * Enable or disable the Xml auto detection
1306: *
1307: * @param autoDetect
1308: * true if you want to activate the Xml dectection.
1309: */
1310: public void setXmlAutoDetection(boolean autoDetect) {
1311: prop.setProperty(XML_AUTO_DETECTION, Boolean
1312: .toString(autoDetect));
1313: save();
1314: }
1315:
1316: /**
1317: * Return the current report as a String for simple output. (a CVS like
1318: * report)
1319: *
1320: * @return The current report as a String for simple output. (a CVS like
1321: * report)
1322: */
1323: public String getReport() {
1324: if (report == null) {
1325: return "No Report available...";
1326: }
1327:
1328: return report.toString();
1329: }
1330:
1331: /**
1332: * Remove old merged op
1333: */
1334: public void removedOldMergedOp() throws Exception {
1335: FileUtils.remove(getMergedOpBasePath());
1336: }
1337:
1338: public void updateProp(Properties prop) {
1339: this .prop.putAll(prop);
1340: }
1341:
1342: private void walkToBuildOpFromRefCopy(File rootDir,
1343: String relativePath, OpVector ops) throws Exception {
1344: File tmpFile = null;
1345:
1346: if (!relativePath.equals(".")) {
1347: tmpFile = new File(rootDir, relativePath);
1348:
1349: if (!(tmpFile.exists())) {
1350: throw new java.io.IOException(tmpFile.getPath()
1351: + " not exists");
1352: }
1353:
1354: if (!(tmpFile.isDirectory()) && !(tmpFile.isFile())) {
1355: Logger.getLogger("ui.log").warning(
1356: "unmanaged file type:" + tmpFile.getPath());
1357:
1358: return;
1359: }
1360:
1361: Logger.getLogger("ui.log")
1362: .info("examining:" + relativePath);
1363:
1364: // monitoring xml
1365: int fileType = getRefCopy().getDBType().getType(
1366: relativePath);
1367:
1368: switch (fileType) {
1369: case DBType.TYPE_DIR:
1370: ops.add(new AddDir(relativePath, this ));
1371:
1372: break;
1373:
1374: case DBType.TYPE_FILE_BIN:
1375: ops.add(new AddBinaryFile(relativePath, this ,
1376: getRefCopyPath() + "/" + relativePath));
1377:
1378: break;
1379:
1380: case DBType.TYPE_FILE_TXT:
1381: ops.add(new AddTxtFile(relativePath, this ,
1382: getRefCopyPath() + "/" + relativePath));
1383:
1384: break;
1385:
1386: case DBType.TYPE_FILE_XML:
1387:
1388: // XmlUtil.normalizeDocument(newFile);
1389: ops.add(new AddXmlFile(relativePath, this ,
1390: getRefCopyPath() + "/" + relativePath));
1391:
1392: break;
1393:
1394: default:
1395:
1396: // nothing
1397: System.out.println(relativePath + " => " + fileType);
1398:
1399: break;
1400: }
1401:
1402: // recurse walking to seek children changes
1403: if (tmpFile.isDirectory()) { // recurse walking to detect new
1404:
1405: // children
1406: File[] subs = tmpFile.listFiles();
1407:
1408: for (int i = 0; i < subs.length; i++) {
1409: walkToBuildOpFromRefCopy(rootDir, relativePath
1410: + "/" + subs[i].getName(), ops);
1411: }
1412: }
1413: } else {
1414: File[] subs = rootDir.listFiles();
1415:
1416: for (int i = 0; i < subs.length; i++) {
1417: walkToBuildOpFromRefCopy(rootDir, subs[i].getName(),
1418: ops);
1419: }
1420: }
1421: }
1422:
1423: public String sendCurrentCompressState() throws Exception {
1424: StateMonitoring.getInstance().setXMLMonitoringStartAction(
1425: "COMPRESS");
1426: StateMonitoring.getInstance().setXMLMonitoringStartSubCall(4,
1427: null);
1428: StateMonitoring.getInstance().setXMLMonitoringComment(
1429: "Start the compress process");
1430:
1431: // TODO from - to
1432: long from = 1;
1433: long to = getAppliedPatch().getLastTicket();
1434:
1435: File patchToDo = new File(getAppliedPatch().getBaseDataPath()
1436: + File.separator + from + "." + to);
1437:
1438: if (!patchToDo.exists()) {
1439: cleanLocalOp();
1440:
1441: File tmp = new File(getLocalCmdPath());
1442: tmp.mkdirs();
1443:
1444: // Generate patch from REFCOPY
1445: OpVectorFsImpl opv = new OpVectorFsImpl(tmp.getPath());
1446: StateMonitoring.getInstance().setXMLMonitoringStartSubCall(
1447: 1, "Compute compressed operations");
1448: walkToBuildOpFromRefCopy(new File(getRefCopyPath()), ".",
1449: opv);
1450:
1451: //System.out.println(opv.size());
1452: StateMonitoring.getInstance().setXMLMonitoringEndSubCall();
1453:
1454: // Generate patch
1455: StateMonitoring.getInstance().setXMLMonitoringStartSubCall(
1456: 1, "Generate compressed patch file");
1457:
1458: OutputStreamWriter osw = new FileWriter(patchToDo);
1459: PatchFile.makePatch(opv, osw, null, from, to, "compress",
1460: "compressed patch");
1461: osw.close();
1462: StateMonitoring.getInstance().setXMLMonitoringEndSubCall();
1463:
1464: // send patch without validate
1465: StateMonitoring.getInstance().setXMLMonitoringStartSubCall(
1466: 2, "Send compressed patch");
1467: getClient().sendPatch(from, to, patchToDo.getPath(), false);
1468: StateMonitoring.getInstance().setXMLMonitoringEndSubCall();
1469: } else {
1470: // Patch already exists
1471: StateMonitoring.getInstance().setXMLMonitoringComment(
1472: false, "Nothing done.");
1473: }
1474:
1475: StateMonitoring.getInstance().setXMLMonitoringEndSubCall();
1476: StateMonitoring.getInstance().setXMLMonitoringComment(false,
1477: "Finished");
1478: StateMonitoring.getInstance().setXMLMonitoringComment(true,
1479: "Compress process finished");
1480: StateMonitoring.getInstance().setXMLMonitoringEndAction(
1481: "COMPRESS");
1482:
1483: return patchToDo.getPath();
1484: }
1485:
1486: public void compressLocalHistory(long from, long to)
1487: throws Exception {
1488: StateMonitoring.getInstance().setXMLMonitoringStartAction(
1489: "COMPRESS");
1490: StateMonitoring.getInstance().setXMLMonitoringStartSubCall(1,
1491: null);
1492: StateMonitoring.getInstance().setXMLMonitoringComment(
1493: "Start the compress process");
1494: StateMonitoring.getInstance().setXMLMonitoringStartSubCall(1,
1495: "Try to find compressed patch");
1496:
1497: // TODO from - to
1498: from = 1;
1499: to = getAppliedPatch().getLastTicket();
1500:
1501: File patchToDo = new File(getAppliedPatch().getBaseDataPath()
1502: + File.separator + from + "." + to);
1503:
1504: if (!patchToDo.exists()) {
1505: StateMonitoring.getInstance().setXMLMonitoringStartSubCall(
1506: 1, "Generate compressed patch file");
1507:
1508: // patch does not exist > generate it
1509: File cmds = new File(getDataPath() + File.separator
1510: + "CMDS");
1511: cmds.mkdirs();
1512:
1513: File attach = new File(getDataPath() + File.separator
1514: + "ATTACH");
1515: attach.mkdirs();
1516:
1517: OpVectorFsImpl opv = new OpVectorFsImpl(cmds.getPath());
1518:
1519: File[] patchs = getAppliedPatch().list();
1520:
1521: for (int i = 0; i < patchs.length; i++) {
1522: File patchFile = patchs[i];
1523: StateMonitoring.getInstance().setXMLMonitoringComment(
1524: false, patchFile.getAbsolutePath());
1525:
1526: PatchFile pf = new PatchFile(patchFile.getName());
1527: pf.buildOpVector(new FileInputStream(patchFile), opv,
1528: attach.getPath(), null);
1529: }
1530:
1531: CompressUtil.compressLog(opv);
1532:
1533: OutputStreamWriter osw = new FileWriter(patchToDo);
1534: PatchFile.makePatch(opv, osw, null, from, to, "compress",
1535: "compressed patch");
1536: osw.close();
1537: StateMonitoring.getInstance().setXMLMonitoringEndSubCall();
1538:
1539: // send patch without validate
1540: StateMonitoring.getInstance().setXMLMonitoringStartSubCall(
1541: 2, "Send compressed patch");
1542: getClient().sendPatch(from, to, patchToDo.getPath(), false);
1543: StateMonitoring.getInstance().setXMLMonitoringEndSubCall();
1544: } else {
1545: // Patch already exists
1546: StateMonitoring.getInstance().setXMLMonitoringComment(
1547: false, "Nothing done.");
1548: }
1549:
1550: StateMonitoring.getInstance().setXMLMonitoringEndSubCall();
1551: StateMonitoring.getInstance().setXMLMonitoringComment(false,
1552: "Finished");
1553: StateMonitoring.getInstance().setXMLMonitoringComment(true,
1554: "Compress process finished");
1555: StateMonitoring.getInstance().setXMLMonitoringEndAction(
1556: "COMPRESS");
1557: }
1558: }
|