Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ package org.apache.stratos.autoscaler; import org.apache.commons.configuration.XMLConfiguration; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.stratos.autoscaler.util.ConfUtil; import org.apache.stratos.cloud.controller.stub.deployment.partition.Partition; import org.apache.stratos.cloud.controller.stub.pojo.MemberContext; import java.io.Serializable; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; /** * This is an object that inserted to the rules engine. * Holds information about a partition. * @author nirmal * */ public class PartitionContext implements Serializable { private static final long serialVersionUID = -2920388667345980487L; private static final Log log = LogFactory.getLog(PartitionContext.class); private String partitionId; private String serviceName; private String networkPartitionId; private Partition partition; // private int currentActiveMemberCount = 0; private int minimumMemberCount = 0; private int pendingMembersFailureCount = 0; private final int PENDING_MEMBER_FAILURE_THRESHOLD = 5; // properties private Properties properties; // 15 mints as the default private long expiryTime = 900000; // pending members private List<MemberContext> pendingMembers; // members to be terminated private List<String> obsoletedMembers; // Contains the members that CEP notified as faulty members. // private List<String> faultyMembers; // active members private List<MemberContext> activeMembers; // termination pending members, member is added to this when Autoscaler send grace fully shut down event private List<MemberContext> terminationPendingMembers; //Keep statistics come from CEP private Map<String, MemberStatsContext> memberStatsContexts; private int nonTerminatedMemberCount; // private int totalMemberCount; // for the use of tests public PartitionContext(long memberExpiryTime) { this.activeMembers = new ArrayList<MemberContext>(); this.terminationPendingMembers = new ArrayList<MemberContext>(); expiryTime = memberExpiryTime; } public PartitionContext(Partition partition) { this.setPartition(partition); this.minimumMemberCount = partition.getPartitionMin(); this.partitionId = partition.getId(); this.pendingMembers = new ArrayList<MemberContext>(); this.activeMembers = new ArrayList<MemberContext>(); this.terminationPendingMembers = new ArrayList<MemberContext>(); this.obsoletedMembers = new CopyOnWriteArrayList<String>(); // this.faultyMembers = new CopyOnWriteArrayList<String>(); memberStatsContexts = new ConcurrentHashMap<String, MemberStatsContext>(); // check if a different value has been set for expiryTime XMLConfiguration conf = ConfUtil.getInstance(null).getConfiguration(); expiryTime = conf.getLong("autoscaler.member.expiryTimeout", 900000); if (log.isDebugEnabled()) { log.debug("Member expiry time is set to: " + expiryTime); } Thread th = new Thread(new PendingMemberWatcher(this)); th.start(); } public List<MemberContext> getPendingMembers() { return pendingMembers; } public void setPendingMembers(List<MemberContext> pendingMembers) { this.pendingMembers = pendingMembers; } public int getActiveMemberCount() { return activeMembers.size(); } public void setActiveMembers(List<MemberContext> activeMembers) { this.activeMembers = activeMembers; } public String getPartitionId() { return partitionId; } public void setPartitionId(String partitionId) { this.partitionId = partitionId; } // public int getTotalMemberCount() { // // live count + pending count // return currentActiveMemberCount + pendingMembers.size(); // } // public void incrementCurrentActiveMemberCount(int count) { // // this.currentActiveMemberCount += count; // } // public void decrementCurrentActiveMemberCount(int count) { // this.currentActiveMemberCount -= count; // } public int getMinimumMemberCount() { return minimumMemberCount; } public void setMinimumMemberCount(int minimumMemberCount) { this.minimumMemberCount = minimumMemberCount; } public Partition getPartition() { return partition; } public void setPartition(Partition partition) { this.partition = partition; } public void addPendingMember(MemberContext ctxt) { this.pendingMembers.add(ctxt); } public boolean removePendingMember(String id) { if (id == null) { return false; } for (Iterator<MemberContext> iterator = pendingMembers.iterator(); iterator.hasNext();) { MemberContext pendingMember = (MemberContext) iterator.next(); if (id.equals(pendingMember.getMemberId())) { iterator.remove(); return true; } } return false; } public void movePendingMemberToActiveMembers(String memberId) { if (memberId == null) { return; } Iterator<MemberContext> iterator = pendingMembers.listIterator(); while (iterator.hasNext()) { MemberContext pendingMember = iterator.next(); if (pendingMember == null) { iterator.remove(); continue; } if (memberId.equals(pendingMember.getMemberId())) { // member is activated // remove from pending list iterator.remove(); // add to the activated list this.activeMembers.add(pendingMember); pendingMembersFailureCount = 0; if (log.isDebugEnabled()) { log.debug(String.format( "Pending member is removed and added to the " + "activated member list. [Member Id] %s", memberId)); } break; } } } public void moveActiveMemberToTerminationPendingMembers(String memberId) { if (memberId == null) { return; } Iterator<MemberContext> iterator = activeMembers.listIterator(); while (iterator.hasNext()) { MemberContext activeMember = iterator.next(); if (activeMember == null) { iterator.remove(); continue; } if (memberId.equals(activeMember.getMemberId())) { // member is activated // remove from pending list iterator.remove(); // add to the activated list this.terminationPendingMembers.add(activeMember); if (log.isDebugEnabled()) { log.debug(String.format("Active member is removed and added to the " + "termination pending member list. [Member Id] %s", memberId)); } break; } } } public void addActiveMember(MemberContext ctxt) { this.activeMembers.add(ctxt); } public void removeActiveMember(MemberContext ctxt) { this.activeMembers.remove(ctxt); } public boolean removeTerminationPendingMember(String memberId) { boolean terminationPendingMemberAvailable = false; for (MemberContext memberContext : terminationPendingMembers) { if (memberContext.getMemberId().equals(memberId)) { terminationPendingMemberAvailable = true; terminationPendingMembers.remove(memberContext); break; } } return terminationPendingMemberAvailable; } public void addObsoleteMember(String memberId) { this.obsoletedMembers.add(memberId); } public boolean removeObsoleteMember(String memberId) { return this.obsoletedMembers.remove(memberId); } // // public void addFaultyMember(String memberId) { // this.faultyMembers.add(memberId); // } // // public boolean removeFaultyMember(String memberId) { // return this.faultyMembers.remove(memberId); // } // // public List<String> getFaultyMembers() { // return this.faultyMembers; // } public long getExpiryTime() { return expiryTime; } public void setExpiryTime(long expiryTime) { this.expiryTime = expiryTime; } public List<String> getObsoletedMembers() { return obsoletedMembers; } public void setObsoletedMembers(List<String> obsoletedMembers) { this.obsoletedMembers = obsoletedMembers; } public String getNetworkPartitionId() { return networkPartitionId; } public void setNetworkPartitionId(String networkPartitionId) { this.networkPartitionId = networkPartitionId; } public Map<String, MemberStatsContext> getMemberStatsContexts() { return memberStatsContexts; } public MemberStatsContext getMemberStatsContext(String memberId) { return memberStatsContexts.get(memberId); } public void addMemberStatsContext(MemberStatsContext ctxt) { this.memberStatsContexts.put(ctxt.getMemberId(), ctxt); } public void removeMemberStatsContext(String memberId) { this.memberStatsContexts.remove(memberId); } public MemberStatsContext getPartitionCtxt(String id) { return this.memberStatsContexts.get(id); } // public boolean memberExist(String memberId) { // return memberStatsContexts.containsKey(memberId); // } public Properties getProperties() { return properties; } public void setProperties(Properties properties) { this.properties = properties; } public String getServiceName() { return serviceName; } public void setServiceName(String serviceName) { this.serviceName = serviceName; } public List<MemberContext> getTerminationPendingMembers() { return terminationPendingMembers; } public void setTerminationPendingMembers(List<MemberContext> terminationPendingMembers) { this.terminationPendingMembers = terminationPendingMembers; } public int getTotalMemberCount() { return activeMembers.size() + pendingMembers.size() + terminationPendingMembers.size(); } public int getNonTerminatedMemberCount() { return activeMembers.size() + pendingMembers.size() + terminationPendingMembers.size(); } public List<MemberContext> getActiveMembers() { return activeMembers; } public boolean removeActiveMemberById(String memberId) { boolean removeActiveMember = false; synchronized (activeMembers) { Iterator<MemberContext> iterator = activeMembers.listIterator(); while (iterator.hasNext()) { MemberContext memberContext = iterator.next(); if (memberId.equals(memberContext.getMemberId())) { iterator.remove(); removeActiveMember = true; break; } } } return removeActiveMember; } public boolean activeMemberExist(String memberId) { for (MemberContext memberContext : activeMembers) { if (memberId.equals(memberContext.getMemberId())) { return true; } } return false; } private class PendingMemberWatcher implements Runnable { private PartitionContext ctxt; public PendingMemberWatcher(PartitionContext ctxt) { this.ctxt = ctxt; } @Override public void run() { while (true) { long expiryTime = ctxt.getExpiryTime(); List<MemberContext> pendingMembers = ctxt.getPendingMembers(); synchronized (pendingMembers) { Iterator<MemberContext> iterator = pendingMembers.listIterator(); while (iterator.hasNext()) { MemberContext pendingMember = iterator.next(); if (pendingMember == null) { continue; } long pendingTime = System.currentTimeMillis() - pendingMember.getInitTime(); if (pendingTime >= expiryTime) { iterator.remove(); log.info("Pending state of member: " + pendingMember.getMemberId() + " is expired. " + "Adding as an obsoleted member."); // member should be terminated ctxt.addObsoleteMember(pendingMember.getMemberId()); pendingMembersFailureCount++; if (pendingMembersFailureCount > PENDING_MEMBER_FAILURE_THRESHOLD) { setExpiryTime(expiryTime * 2);//Doubles the expiry time after the threshold of failure exceeded //TODO Implement an alerting system: STRATOS-369 } } } } try { // TODO find a constant Thread.sleep(15000); } catch (InterruptedException ignore) { } } } } }