package com.fourinone;
import java.util.Hashtable;
import java.util.List;
import java.rmi.RemoteException;//ServiceException
import java.io.Serializable;
import java.util.zip.CRC32;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.Date;
public class ParkService extends MementoService implements Park
{
private ParkObjValue parkinfo = new ParkObjValue();
private static ObjValue hbinfo = new ObjValue();
//private Lock lk = new ReentrantLock();
private ReadWriteLock rwlk = new ReentrantReadWriteLock();
private ParkLeader pl = null;
public ParkService(String host, int port, String[][] servers, String parkService) throws RemoteException{
pl = new ParkLeader(host,port,servers,parkService);
pl.wantBeMaster(this);
}
private String checkSessionId(String sessionid){
if(sessionid==null)
return "se"+System.nanoTime();
else
return sessionid;
}
private Long updateDomainVersion(String domain) throws RemoteException{
Long domainversion = (Long)parkinfo.getObj(ParkMeta.getYBB(domain));
ObjValue nodeversions = parkinfo.getWidely(ParkMeta.getYBB(domain+"\\..+"));
List vlist = nodeversions.getObjValues();
String crcstr = "";
for(Object obj:vlist)
crcstr+=obj+"";
Long crcversion = getObjectVersion(ObjectBytes.toBytes(crcstr));
return (crcversion!=domainversion)?crcversion:domainversion;
}
private Long updateDomainVersion(){
Long crcversion = getObjectVersion(ObjectBytes.toBytes(System.nanoTime()));
return crcversion;
}
private Long getObjectVersion(byte[] obj){
CRC32 crc = new CRC32();
crc.update(obj);//ObjectBytes.toBytes(o)
return new Long(crc.getValue());
}
public String getSessionId() throws RemoteException{
return checkSessionId(null);
}
public ObjValue create(String domain, String node, byte[] obj, String sessionid, int auth, boolean heartbeat) throws RemoteException,ClosetoOverException
{
ClosetoOverException.checkMemCapacity();
ObjValue objv = null;
if(domain!=null&&node!=null){
//lk.lock();
Lock wlk = rwlk.writeLock();
wlk.lock();
try{
String domainnodekey = parkinfo.getDomainnodekey(domain, node);
if(!parkinfo.containsKey(domainnodekey)){
if(!parkinfo.containsKey(domain)){
parkinfo.setObj(domain, 0l);
parkinfo.setObj(ParkMeta.getYBB(domain), 0l);
parkinfo.setString(ParkMeta.getYCJZ(domain), sessionid);
parkinfo.setString(ParkMeta.getYCIP(domain), getClientHost());
parkinfo.setObj(ParkMeta.getYCSJ(domain), System.currentTimeMillis());
}
parkinfo.setObj(domainnodekey, obj);
parkinfo.setObj(ParkMeta.getYBB(domainnodekey), getObjectVersion(obj));
parkinfo.setObj(ParkMeta.getYBB(domain), updateDomainVersion());//updateDomainVersion(domain)
parkinfo.setObj(ParkMeta.getYCJZ(domainnodekey), sessionid);
parkinfo.setObj(ParkMeta.getYQX(domainnodekey), auth);
parkinfo.setObj(ParkMeta.getYCIP(domainnodekey), getClientHost());
parkinfo.setObj(ParkMeta.getYCSJ(domainnodekey), System.currentTimeMillis());
Long nodenum = (Long)parkinfo.getObj(domain);
parkinfo.setObj(domain, nodenum+1);
if(heartbeat)
{
parkinfo.setObj(ParkMeta.getYSX(domainnodekey), ParkMeta.getSXXT());
//HbDaemo.runGetTask(hbinfo, this);
}
pl.runCopyTask(domainnodekey, this);
LogUtil.fine("[create]", "["+domainnodekey+"]", obj);
objv = get(domain, node, sessionid);
}
else LogUtil.info("[Park]", "[create]", domainnodekey+" is exist!");//throw exist exception
}catch(Exception e){
//e.printStackTrace();
LogUtil.info("[Park]", "[create]", e);
}finally {
//lk.unlock();
wlk.unlock();
}
}
return objv;
}
//synchronized
public ObjValue update(String domain, String node, byte[] obj, String sessionid) throws RemoteException,ClosetoOverException
{
ClosetoOverException.checkMemCapacity();
ObjValue objv = null;
if(domain!=null&&node!=null){
//lk.lock();
Lock wlk = rwlk.writeLock();
wlk.lock();
try{
String domainnodekey = parkinfo.getDomainnodekey(domain, node);
if(checkAuth(domainnodekey, sessionid, AuthPolicy.OP_READ_WRITE)){
if(parkinfo.containsKey(domainnodekey)){
parkinfo.setObj(domainnodekey, obj);
Long theversion = getObjectVersion(obj);
if(theversion!=(Long)parkinfo.getObj(ParkMeta.getYBB(domainnodekey))){
parkinfo.setObj(ParkMeta.getYBB(domainnodekey), theversion);
parkinfo.setObj(ParkMeta.getYBB(domain), updateDomainVersion());//updateDomainVersion(domain)
}
parkinfo.setString(ParkMeta.getYGXZ(domainnodekey), sessionid);
parkinfo.setString(ParkMeta.getYGIP(domainnodekey), getClientHost());
parkinfo.setObj(ParkMeta.getYGSJ(domainnodekey), System.currentTimeMillis());
LogUtil.fine("[update]", "["+domainnodekey+"]", obj);
pl.runCopyTask(domainnodekey, this);
objv = get(domain, node, sessionid);
}
else LogUtil.info("[Park]", "[update]", domainnodekey+" is not exist!");//throw not exist exception
}
}catch(Exception e){
//e.printStackTrace();
LogUtil.info("[Park]", "[update]", e);
}finally {
//lk.unlock();
wlk.unlock();
}
}
return objv;
}
public boolean update(String domain, int auth, String sessionid) throws RemoteException
{
boolean updateflag = false;
if(domain!=null){
Lock wlk = rwlk.writeLock();
wlk.lock();
try{
if(parkinfo.containsKey(domain)){
if(checkAuth(domain, sessionid, AuthPolicy.OP_READ_WRITE)){
parkinfo.setObj(ParkMeta.getYQX(domain), auth);
updateflag = true;
LogUtil.fine("[update]", "["+domain+" Auth]", auth);
pl.runCopyTask(domain, this);
}
}else LogUtil.info("[Park]", "[update]", domain+" is not exist!");//throw not exist exception
}catch(Exception e){
LogUtil.info("[Park]", "[update]", e);
}finally {
wlk.unlock();
}
}
return updateflag;
}
public ObjValue delete(String domain, String node, String sessionid) throws RemoteException,ClosetoOverException
{
ObjValue objrm = null;
//if(sessionid==Acl)
if(domain!=null){
if(node==null)
ClosetoOverException.checkMemCapacity();
if(checkAuth(parkinfo.getDomainnodekey(domain, node), sessionid, AuthPolicy.OP_ALL))
objrm = delete(domain, node);
}
return objrm;
}
protected ObjValue delete(String domain, String node)
{
ObjValue objrm = null;
Lock wlk = rwlk.writeLock();
wlk.lock();
try{
String domainnodekey = parkinfo.getDomainnodekey(domain, node);
objrm = parkinfo.removeNode(domain, node);//removeNodeWidely(domainnodekey);
if(!objrm.isEmpty()){
Long nodenum = (Long)parkinfo.getObj(domain);
//System.out.println("delete nodenum:"+nodenum);
if(nodenum!=null){
if(nodenum==1l)
parkinfo.removeDomain(domain);//removeNodeWidely(domain);
else{
parkinfo.setObj(domain, nodenum-1);
parkinfo.setObj(ParkMeta.getYBB(domain), updateDomainVersion());//updateDomainVersion(domain)
}
}
LogUtil.fine("[delete]", "["+domainnodekey+"]", objrm);
pl.runCopyTask(domainnodekey, this);
}else{
objrm = null;
LogUtil.info("[Park]", "[delete]", domainnodekey+" cant be deleted or not exist!");//throw not exist exception
}
}catch(Exception e){
//e.printStackTrace();
LogUtil.info("[Park]", "[delete]", e);
}finally {
wlk.unlock();
}
return objrm;
}
public boolean checkAuth(String domainnodekey, String sessionid, AuthPolicy targetauth)
{
boolean authflag = false;
String creator = parkinfo.getString(ParkMeta.getYCJZ(domainnodekey));
if(creator!=null){
if(creator.equals(sessionid))
authflag = true;
else{
Object domainnodeAuth = parkinfo.getObj(ParkMeta.getYQX(domainnodekey));
int thekeyauth = domainnodeAuth!=null?(Integer)domainnodeAuth:1;//only read for domain
authflag = AuthPolicy.authIncluded(targetauth.getPolicy(), thekeyauth);
}
}
if(!authflag)
LogUtil.info("[Park]", "[AuthPolicy]", "No permissions to do for "+domainnodekey+"!");
return authflag;
}
public ObjValue get(String domain, String node, String sessionid) throws RemoteException,ClosetoOverException
{
//String thesessionid = checkSessionId(sessionid);
//lk.lock();
ObjValue ov = null;
if(domain!=null){
if(node==null)
ClosetoOverException.checkMemCapacity();
Lock rlk = rwlk.readLock();
rlk.lock();
LogUtil.fine("[Park]", "[get]", parkinfo.getDomainnodekey(domain, node));
ov = parkinfo.getNode(domain, node);//parkinfo.getNodeWidely(parkinfo.getDomainnodekey(domain, node));
if(ov.isEmpty())
ov = null;
//lk.unlock();
rlk.unlock();
}
return ov;
}
public ObjValue getLastest(String domain, String node, String sessionid, long version) throws RemoteException,ClosetoOverException
{
//lk.lock();
Lock rlk = rwlk.readLock();
rlk.lock();
Long nodeversion = (Long)parkinfo.getObj(ParkMeta.getYBB(parkinfo.getDomainnodekey(domain, node)));
if(nodeversion!=null&&nodeversion!=version)
LogUtil.fine("[Park]", "[getLastest]", "nodeversion:"+nodeversion+";version:"+version);
ObjValue ov = (nodeversion!=null&&nodeversion!=version)?get(domain,node,sessionid):null;
//lk.unlock();
rlk.unlock();
return ov;
}
public ObjValue getParkinfo() throws RemoteException
{
try{
LogUtil.fine("[Park]", "[getParkinfo]", "getParkinfo from "+getClientHost());
}catch(Exception e){
LogUtil.fine("[Park]", "[getParkinfo]", e.getMessage());
}
return getTheParkinfo();
}
ObjValue getTheParkinfo()
{
ObjValue ov = null;
Lock rlk = rwlk.readLock();
rlk.lock();
ov = parkinfo.getParkInfo();
rlk.unlock();
return ov;
}
public boolean setParkinfo(ObjValue ov) throws RemoteException
{
LogUtil.fine("[Park]", "[setParkinfo]", ov);
Lock wlk = rwlk.writeLock();
wlk.lock();
parkinfo = (ParkObjValue)ov;
wlk.unlock();
return true;
}
public String[] askMaster() throws RemoteException
{
LogUtil.info("[Park]", "[askMaster]", "receive askMaster................");
return pl.isMaster();
}
public boolean askLeader() throws RemoteException,LeaderException
{
LogUtil.info("[Park]", "[askLeader]", "receive askLeader................");
String[] sv = new String[2];
if(pl.checkMasterPark(sv,this))
return true;
else throw new LeaderException(pl.getThisserver(),sv);
}
public boolean heartbeat(String[] domainnodekey, String sessionid) throws RemoteException
{
boolean hbback = false;
if(domainnodekey!=null){
for(String curkey:domainnodekey)
hbinfo.setObj(curkey, new Date().getTime());
hbback = true;
}
//System.out.println("hbinfo:"+hbinfo);
HbDaemo.runGetTask(hbinfo, this);
return hbback;
}
/*public List<ObjValue> getNodesInDomain(String domain, String sessionid) throws RemoteException
{
return null;
}*/
public static void main(String[] args)
{
if(args!=null&&args.length==2)
BeanContext.startPark(args[0],Integer.parseInt(args[1]));
else BeanContext.startPark();
/*BeanContext.setConfigFile("D:\\demo\\comutil\\test\\config.xml");
String[][] servers = new String[args.length][];
for(int i=0;i<args.length;i++){
String[] theserver = new String[]{"localhost",args[i]};
servers[i] = theserver;
}
try{
ParkService ps = new ParkService(servers[0][0],Integer.parseInt(servers[0][1]), servers, "ParkService");
Long i=new Long(0);
System.out.println(i+","+new java.util.Date());
while(true)
{
ObjValue ov = ps.createTest("d", i+"", new byte[1], "aaaaa", 7, false);
if(i%100==0)
{
System.out.println(i+","+new java.util.Date());
}
i++;
}
}catch(Exception e){
System.out.println(e);
}*/
//BeanContext.startPark(servers[0][0],Integer.parseInt(servers[0][1]), servers);
//BeanContext.startPark();
}
}