+++ /dev/null
-/*******************************************************************************\r
- * ============LICENSE_START====================================================\r
- * * org.onap.aaf\r
- * * ===========================================================================\r
- * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.\r
- * * ===========================================================================\r
- * * Licensed under the Apache License, Version 2.0 (the "License");\r
- * * you may not use this file except in compliance with the License.\r
- * * You may obtain a copy of the License at\r
- * * \r
- * * http://www.apache.org/licenses/LICENSE-2.0\r
- * * \r
- * * Unless required by applicable law or agreed to in writing, software\r
- * * distributed under the License is distributed on an "AS IS" BASIS,\r
- * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * * See the License for the specific language governing permissions and\r
- * * limitations under the License.\r
- * * ============LICENSE_END====================================================\r
- * *\r
- * * ECOMP is a trademark and service mark of AT&T Intellectual Property.\r
- * *\r
- ******************************************************************************/\r
-package org.onap.aaf.dao;\r
-\r
-import java.io.IOException;\r
-import java.util.ArrayList;\r
-import java.util.List;\r
-\r
-import org.onap.aaf.authz.env.AuthzEnv;\r
-\r
-import org.onap.aaf.cadi.routing.GreatCircle;\r
-import org.onap.aaf.inno.env.APIException;\r
-import org.onap.aaf.inno.env.Env;\r
-import org.onap.aaf.inno.env.util.Split;\r
-import com.datastax.driver.core.Cluster;\r
-import com.datastax.driver.core.Cluster.Builder;\r
-import com.datastax.driver.core.policies.DCAwareRoundRobinPolicy;\r
-\r
-public class CassAccess {\r
- public static final String KEYSPACE = "authz";\r
- public static final String CASSANDRA_CLUSTERS = "cassandra.clusters";\r
- public static final String CASSANDRA_CLUSTERS_PORT = "cassandra.clusters.port";\r
- public static final String CASSANDRA_CLUSTERS_USER_NAME = "cassandra.clusters.user";\r
- public static final String CASSANDRA_CLUSTERS_PASSWORD = "cassandra.clusters.password";\r
- public static final String CASSANDRA_RESET_EXCEPTIONS = "cassandra.reset.exceptions";\r
- public static final String LATITUDE = "LATITUDE";\r
- public static final String LONGITUDE = "LONGITUDE";\r
- private static final List<Resettable> resetExceptions = new ArrayList<Resettable>();\r
- public static final String ERR_ACCESS_MSG = "Accessing Backend";\r
- private static Builder cb = null;\r
-\r
- /**\r
- * To create DCAwareRoundRobing Policy:\r
- * Need Properties\r
- * LATITUDE (or AFT_LATITUDE)\r
- * LONGITUDE (or AFT_LONGITUDE)\r
- * CASSANDRA CLUSTERS with additional information:\r
- * machine:DC:lat:long,machine:DC:lat:long\r
- * @param env\r
- * @param prefix\r
- * @return\r
- * @throws APIException\r
- * @throws IOException\r
- */\r
-\r
- @SuppressWarnings("deprecation")\r
- public static synchronized Cluster cluster(Env env, String prefix) throws APIException, IOException {\r
- if(cb == null) {\r
- String pre;\r
- if(prefix==null) {\r
- pre="";\r
- } else {\r
- env.info().log("Cassandra Connection for ",prefix);\r
- pre = prefix+'.';\r
- }\r
- cb = Cluster.builder();\r
- String str = env.getProperty(pre+CASSANDRA_CLUSTERS_PORT,"9042");\r
- if(str!=null) {\r
- env.init().log("Cass Port = ",str );\r
- cb.withPort(Integer.parseInt(str));\r
- }\r
- str = env.getProperty(pre+CASSANDRA_CLUSTERS_USER_NAME,null);\r
- if(str!=null) {\r
- env.init().log("Cass User = ",str );\r
- String epass = env.getProperty(pre + CASSANDRA_CLUSTERS_PASSWORD,null);\r
- if(epass==null) {\r
- throw new APIException("No Password configured for " + str);\r
- }\r
- //TODO Figure out way to ensure Decryptor setting in AuthzEnv\r
- if(env instanceof AuthzEnv) {\r
- cb.withCredentials(str,((AuthzEnv)env).decrypt(epass,true));\r
- } else {\r
- cb.withCredentials(str, env.decryptor().decrypt(epass));\r
- }\r
- }\r
- \r
- str = env.getProperty(pre+CASSANDRA_RESET_EXCEPTIONS,null);\r
- if(str!=null) {\r
- env.init().log("Cass ResetExceptions = ",str );\r
- for(String ex : Split.split(',', str)) {\r
- resetExceptions.add(new Resettable(env,ex));\r
- }\r
- }\r
- \r
- str = env.getProperty(LATITUDE,env.getProperty("AFT_LATITUDE",null));\r
- Double lat = str!=null?Double.parseDouble(str):null;\r
- str = env.getProperty(LONGITUDE,env.getProperty("AFT_LONGITUDE",null));\r
- Double lon = str!=null?Double.parseDouble(str):null;\r
- if(lat == null || lon == null) {\r
- throw new APIException("LATITUDE(or AFT_LATITUDE) and/or LONGITUDE(or AFT_LATITUDE) are not set");\r
- }\r
- \r
- env.init().printf("Service Latitude,Longitude = %f,%f",lat,lon);\r
- \r
- str = env.getProperty(pre+CASSANDRA_CLUSTERS,"localhost");\r
- env.init().log("Cass Clusters = ",str );\r
- String[] machs = Split.split(',', str);\r
- String[] cpoints = new String[machs.length];\r
- String bestDC = null;\r
- int numInBestDC = 1;\r
- double mlat, mlon,temp,distance = -1.0;\r
- for(int i=0;i<machs.length;++i) {\r
- String[] minfo = Split.split(':',machs[i]);\r
- if(minfo.length>0) {\r
- cpoints[i]=minfo[0];\r
- }\r
- \r
- // Calc closest DC with Great Circle\r
- if(minfo.length>3) {\r
- mlat = Double.parseDouble(minfo[2]);\r
- mlon = Double.parseDouble(minfo[3]);\r
- if((temp=GreatCircle.calc(lat, lon, mlat, mlon)) > distance) {\r
- distance = temp;\r
- if(bestDC!=null && bestDC.equals(minfo[1])) {\r
- ++numInBestDC;\r
- } else {\r
- bestDC = minfo[1];\r
- numInBestDC = 1;\r
- }\r
- } else {\r
- if(bestDC!=null && bestDC.equals(minfo[1])) {\r
- ++numInBestDC;\r
- }\r
- }\r
- }\r
- }\r
- \r
- cb.addContactPoints(cpoints);\r
- \r
- if(bestDC!=null) {\r
- // 8/26/2016 Management has determined that Accuracy is preferred over speed in bad situations\r
- // Local DC Aware Load Balancing appears to have the highest normal performance, with the best\r
- // Degraded Accuracy\r
- cb.withLoadBalancingPolicy(new DCAwareRoundRobinPolicy(\r
- bestDC, numInBestDC, true /*allow LocalDC to look at other DCs for LOCAL_QUORUM */));\r
- env.init().printf("Cassandra configured for DCAwareRoundRobinPolicy at %s with emergency remote of up to %d node(s)"\r
- ,bestDC, numInBestDC);\r
- } else {\r
- env.init().printf("Cassandra is using Default Policy, which is not DC aware");\r
- }\r
- }\r
- return cb.build();\r
- }\r
- \r
- private static class Resettable {\r
- private Class<? extends Exception> cls;\r
- private List<String> messages;\r
- \r
- @SuppressWarnings("unchecked")\r
- public Resettable(Env env, String propData) throws APIException {\r
- if(propData!=null && propData.length()>1) {\r
- String[] split = Split.split(':', propData);\r
- if(split.length>0) {\r
- try {\r
- cls = (Class<? extends Exception>)Class.forName(split[0]);\r
- } catch (ClassNotFoundException e) {\r
- throw new APIException("Declared Cassandra Reset Exception, " + propData + ", cannot be ClassLoaded");\r
- }\r
- }\r
- if(split.length>1) {\r
- messages=new ArrayList<String>();\r
- for(int i=1;i<split.length;++i) {\r
- String str = split[i];\r
- int start = str.startsWith("\"")?1:0;\r
- int end = str.length()-(str.endsWith("\"")?1:0);\r
- messages.add(split[i].substring(start, end));\r
- }\r
- } else {\r
- messages = null;\r
- }\r
- }\r
- }\r
- \r
- public boolean matches(Exception ex) {\r
- if(ex.getClass().equals(cls)) {\r
- if(messages!=null) {\r
- String msg = ex.getMessage();\r
- for(String m : messages) {\r
- if(msg.contains(m)) {\r
- return true;\r
- }\r
- }\r
- }\r
- }\r
- return false;\r
- }\r
- }\r
- \r
- public static final boolean isResetException(Exception e) {\r
- if(e==null) {\r
- return true;\r
- }\r
- for(Resettable re : resetExceptions) {\r
- if(re.matches(e)) {\r
- return true;\r
- }\r
- }\r
- return false;\r
- }\r
-}\r