DNSStatefulObject.java
Go to the documentation of this file.
00001 // Licensed under Apache License version 2.0
00002 package javax.jmdns.impl;
00003 
00004 import java.util.Collection;
00005 import java.util.concurrent.ConcurrentHashMap;
00006 import java.util.concurrent.ConcurrentMap;
00007 import java.util.concurrent.Semaphore;
00008 import java.util.concurrent.TimeUnit;
00009 import java.util.concurrent.locks.ReentrantLock;
00010 import java.util.logging.Level;
00011 import java.util.logging.Logger;
00012 
00013 import javax.jmdns.impl.constants.DNSState;
00014 import javax.jmdns.impl.tasks.DNSTask;
00015 
00022 public interface DNSStatefulObject {
00023 
00032     public static final class DNSStatefulObjectSemaphore {
00033         private static Logger                          logger = Logger.getLogger(DNSStatefulObjectSemaphore.class.getName());
00034 
00035         private final String                           _name;
00036 
00037         private final ConcurrentMap<Thread, Semaphore> _semaphores;
00038 
00043         public DNSStatefulObjectSemaphore(String name) {
00044             super();
00045             _name = name;
00046             _semaphores = new ConcurrentHashMap<Thread, Semaphore>(50);
00047         }
00048 
00055         public void waitForEvent(long timeout) {
00056             Thread thread = Thread.currentThread();
00057             Semaphore semaphore = _semaphores.get(thread);
00058             if (semaphore == null) {
00059                 semaphore = new Semaphore(1, true);
00060                 semaphore.drainPermits();
00061                 _semaphores.putIfAbsent(thread, semaphore);
00062             }
00063             semaphore = _semaphores.get(thread);
00064             try {
00065                 semaphore.tryAcquire(timeout, TimeUnit.MILLISECONDS);
00066             } catch (InterruptedException exception) {
00067                 logger.log(Level.FINER, "Exception ", exception);
00068             }
00069         }
00070 
00074         public void signalEvent() {
00075             Collection<Semaphore> semaphores = _semaphores.values();
00076             for (Semaphore semaphore : semaphores) {
00077                 semaphore.release();
00078                 semaphores.remove(semaphore);
00079             }
00080         }
00081 
00082         @Override
00083         public String toString() {
00084             StringBuilder aLog = new StringBuilder(1000);
00085             aLog.append("Semaphore: ");
00086             aLog.append(this._name);
00087             if (_semaphores.size() == 0) {
00088                 aLog.append(" no semaphores.");
00089             } else {
00090                 aLog.append(" semaphores:\n");
00091                 for (Thread thread : _semaphores.keySet()) {
00092                     aLog.append("\tThread: ");
00093                     aLog.append(thread.getName());
00094                     aLog.append(' ');
00095                     aLog.append(_semaphores.get(thread));
00096                     aLog.append('\n');
00097                 }
00098             }
00099             return aLog.toString();
00100         }
00101 
00102     }
00103 
00104     public static class DefaultImplementation extends ReentrantLock implements DNSStatefulObject {
00105         private static Logger                    logger           = Logger.getLogger(DefaultImplementation.class.getName());
00106 
00107         private static final long                serialVersionUID = -3264781576883412227L;
00108 
00109         private volatile JmDNSImpl               _dns;
00110 
00111         protected volatile DNSTask               _task;
00112 
00113         protected volatile DNSState              _state;
00114 
00115         private final DNSStatefulObjectSemaphore _announcing;
00116 
00117         private final DNSStatefulObjectSemaphore _canceling;
00118 
00119         public DefaultImplementation() {
00120             super();
00121             _dns = null;
00122             _task = null;
00123             _state = DNSState.PROBING_1;
00124             _announcing = new DNSStatefulObjectSemaphore("Announce");
00125             _canceling = new DNSStatefulObjectSemaphore("Cancel");
00126         }
00127 
00131         @Override
00132         public JmDNSImpl getDns() {
00133             return this._dns;
00134         }
00135 
00136         protected void setDns(JmDNSImpl dns) {
00137             this._dns = dns;
00138         }
00139 
00143         @Override
00144         public void associateWithTask(DNSTask task, DNSState state) {
00145             if (this._task == null && this._state == state) {
00146                 this.lock();
00147                 try {
00148                     if (this._task == null && this._state == state) {
00149                         this.setTask(task);
00150                     }
00151                 } finally {
00152                     this.unlock();
00153                 }
00154             }
00155         }
00156 
00160         @Override
00161         public void removeAssociationWithTask(DNSTask task) {
00162             if (this._task == task) {
00163                 this.lock();
00164                 try {
00165                     if (this._task == task) {
00166                         this.setTask(null);
00167                     }
00168                 } finally {
00169                     this.unlock();
00170                 }
00171             }
00172         }
00173 
00177         @Override
00178         public boolean isAssociatedWithTask(DNSTask task, DNSState state) {
00179             this.lock();
00180             try {
00181                 return this._task == task && this._state == state;
00182             } finally {
00183                 this.unlock();
00184             }
00185         }
00186 
00187         protected void setTask(DNSTask task) {
00188             this._task = task;
00189         }
00190 
00195         protected void setState(DNSState state) {
00196             this.lock();
00197             try {
00198                 this._state = state;
00199                 if (this.isAnnounced()) {
00200                     _announcing.signalEvent();
00201                 }
00202                 if (this.isCanceled()) {
00203                     _canceling.signalEvent();
00204                     // clear any waiting announcing
00205                     _announcing.signalEvent();
00206                 }
00207             } finally {
00208                 this.unlock();
00209             }
00210         }
00211 
00215         @Override
00216         public boolean advanceState(DNSTask task) {
00217             boolean result = true;
00218             if (this._task == task) {
00219                 this.lock();
00220                 try {
00221                     if (this._task == task) {
00222                         this.setState(this._state.advance());
00223                     } else {
00224                         logger.warning("Trying to advance state whhen not the owner. owner: " + this._task + " perpetrator: " + task);
00225                     }
00226                 } finally {
00227                     this.unlock();
00228                 }
00229             }
00230             return result;
00231         }
00232 
00236         @Override
00237         public boolean revertState() {
00238             boolean result = true;
00239             if (!this.willCancel()) {
00240                 this.lock();
00241                 try {
00242                     if (!this.willCancel()) {
00243                         this.setState(this._state.revert());
00244                         this.setTask(null);
00245                     }
00246                 } finally {
00247                     this.unlock();
00248                 }
00249             }
00250             return result;
00251         }
00252 
00256         @Override
00257         public boolean cancelState() {
00258             boolean result = false;
00259             if (!this.willCancel()) {
00260                 this.lock();
00261                 try {
00262                     if (!this.willCancel()) {
00263                         this.setState(DNSState.CANCELING_1);
00264                         this.setTask(null);
00265                         result = true;
00266                     }
00267                 } finally {
00268                     this.unlock();
00269                 }
00270             }
00271             return result;
00272         }
00273 
00277         @Override
00278         public boolean closeState() {
00279             boolean result = false;
00280             if (!this.willClose()) {
00281                 this.lock();
00282                 try {
00283                     if (!this.willClose()) {
00284                         this.setState(DNSState.CLOSING);
00285                         this.setTask(null);
00286                         result = true;
00287                     }
00288                 } finally {
00289                     this.unlock();
00290                 }
00291             }
00292             return result;
00293         }
00294 
00298         @Override
00299         public boolean recoverState() {
00300             boolean result = false;
00301             this.lock();
00302             try {
00303                 this.setState(DNSState.PROBING_1);
00304                 this.setTask(null);
00305             } finally {
00306                 this.unlock();
00307             }
00308             return result;
00309         }
00310 
00314         @Override
00315         public boolean isProbing() {
00316             return this._state.isProbing();
00317         }
00318 
00322         @Override
00323         public boolean isAnnouncing() {
00324             return this._state.isAnnouncing();
00325         }
00326 
00330         @Override
00331         public boolean isAnnounced() {
00332             return this._state.isAnnounced();
00333         }
00334 
00338         @Override
00339         public boolean isCanceling() {
00340             return this._state.isCanceling();
00341         }
00342 
00346         @Override
00347         public boolean isCanceled() {
00348             return this._state.isCanceled();
00349         }
00350 
00354         @Override
00355         public boolean isClosing() {
00356             return this._state.isClosing();
00357         }
00358 
00362         @Override
00363         public boolean isClosed() {
00364             return this._state.isClosed();
00365         }
00366 
00367         private boolean willCancel() {
00368             return this._state.isCanceled() || this._state.isCanceling();
00369         }
00370 
00371         private boolean willClose() {
00372             return this._state.isClosed() || this._state.isClosing();
00373         }
00374 
00378         @Override
00379         public boolean waitForAnnounced(long timeout) {
00380             if (!this.isAnnounced() && !this.willCancel()) {
00381                 _announcing.waitForEvent(timeout);
00382             }
00383             if (!this.isAnnounced()) {
00384                 if (this.willCancel() || this.willClose()) {
00385                     logger.fine("Wait for announced cancelled: " + this);
00386                 } else {
00387                     logger.warning("Wait for announced timed out: " + this);
00388                 }
00389             }
00390             return this.isAnnounced();
00391         }
00392 
00396         @Override
00397         public boolean waitForCanceled(long timeout) {
00398             if (!this.isCanceled()) {
00399                 _canceling.waitForEvent(timeout);
00400             }
00401             if (!this.isCanceled() && !this.willClose()) {
00402                 logger.warning("Wait for canceled timed out: " + this);
00403             }
00404             return this.isCanceled();
00405         }
00406 
00410         @Override
00411         public String toString() {
00412             return (_dns != null ? "DNS: " + _dns.getName() : "NO DNS") + " state: " + _state + " task: " + _task;
00413         }
00414 
00415     }
00416 
00422     public JmDNSImpl getDns();
00423 
00432     public void associateWithTask(DNSTask task, DNSState state);
00433 
00440     public void removeAssociationWithTask(DNSTask task);
00441 
00451     public boolean isAssociatedWithTask(DNSTask task, DNSState state);
00452 
00461     public boolean advanceState(DNSTask task);
00462 
00469     public boolean revertState();
00470 
00476     public boolean cancelState();
00477 
00483     public boolean closeState();
00484 
00490     public boolean recoverState();
00491 
00497     public boolean isProbing();
00498 
00504     public boolean isAnnouncing();
00505 
00511     public boolean isAnnounced();
00512 
00518     public boolean isCanceling();
00519 
00525     public boolean isCanceled();
00526 
00532     public boolean isClosing();
00533 
00539     public boolean isClosed();
00540 
00548     public boolean waitForAnnounced(long timeout);
00549 
00557     public boolean waitForCanceled(long timeout);
00558 
00559 }


zeroconf_jmdns_suite
Author(s): Daniel Stonier
autogenerated on Thu Aug 27 2015 15:50:27