Manejo de Conflictos de Replicación

De ChuWiki

Manejo de conflictos de replicación[editar]

Lotus Notes es un sistema cliente - servidor de trabajo colaborativo, es desarrollado por Lotus Software.

Como Lotus Notes permite tener replicas distribuidas de sus bases de datos, es muy común que surjan conflictos de replicación cuando un mismo documento es modificado en dos diversas replicas y luego la base de datos es replicada a un servidor central.

Lotus Notes tiene un algoritmo interno con el cual marca uno de los documentos como conflicto de replicación y al otro lo considera como ganador. Sin embargo es necesario asegurarse que la perdida de información es mínima.

Este agente de Java Lotus Notes permite eliminar los conflictos de replicación, revisando uno a uno los campos de cada documento y eligiendo conservar el de fecha más reciente de edición. Puede ser agendado en un servidor, teniendo en cuenta que para agendar un agente este debe ser firmado y el usuario que lo firma debe tener permisos de ejecutar procedimientos en el servidor.


/**
 *
 */
import lotus.domino.*;
import java.util.Vector;

/**
 * @author jabernal
 *
 */
public class SolveReplicationConflicts extends AgentBase {

  /**
   * @param args
   */
  public void NotesMain() {

    try {
      Session session = getSession();
      AgentContext agentContext = session.getAgentContext();

      // Abrimos la base de datos actual
      Database db = agentContext.getCurrentDatabase();
      String serverName = db.getServer();
      // Nos aseguramos que sólo se ejecuta en un servidor COLO_
      if(!(serverName == ""))
      {
        deleteConflicts(db);
      }
    } catch(NotesException ex) {
      ex.printStackTrace();
    }
  }

  private void deleteConflicts(Database db)
  {
    boolean markToDelete = false;
    DocumentCollection collection = null;
    // Buscamos los documentos que son marcados como conflictos de replicación por Lotus Notes
    try
    {
      collection = db.search("@IsAvailable( $Conflict ) & @IsAvailable( $Ref )", null, 0);
    }catch(NotesException ex){
      ex.printStackTrace();
    }
    if(!(collection == null))
    {
      Document winnerDoc = null;
      Document parentDoc = null;
      Document tempDoc = null;
      // Recorremos la colección
      Document loserDoc = null;
      try{
        loserDoc = collection.getFirstDocument();
      }catch(NotesException ex){
        ex.printStackTrace();
      }
      while(!(loserDoc == null))
      {
        // Asignamos el documento en una variable temporal para poderlo borrar en caso necesario
        tempDoc = loserDoc;
        markToDelete = false;
        winnerDoc = null;
        // Buscamos el documento ganador en la resolución de conflictos
        try{
          winnerDoc = db.getDocumentByUNID(loserDoc.getParentDocumentUNID());
        }catch(NotesException ex){
          ex.printStackTrace();
        }
        // Si se encontró el documento ganador
        if(!(winnerDoc == null))
        {
          try{
            if(winnerDoc.getLastModified().toJavaDate().before(
                loserDoc.getLastModified().toJavaDate()))
            {
              replaceItems(loserDoc, winnerDoc);
              parentDoc = null;
              if(winnerDoc.hasItem("$Ref"))
              {
                try{
                  parentDoc = db.getDocumentByUNID(winnerDoc.getParentDocumentUNID());
                }catch(Exception ex){
                  ex.printStackTrace();
                }
              }
              loserDoc.removeItem("$Conflict");
              loserDoc.removeItem("$Ref");
              if(!(parentDoc == null))
              {
                loserDoc.makeResponse(parentDoc);
              }
              loserDoc.save(true, false, false);
              winnerDoc.remove(true);
            }
            else
            {
              if(replaceItems(winnerDoc, loserDoc))
              {
                winnerDoc.save(true, false, false);
              }
              markToDelete = true;
            }
          }catch(NotesException ex){}
        }
        try{
          loserDoc = collection.getNextDocument(loserDoc);
        }catch(NotesException ex){
          ex.printStackTrace();
          loserDoc = null;
        }
        if(markToDelete)
        {
          try{
            tempDoc.remove(true);
          }catch(NotesException ex){
            ex.printStackTrace();
          }
        }
      }
    }
  }

  private boolean replaceItems(Document docToKeep, Document docToDelete)
  {
    boolean found = false;
    try{
      Vector items = docToKeep.getItems();
      Item itemToKeep = null;
      Item itemToDelete = null;
      for(int i = 0; i < items.size(); ++i)
      {
        itemToKeep = (Item)items.elementAt(i);
        if(!(itemToKeep == null))
        {
          if(itemToKeep.getName() != "Form" && itemToKeep.getName().indexOf("$") < 0)
          {
            if(docToDelete.hasItem(itemToKeep.getName()))
            {
              itemToDelete = null;
              try{
                itemToDelete = docToDelete.getFirstItem(itemToKeep.getName());
              }catch(Exception ex){
                // ex.printStackTrace();
              }
              if(!(itemToDelete == null))
              {
                try{
                  if(itemToKeep.getValues() != itemToDelete.getValues())
                  {
                    if(itemToKeep.getLastModified().toJavaDate().before(
                        itemToDelete.getLastModified().toJavaDate()))
                    {
                      try{
                        docToKeep.replaceItemValue(itemToKeep.getName(), itemToDelete.getValues());
                      }catch(NotesException ex){
                        // ex.printStackTrace();
                      }
                      found = true;
                    }
                  }
                }catch(NotesException ex){
                  // ex.printStackTrace();
                }
                catch(Exception ex){
                  // ex.printStackTrace();
                }
              }
            }
          }
        }
      }
    }catch(NotesException ex){
      ex.printStackTrace();
    }
    return found;
  }
}