All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.gemstone.gemfire.internal.ManagerLogWriter Maven / Gradle / Ivy

/*
 * Copyright (c) 2010-2015 Pivotal Software, Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License. You
 * may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * permissions and limitations under the License. See accompanying
 * LICENSE file.
 */
package com.gemstone.gemfire.internal;

import com.gemstone.gemfire.distributed.DistributedMember;
import com.gemstone.gemfire.distributed.internal.DistributionManager;
import com.gemstone.gemfire.distributed.internal.membership.InternalDistributedMember;
import com.gemstone.gemfire.i18n.LogWriterI18n;
import com.gemstone.gemfire.internal.admin.remote.AlertListenerMessage;
import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
import com.gemstone.gemfire.internal.tcp.ReenteredConnectException;
import com.gemstone.gemfire.internal.util.LogFileUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Pattern;

/**
  * Implementation of {@link LogWriterI18n} for distributed system members.
  * Its just like {@link LocalLogWriter} except it has support for rolling
  * and alerts. 
  *
  * @author Darrel Schneider
  * @since 1.0
  */
public class ManagerLogWriter extends LocalLogWriter  {

  public static final String TEST_FILE_SIZE_LIMIT_IN_KB_PROPERTY = "gemfire.logging.test.fileSizeLimitInKB";

  private final boolean fileSizeLimitInKB;
  
  private LogConfig cfg = null;
  private DistributionManager dm = null;

    // Constructors
    /**
     * Creates a writer that logs to System.out.
     * @param level only messages greater than or equal to this value will be logged.
     * @throws IllegalArgumentException if level is not in legal range
     */
    public ManagerLogWriter(int level, PrintStream out) {
	this(level, out, null);
    }

    /**
     * Creates a writer that logs to System.out.
     *
     * @param level 
     *        only messages greater than or equal to this value will
     *        be logged. 
     * @param connectionName
     *        Name of the connection associated with this logger
     *
     * @throws IllegalArgumentException if level is not in legal range
     *
     * @since 3.5
     */
    public ManagerLogWriter(int level, PrintStream out,
                            String connectionName) {
	super(level, out, connectionName);
	this.fileSizeLimitInKB = Boolean.getBoolean(TEST_FILE_SIZE_LIMIT_IN_KB_PROPERTY);
    }
  
    // Special Instance Methods on this class only

    
    private LocalLogWriter mainLogger = this;

    /**
     * Gets the logger that writes to the main log file.
     * This logger may differ from the current logger when rolling
     * logs are used.
     */
    public LogWriterI18n getMainLogger() {
      return this.mainLogger;
    }
  
    /**
     * Sets the config that should be used by this manager to decide
     * how to manage its logging.
     */
    public void setConfig(LogConfig cfg) {
      this.cfg = cfg;
      configChanged();
    }

    /**
     * Sets the DistributionManager that will be used to send alert
     * messages to any listening consoles
     */
    public void setDistributionManager(DistributionManager dm) {
      this.dm = dm;
    }

    /**
     * Call when the config changes at runtime.
     */
    public void configChanged() {
      setLevel(cfg.getLogLevel());
      useChildLogging = cfg.getLogFile() != null
        && !cfg.getLogFile().equals(new File(""))
        && cfg.getLogFileSizeLimit() != 0;

      if (useChildLogging()) {
        childLogPattern = getLogPattern(this.cfg.getLogFile().getName());
        logDir = getParentFile(this.cfg.getLogFile());
        // let archive id always follow main log id, not the vice versa
        // e.g. in getArchiveName(), it's using mainArchiveId = calcNextMainId(archiveDir);
        // This is the only place we assign mainLogId. 
        // mainLogId is only referenced when useChildLogging==true
        mainLogId = calcNextMainId(logDir, true);
      }
      if (started) {
        if (useChildLogging()) {
          if (mainLog) {
            rollLog();
          }
        } else {
          if (!mainLog) {
            switchLogs(this.cfg.getLogFile(), true);
          }
        }
      }
    }

  public File getChildLogFile() {
    return this.activeLogFile;
  }

  private Pattern childLogPattern = null;
  private File logDir = null;
  private int mainLogId = -1;
  private int childId = 0;


  public File getLogDir() {
    return this.logDir;
  }

  public int getMainLogId() {
    return this.mainLogId;
  }
  
  public static String formatId(int id) {
    StringBuilder result = new StringBuilder(10);
    result.append('-');
    if (id < 10) {
      result.append('0');
    }
    result.append(id);
    return result.toString();
  }
    private File getNextChildLogFile() {
      String path = this.cfg.getLogFile().getPath();
      int extIdx = path.lastIndexOf('.');
      String ext = "";
      if (extIdx != -1) {
        ext = path.substring(extIdx);
        path = path.substring(0, extIdx);
      }
      path = path + formatId(mainLogId) + formatId(this.childId) + ext;
      this.childId++;
      File result = new File(path);
      if (result.exists()) {
        // try again until a unique name is found
        return getNextChildLogFile();
      } else {
        return result;
      }
    }

    private boolean useChildLogging = false;
    public boolean useChildLogging() {
      return this.useChildLogging;
    }
    /**
     * Set to true when roll is in progress
     */
    private boolean rolling = false; 
    private boolean mainLog = true; 

    private long getLogFileSizeLimit() {
      if (rolling || mainLog) {
        return Long.MAX_VALUE;
      } else {
        long result = cfg.getLogFileSizeLimit();
        if (result == 0) {
          return Long.MAX_VALUE;
        }
        if (this.fileSizeLimitInKB) {
          // use KB instead of MB to speed up log rolling for test purpose
          return result * (1024);
        } else {
          return result * (1024*1024);
        }
      }
    }
    private long getLogDiskSpaceLimit() {
      long result = cfg.getLogDiskSpaceLimit();
      return result * (1024*1024);
    }

    
    private static String getMetaLogFileName(String baseLogFileName, int mainLogId) {
      String metaLogFile = null;
      int extIdx = baseLogFileName.lastIndexOf('.');
      String ext = "";
      if (extIdx != -1) {
        ext = baseLogFileName.substring(extIdx);
        metaLogFile = baseLogFileName.substring(0, extIdx);
      }
      String fileName = new File(metaLogFile).getName();
      String parent = new File(metaLogFile).getParent();
      
      metaLogFile = "meta-"+ fileName + formatId(mainLogId) + ext;
      if (parent != null) {
        metaLogFile = parent + File.separator + metaLogFile;
      }
      return metaLogFile;
    }
    
    private File activeLogFile = null;
    private synchronized void switchLogs(File newLog, boolean newIsMain) {
      rolling = true;
      try {
        try {
          if (!newIsMain) {
            if (mainLog && mainLogger == this && this.cfg.getLogFile() != null) {
              // this is the first child. Save the current output stream
              // so we can log special messages to the main log instead
              // of the current child log.
              String metaLogFile = getMetaLogFileName(this.cfg.getLogFile().getPath(), this.mainLogId);
              mainLogger = new LocalLogWriter(INFO_LEVEL, new PrintStream(new FileOutputStream(metaLogFile, true), true));
              if(activeLogFile==null) {
                mainLogger.info(LocalizedStrings.ManagerLogWriter_SWITCHING_TO_LOG__0, this.cfg.getLogFile());
              }
            } else {
              mainLogger.info(LocalizedStrings.ManagerLogWriter_ROLLING_CURRENT_LOG_TO_0, newLog);
            }
          }
          boolean renameOK = true;
          String oldName = this.cfg.getLogFile().getAbsolutePath();
          File tmpFile = null;
          if(this.activeLogFile!=null) {
            // @todo gregp: is a bug that we get here and try to rename the activeLogFile
            // to a newLog of the same name? This works ok on Unix but on windows fails.
            if (!this.activeLogFile.getAbsolutePath().equals(newLog.getAbsolutePath())) {
              boolean isWindows = false;
              String os = System.getProperty("os.name");
              if (os != null) {
                if (os.indexOf("Windows") != -1) {
                  isWindows = true;
                }
              }
              if (isWindows) {
                // For windows to work we need to redirect everything
                // to a temporary file so we can get oldFile closed down
                // so we can rename it. We don't actually write to this tmp file
                File tmpLogDir = getParentFile(this.cfg.getLogFile());
                tmpFile = File.createTempFile("mlw", null, tmpLogDir);
                // close the old guy down before we do the rename
                PrintStream tmpps = OSProcess.redirectOutput(tmpFile);
	        PrintWriter oldPW = this.setTarget(new PrintWriter(tmpps,true));
                if (oldPW != null) {
                  oldPW.close();
                }
              }
              File oldFile = this.activeLogFile;
              renameOK = LogFileUtils.renameAggressively(oldFile,newLog.getAbsoluteFile());
              if(!renameOK) {
                mainLogger.warning("Could not delete original file '" + oldFile +
                          "' after copying to '" + newLog.getAbsoluteFile() + "'. Continuing without rolling.");
              } else {
	       renameOK = true;
	      } 
            }
          }
          this.activeLogFile = new File(oldName);
          PrintStream ps = OSProcess.redirectOutput(activeLogFile);
          PrintWriter oldPW = this.setTarget(new PrintWriter(ps, true), this.activeLogFile.length());
          if (oldPW != null) {
            oldPW.close();
          }
          if (tmpFile != null) {
            tmpFile.delete();
          }
          mainLog = newIsMain;
          if (mainLogger==null) {
            mainLogger = this;
          }
          if (!renameOK) {
            mainLogger.warning("Could not rename \"" + this.activeLogFile
                               + "\" to \"" + newLog + "\". Continuing without rolling.");
          }
        } catch (IOException ex) {
          mainLogger.warning("Could not open log \"" + newLog
                             + "\" because " + ex);
        }
        checkDiskSpace(this.activeLogFile);
      } finally {
        rolling = false;
      }
    }
    
    /** notification from manager that the output file is being closed */
    public void closingLogFile() {
      OutputStream out = new OutputStream() {
        @Override
        public void write(int b) throws IOException {
          // --> /dev/null
        }
      };
      close();
      if(mainLogger!=null) {
         mainLogger.close();
      }
      PrintWriter pw = this.setTarget(new PrintWriter(out, true));
      if(pw!=null) {
        pw.close();
      }
    }

    /* This method is only used by gemfirexd, use getLogNameForOldMainLog instead - xzhou
     *  
     */
//    public static File getMainLogName(File log) {
//      /*
//       * this is just searching for the existing logfile name
//       * we need to search for meta log file name
//       *
//       */
//      File dir = log.getAbsoluteFile().getParentFile();
//      int previousMainId = calcNextMainId(dir, true);
//      // comment out the following to fix bug 31789
////       if (previousMainId > 1) {
////         previousMainId--;
////       }
//      previousMainId--;
//      File result = null;
//      do {
//        previousMainId++;
//        StringBuilder buf = new StringBuilder(log.getPath());
//        int insertIdx = buf.lastIndexOf(".");
//        if (insertIdx == -1) {
//          buf
//            .append(formatId(previousMainId))
//            .append(formatId(1));
//        } else {
//          buf.insert(insertIdx, formatId(1));
//          buf.insert(insertIdx, formatId(previousMainId));
//        }
//        result = new File(buf.toString());
//      } while (result.exists());
//      return result;
//    }
    
    /**
     * as a fix for bug #41474 we use "." if getParentFile returns null
     */
    private static File getParentFile(File f) {
      File tmp = f.getAbsoluteFile().getParentFile();
      if (tmp == null) {
        tmp = new File(".");
      }
      return tmp;
    }
    
    
    public static File getLogNameForOldMainLog(File log, boolean useOldFile) {
      /*
       * this is just searching for the existing logfile name
       * we need to search for meta log file name
       * 
       */
      File dir = getParentFile(log.getAbsoluteFile());
      int previousMainId = calcNextMainId(dir, true);
      if (useOldFile) {
        if(previousMainId>0) {
          previousMainId--;
        }
      }
      if(previousMainId==0) {
        previousMainId=1;
      }
    
      // comment out the following to fix bug 31789
//       if (previousMainId > 1) {
//         previousMainId--;
//       }
      File result = null;
        int childId = calcNextChildId(log, previousMainId > 0 ? previousMainId : 0);
        StringBuilder buf = new StringBuilder(log.getPath());
        int insertIdx = buf.lastIndexOf(".");
        if (insertIdx == -1) {
          buf
            .append(formatId(previousMainId))
            .append(formatId(childId));
        } else {
          buf.insert(insertIdx, formatId(childId));
          buf.insert(insertIdx, formatId(previousMainId));
        }
        result = new File(buf.toString());
      return result;
    }
    

    private static Pattern getLogPattern(String name) {
      int extIdx = name.lastIndexOf('.');
      String ext = "";
      if (extIdx != -1) {
        ext = "\\Q" + name.substring(extIdx) + "\\E";
        name = name.substring(0, extIdx);
      }
      name = "\\Q" + name + "\\E" + "-\\d+-\\d+" + ext;
      return Pattern.compile(name);
    }

    protected static final Pattern mainIdPattern = Pattern.compile(".+-\\d+-\\d+\\..+");
    protected static final Pattern metaIdPattern = Pattern.compile("meta-.+-\\d+\\..+");

    public static int calcNextMainId(File dir, boolean toCreateNew) {
      int result = 0;
      File[] childLogs = FileUtil.listFiles(dir, new FilenameFilter() {
          public boolean accept(File d, String name) {
            return mainIdPattern.matcher(name).matches();
          }
        });
      
      /* Search child logs */
      for (File childLog: childLogs) {
        String name = childLog.getName();
        int endIdIdx = name.lastIndexOf('-');
        int startIdIdx = name.lastIndexOf('-', endIdIdx-1);
        String id = name.substring(startIdIdx+1, endIdIdx);
        try {
          int mid= Integer.parseInt(id);
          if (mid > result) {
            result = mid;
          }
        } catch (NumberFormatException ignore) {
        }
      }
      
      /* And search meta logs */
      if (toCreateNew) {
        File[] metaLogs = FileUtil.listFiles(dir, new FilenameFilter() {
          public boolean accept(File d, String name) {
            return metaIdPattern.matcher(name).matches();
          }
        });
        for (File metaLog: metaLogs) {
          String name = metaLog.getName();
          int endIdIdx = name.lastIndexOf('.');
          int startIdIdx = name.lastIndexOf('-', endIdIdx-1);
          String id = name.substring(startIdIdx+1, endIdIdx);
          try {
            int mid = Integer.parseInt(id);
            if (mid > result) {
              result = mid;
            }
          } catch (NumberFormatException ignore) {
          }
        }
        result++;
      }

      return result;
    }
    protected static final Pattern childIdPattern = Pattern.compile(".+-\\d+-\\d+\\..+");

    
    public static int calcNextChildId(File log,int mainId) {
      int result = 0;
      File dir = getParentFile(log.getAbsoluteFile());
      int endidx1 = log.getName().indexOf('-');
      int endidx2 = log.getName().lastIndexOf('.');
      String baseName = log.getName();
      if (endidx1 != -1) {
        baseName =  log.getName().substring(0, endidx1);
      } else {
        baseName =  log.getName().substring(0, endidx2);
      }
      File[] childLogs = FileUtil.listFiles(dir, new FilenameFilter() {
          public boolean accept(File d, String name) {
            return childIdPattern.matcher(name).matches();
          }
        });
      
      /* Search child logs */
      
      for (File childLog: childLogs) {
        String name = childLog.getName();
        // only compare the childlogid among the same set of log files.
        if (!name.startsWith(baseName)) {
          continue;
        }
        int endIdIdx = name.lastIndexOf('-');
        int startIdIdx = name.lastIndexOf('-', endIdIdx-1);
        String id = name.substring(startIdIdx+1, endIdIdx);
        
        int startChild = name.lastIndexOf("-");
        int endChild = name.lastIndexOf(".");
        if(startChild>0 && endChild>0) {
          String childId = name.substring(startChild+1,endChild);
          
          try {
            int mainLogId = Integer.parseInt(id);
            int childLogId = Integer.parseInt(childId);
            if (mainLogId ==mainId && childLogId>result) {
              result = childLogId;
            }
          } catch (NumberFormatException ignore) {
          }
        }
      }
      result++;
      return result;
    }
    
    

//  private static void debugLog(String msg, boolean stackDump) {
//    try {
//      FileOutputStream f = new FileOutputStream("debug.log", true);
//      LogWriterI18n lw = new LocalLogWriter(ALL_LEVEL, new PrintStream(f));
//      if (stackDump) {
//        lw.info(msg, new RuntimeException("STACK"));
//      } else {
//        lw.info(msg);
//      }
//      f.close();
//    } catch (IOException ignore) {
//    }
//  }
  
    public static void removeOldLogs(LogConfig cfg,
                                     File logFile) {
      LogWriterI18n log = new LocalLogWriter(INFO_LEVEL, System.err);
      checkDiskSpace("log", null,
                     ((long)cfg.getLogDiskSpaceLimit()) * (1024*1024),
                     getParentFile(logFile),
                     getLogPattern(logFile.getName()),
                     log);
    }
  
    public static void checkDiskSpace(String type,
                                       File newLog,
                                       long spaceLimit,
                                       File dir,
                                       final Pattern logPattern,
                                       LogWriterI18n logger) {
      if (spaceLimit == 0 || logPattern == null) {
        return;
      }
      final String newLogName = (newLog == null) ? null : newLog.getName();
      File[] childLogs = FileUtil.listFiles(dir, new FilenameFilter() {
          public boolean accept(File d, String name) {
            if (name.equals(newLogName)) {
              return false;
            } else {
              boolean result = logPattern.matcher(name).matches();
              return result;
            }
          }
        });
      if (childLogs == null) {
        if (dir.isDirectory()) {
          logger.warning(
              LocalizedStrings.ManagerLogWriter_COULD_NOT_CHECK_DISK_SPACE_ON_0_BECAUSE_JAVAIOFILELISTFILES_RETURNED_NULL_THIS_COULD_BE_CAUSED_BY_A_LACK_OF_FILE_DESCRIPTORS,
              dir);
        }
        return;
      }
      Arrays.sort(childLogs, new Comparator() {
          public int compare(Object o1, Object o2) {
            File f1 = (File)o1;
            File f2 = (File)o2;
            long diff =  f1.lastModified() - f2.lastModified();
            if (diff < 0) {
              return -1;
            } else if (diff > 0) {
              return 1;
            } else {
              return 0;
            }
          }
        });
      long spaceUsed = 0;
      for (File childLog: childLogs) {
        spaceUsed += childLog.length();
      }
      int fIdx = 0;
      while (spaceUsed >= spaceLimit
             && fIdx < childLogs.length) { // check array index to 37388
        long childSize = childLogs[fIdx].length();
        if (childLogs[fIdx].delete()) {
            spaceUsed -= childSize;
            logger.info(LocalizedStrings.ManagerLogWriter_DELETED_INACTIVE__0___1_, new Object[] {type, childLogs[fIdx]});
        } else {
          logger.warning(LocalizedStrings.ManagerLogWriter_COULD_NOT_DELETE_INACTIVE__0___1_, new Object[] {type, childLogs[fIdx]});
        }
        fIdx++;
      }
      if (spaceUsed > spaceLimit) {
        logger.warning(
            LocalizedStrings.ManagerLogWriter_COULD_NOT_FREE_SPACE_IN_0_DIRECTORY_THE_SPACE_USED_IS_1_WHICH_EXCEEDS_THE_CONFIGURED_LIMIT_OF_2,
            new Object[] {type, Long.valueOf(spaceUsed), Long.valueOf(spaceLimit)});
      }
    }

    private void checkDiskSpace(File newLog) {
      checkDiskSpace("log", newLog, getLogDiskSpaceLimit(), logDir, childLogPattern, mainLogger);
    }
  
    public void rollLog() {
      rollLog(false);
    }
  private void rollLogIfFull() {
    rollLog(true);
  }
  
  private void rollLog(boolean ifFull) {
    if (!useChildLogging()) {
      return;
    }
    synchronized (this) {
      // need to do the activeLogFull call while synchronized
      if (ifFull && !activeLogFull()) {
        return;
      }
      switchLogs(getNextChildLogFile(), false);
    }
  }

  private boolean started = false;
    /**
     * Called when manager is done starting up.
     * This is when a child log will be started if rolling is configured.
     */
    public void startupComplete() {
      started = true;
      rollLog();
    }
    /**
     * Called when manager starts shutting down.
     * This is when any current child log needs to be closed and the
     * rest of the logging reverted to the main. Also clears alert listeners.
     */
    public void shuttingDown() {
      synchronized (alertListeners) {
        alertListeners.clear();
      }
      if (useChildLogging()) {
        switchLogs(this.cfg.getLogFile(), true);
      }
    }

    private boolean activeLogFull() {
      long limit = getLogFileSizeLimit();
      if (limit == Long.MAX_VALUE) {
        return false;
      } else {
        return getBytesLogged() >= limit;
      }
    }

    @Override
    public String put(int msgLevel, Date msgDate,
      String connectionName, String threadName, long tid, String msg,
      String exceptionText) {

      String result = null; // This seems to workaround a javac bug
      result = super.put(msgLevel, msgDate, connectionName, threadName,
        tid, msg, exceptionText);
      notifyAlertListeners(msgLevel, msgDate, connectionName, threadName, tid, msg,
        exceptionText);
      return result;
    }

    @Override
    public void writeFormattedMessage(String s) {
      rollLogIfFull();
      super.writeFormattedMessage(s);
    }

  // alert listener support
  private final Map alertListeners = new HashMap();
  private int lowestAlertLevel = NONE_LEVEL;

  /** Is this thread in the process of sending an alert?  */
  private static final ThreadLocal alerting =
    new ThreadLocal() {
    @Override
        protected Object initialValue() {
          return Boolean.FALSE;
        }
      };
  

  /**
   * is the current thread in the process of sending an alert?
   * @return true if the current thread is sending an alert, false if not
   */
  public static boolean isAlerting() {
    return ((Boolean)alerting.get()).booleanValue();
  }

  private void notifyAlertListeners(int msgLevelWithFlags, Date msgDate, String connectionName, String threadName, long tid, String msg, String exceptionText) {
    int msgLevel = getRealLogLevel(msgLevelWithFlags);
    if (msgLevel < lowestAlertLevel) {
      return;
    }

    if (((Boolean) alerting.get()).booleanValue()) {
      // If this thread is already sending an alert, do not send
      // another one.  Otherwise, we get infinite recursion.
      return;

    } else {
      alerting.set(Boolean.TRUE);
    }
    Collection listeners = new ArrayList();
    synchronized (alertListeners) {
      // Make a copy of the alert listeners to avoid deadlock with
      // logging and membership
      listeners.addAll(this.alertListeners.entrySet());
    }

    Iterator it = listeners.iterator();
    while (it.hasNext()) {
      Map.Entry me = (Map.Entry)it.next();
      int alertLevel = ((Integer)me.getValue()).intValue();      
      Object recipient = me.getKey();
      if (msgLevel >= alertLevel && dm != null) {
        try {
        dm.putOutgoing(AlertListenerMessage.create(recipient, msgLevel,
                                                   msgDate, connectionName,
                                                   threadName, tid, msg,
                                                   exceptionText));
        } catch(ReenteredConnectException e) {
          //Ok, we can't send to this recipient, because we're in the middle
          //of trying to connect to it.
        }
      }
    }

    alerting.set(Boolean.FALSE);
  }
  
  /**
   * DUnit test method to determine whether this LogWriterI18n has an alert
   * listener.
   * @return true if there is an alert listener registered
   */
  public boolean hasAlertListener() {
    return this.alertListeners.size() > 0;
  }
  
  public void addAlertListener(InternalDistributedMember sender, int msgLevel) {
    if (infoEnabled()) {
      info("Adding alert listener " + String.valueOf(sender) + " level=" + msgLevel);
    }
    synchronized (alertListeners) {
      alertListeners.put(sender, Integer.valueOf(msgLevel));
      if (msgLevel < lowestAlertLevel) {
        lowestAlertLevel = msgLevel;
      }
    }
  }
  public boolean removeAlertListener(InternalDistributedMember sender) {
    Integer oldValue = null;
    synchronized (alertListeners) {
      oldValue = (Integer)alertListeners.remove(sender);
      if (oldValue != null) {
        int removedLevel = oldValue.intValue();
        if (removedLevel == lowestAlertLevel) {
          // recalculate
          int oldLowestAlertLevel = lowestAlertLevel;
          lowestAlertLevel = NONE_LEVEL;
          Iterator it = alertListeners.values().iterator();
          while (it.hasNext()) {
            int l = ((Integer)it.next()).intValue();
            if (l < lowestAlertLevel) {
              lowestAlertLevel = l;
              if (l == oldLowestAlertLevel) {
                break;
              }
            }
          }
        }
      }
    }
    if (oldValue != null) {
      if (fineEnabled()) {
        fine("Removed alert listener " + String.valueOf(sender));
      }
    }
    return oldValue != null;
  }
  public static interface LogConfig {
    /**
     * Returns the value of the "log-level" property
     *
     * @see com.gemstone.gemfire.internal.LogWriterImpl
     */
    public int getLogLevel();
    /**
     * Returns the value of the "log-file" property
     *
     * @return null if logging information goes to standard
     *         out
     */
    public File getLogFile();
    /**
     * Returns the value of the "log-file-size-limit"
     * property
     */
    public int getLogFileSizeLimit();
    /**
     * Returns the value of the "log-disk-space-limit"
     * property
     */
    public int getLogDiskSpaceLimit();
  }

  public boolean hasAlertListenerFor(DistributedMember member, int severity) {
    synchronized(this.alertListeners) {
      Integer memberSeverity = (Integer) this.alertListeners.get(member);
      return memberSeverity!=null && memberSeverity.intValue() == severity;
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy