| /* |
| * 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.vinci.transport.vns.service; |
| |
| import java.util.ArrayList; |
| import java.util.Stack; |
| |
| /** |
| * Services of the same name get put in the same stack and stored within the ServiceTree. |
| */ |
| public class ServiceStack { |
| |
| String name; |
| |
| Stack stack; |
| |
| int toplevel; |
| |
| public ServiceStack(String name) { |
| this.name = name; |
| reinit(); |
| } |
| |
| public void reinit() { |
| stack = new Stack(); |
| toplevel = 0; |
| } |
| |
| /* |
| * Return the Vinci view of the level No specification (null) or "none" -> -1 (highest) "all" -> |
| * -2 (invalid / indication to concatenate all) Positive int specification -> actual level from |
| * bottom of stack Negative int specification -> level from top of stack "new" or "next" -> one |
| * above the toplevel |
| */ |
| |
| public static int getAbsLevel(String level) { |
| |
| // Default as specified in SPEC.txt |
| if (level == null || level.trim().toLowerCase().equals("none")) |
| level = "-1"; |
| |
| level = level.toLowerCase().trim(); |
| |
| if (level.equals("all")) |
| return -2; |
| |
| if (level.equals("new") || level.equals("next")) |
| return 0; // Start with lowest priority |
| |
| int mylevel = Integer.parseInt(level); |
| |
| if (mylevel == -1) |
| return -1; // Special case for highest priority servers |
| |
| if (mylevel < 0) |
| return 0; // Can't count from top as top doesn't exist => return 0 |
| |
| return mylevel; |
| } |
| |
| public int absLevel(String level) { |
| |
| // Default as specified in SPEC.txt |
| if (level == null || level.trim().toLowerCase().equals("none")) |
| level = "-1"; |
| |
| level = level.toLowerCase().trim(); |
| |
| if (level.equals("all")) { |
| return -2; |
| } |
| |
| if (level.equals("new") || level.equals("next")) { |
| // Will be adjusted in actualLevel |
| return toplevel; |
| } |
| |
| int mylevel = Integer.parseInt(level); |
| |
| if (mylevel == -1) |
| return -1; // Special case for highest priority servers |
| |
| if (mylevel < 0) { |
| return Math.max(0, toplevel + mylevel); // If invalid level specified, return 0 |
| } else |
| return mylevel; |
| } |
| |
| public int absLevel(int i) { |
| return absLevel("" + i); |
| } |
| |
| /* |
| * Return the mapping into the ArrayList Returns -1 if the number cannot be mapped to a positive |
| * val |
| */ |
| private int actualLevel(int level) { |
| if (level < -1) |
| return -1; |
| |
| return level + 1; |
| } |
| |
| /* |
| * Expand the stack to the specified index level level represents the actual vector index |
| */ |
| public void expand(int level) { |
| |
| while (stack.size() <= level) |
| stack.push(null); |
| |
| if (toplevel < level) |
| toplevel = level; |
| |
| } |
| |
| /* |
| * Get the set of values above the specified Vinci level Returns an Object [] of those values |
| * (Service []) |
| */ |
| public Service[] get(String mylevel) { |
| int level = absLevel(mylevel); |
| ArrayList result = new ArrayList(); |
| |
| // Concatenate all |
| if (level == -2) { |
| |
| for (int i = 0; i < stack.size(); i++) |
| if (stack.get(i) != null) |
| result.addAll((ArrayList) stack.get(i)); |
| } else { |
| level = actualLevel(level); // convert to actual level index |
| |
| expand(level); |
| |
| level = Math.min(level, toplevel); |
| |
| // Special case check for topmost level |
| if (level == 0) { |
| if (stack.get(level) != null) |
| result.addAll((ArrayList) stack.get(level)); |
| if (result.size() < 1) |
| level = Math.max(level, toplevel); // Go to the next lower level if no results |
| } |
| |
| while (level >= 1) { // count go downto level 0 if service not found yet |
| if (stack.get(level) != null) { |
| result.addAll((ArrayList) stack.get(level)); |
| break; // Break as soon as we find a level with services running |
| } |
| level--; |
| } |
| |
| } |
| |
| Service[] res = new Service[result.size()]; |
| for (int i = 0; i < result.size(); i++) |
| res[i] = (Service) result.get(i); |
| |
| return res; |
| } |
| |
| public Object[] get(int mylevel) { |
| return get("" + mylevel); |
| } |
| |
| /* |
| * Updates the level fields in the Service and makes them consistent i.e. transforms the |
| * vinciLevel string and the actualLevel int if need be. |
| */ |
| public void makeConsistent(Service S) { |
| if (S.actualLevel < -1) { |
| S.level = "" + absLevel(S.level); |
| S.actualLevel = actualLevel(Integer.parseInt(S.level)); |
| if (S.level.equals("-2")) |
| S.level = "all"; // Switch back to all to prevent the VNS from screwing up |
| S.update(); |
| } |
| } |
| |
| /* |
| * Add the specified service to the stack The level in the Service must be a non-index level |
| */ |
| public void add(Service S) { |
| makeConsistent(S); |
| |
| // Get the actual vector index |
| int mylevel = S.actualLevel; |
| |
| // Grow the stack if need be |
| expand(mylevel); |
| |
| ArrayList v; |
| |
| if (stack.get(mylevel) == null) { |
| v = new ArrayList(); |
| v.add(S); |
| stack.setElementAt(v, mylevel); |
| } else { |
| v = (ArrayList) stack.get(mylevel); |
| v.add(S); |
| } |
| |
| pr("Added " + S.toString()); |
| } |
| |
| public boolean update(Service S) { |
| |
| // Can't update something without a level specification |
| if (S.level == null) { |
| pr("No level specified"); |
| return false; |
| } |
| |
| makeConsistent(S); |
| |
| // Get the actual vector index |
| int mylevel = S.actualLevel; |
| |
| if (stack.get(mylevel) == null) { |
| pr("No services found at specified level"); |
| return false; |
| } |
| |
| ArrayList v = (ArrayList) stack.get(mylevel); |
| Service temp; |
| |
| for (int i = 0; i < v.size(); i++) { |
| temp = (Service) v.get(i); |
| |
| if (temp.equals(S)) { |
| S.minport = temp.minport; |
| S.maxport = temp.maxport; |
| S.port = temp.port; |
| S.level = temp.level; // Weird bug [level being reset] |
| v.set(i, S); |
| pr("Update of " + S.toString() + " successful"); |
| |
| return true; |
| } |
| } |
| |
| pr("No matching service found"); |
| return false; |
| } |
| |
| public boolean isEmpty(String level) { |
| // Convert to a valid Vinci level first |
| return isEmpty(absLevel(level)); |
| } |
| |
| public boolean isEmpty(int level) { |
| if (stack.size() == 0) |
| return true; |
| |
| // Got request for all |
| if (level == -2) |
| return false; |
| |
| // toplevel should never be greater than max index of the stack |
| int mylevel = Math.min(actualLevel(level), toplevel); |
| |
| // Check if the level is the topmost level, if so, start from the topmost |
| if (level == -1) |
| mylevel = stack.size() - 1; |
| |
| while (mylevel >= 0) { |
| if (stack.get(mylevel) != null) |
| return false; |
| mylevel--; |
| } |
| |
| return true; |
| } |
| |
| public Object[] delete(Service S) { |
| ArrayList dellist = new ArrayList(), newlist = new ArrayList(); |
| |
| if (S.level == null) { |
| Object[] result = get("None"); |
| reinit(); |
| return result; |
| } |
| |
| makeConsistent(S); |
| |
| // Get the actual vector index |
| int mylevel = S.actualLevel; |
| |
| if (stack.get(mylevel) == null) |
| return dellist.toArray(); |
| |
| ArrayList srv = (ArrayList) stack.get(mylevel); |
| Service temp; |
| pr("Deleting : " + S); |
| for (int i = 0; i < srv.size(); i++) { |
| temp = (Service) srv.get(i); |
| pr("Checking : " + temp); |
| if (!(temp.toString().equals(S.toString()))) { |
| newlist.add(temp); |
| } else { |
| pr("Delete match : " + temp.toString()); |
| dellist.add(temp); |
| } |
| } |
| |
| if (newlist.size() == 0) { |
| stack.set(mylevel, null); |
| // Decrease the stack size |
| while (toplevel > 0 && stack.get(toplevel) == null) |
| toplevel--; |
| } else { |
| stack.setElementAt(newlist, mylevel); |
| } |
| |
| return dellist.toArray(); |
| } |
| |
| public static String pr(String s) { |
| System.err.println(s); |
| return s; |
| } |
| |
| } // end class |