Back to index

nordugrid-arc-nox  1.1.0~rc6
IntraProcessCounter.cpp
Go to the documentation of this file.
00001 // -*- indent-tabs-mode: nil -*-
00002 
00003 #ifdef HAVE_CONFIG_H
00004 #include <config.h>
00005 #endif
00006 
00007 // Counter.cpp
00008 
00009 #include <cstdlib>
00010 
00011 #include "IntraProcessCounter.h"
00012 
00013 namespace Arc {
00014 
00015   IntraProcessCounter::IntraProcessCounter(int limit, int excess)
00016     : limit(limit),
00017       excess(excess),
00018       value(limit),
00019       nextReservationID(1) {
00020     // Nothing else needs to be done.
00021   }
00022 
00023   IntraProcessCounter::IntraProcessCounter(const IntraProcessCounter&)
00024     : Counter() {
00025     // Executing this code should be impossible!
00026     exit(EXIT_FAILURE);
00027   }
00028 
00029   IntraProcessCounter::~IntraProcessCounter() {
00030     // Nothing needs to be done.
00031   }
00032 
00033   void IntraProcessCounter::operator=(const IntraProcessCounter&) {
00034     // Executing this code should be impossible!
00035     exit(EXIT_FAILURE);
00036   }
00037 
00038   int IntraProcessCounter::getLimit() {
00039     return limit;
00040   }
00041 
00042   int IntraProcessCounter::setLimit(int newLimit) {
00043     synchMutex.lock();
00044     value += newLimit - limit;
00045     limit = newLimit;
00046     synchMutex.unlock();
00047     synchCond.signal();
00048     return newLimit;
00049   }
00050 
00051   int IntraProcessCounter::changeLimit(int amount) {
00052     int newLimit;
00053     synchMutex.lock();
00054     newLimit = limit + amount;
00055     value += amount;
00056     limit = newLimit;
00057     synchMutex.unlock();
00058     synchCond.signal();
00059     return newLimit;
00060   }
00061 
00062   int IntraProcessCounter::getExcess() {
00063     return excess;
00064   }
00065 
00066   int IntraProcessCounter::setExcess(int newExcess) {
00067     synchMutex.lock();
00068     excess = newExcess;
00069     synchMutex.unlock();
00070     synchCond.signal();
00071     return newExcess;
00072   }
00073 
00074   int IntraProcessCounter::changeExcess(int amount) {
00075     int newExcess;
00076     synchMutex.lock();
00077     newExcess = excess + amount;
00078     excess += amount;
00079     synchMutex.unlock();
00080     synchCond.signal();
00081     return newExcess;
00082   }
00083 
00084   int IntraProcessCounter::getValue() {
00085     int result;
00086     synchMutex.lock();
00087     result = unsafeGetValue();
00088     synchMutex.unlock();
00089     return result;
00090   }
00091 
00092   CounterTicket IntraProcessCounter::reserve(int amount,
00093                                              Glib::TimeVal duration,
00094                                              bool prioritized,
00095                                              Glib::TimeVal timeOut) {
00096     Glib::TimeVal deadline = getExpiryTime(timeOut);
00097     Glib::TimeVal expiryTime;
00098     IDType reservationID;
00099     synchMutex.lock();
00100     while (amount > unsafeGetValue() + (prioritized ? excess : 0) and
00101            getCurrentTime() < deadline)
00102       synchCond.timed_wait(synchMutex,
00103                            std::min(deadline, unsafeGetNextExpiration()));
00104     if (amount <= unsafeGetValue() + (prioritized ? excess : 0)) {
00105       expiryTime = getExpiryTime(duration);
00106       reservationID = unsafeReserve(amount, expiryTime);
00107     }
00108     else {
00109       expiryTime = HISTORIC;
00110       reservationID = 0;
00111     }
00112     synchMutex.unlock();
00113     return getCounterTicket(reservationID, expiryTime, this);
00114   }
00115 
00116   void IntraProcessCounter::cancel(unsigned long long int reservationID) {
00117     synchMutex.lock();
00118     unsafeCancel(reservationID);
00119     synchMutex.unlock();
00120     synchCond.signal();
00121   }
00122 
00123   void IntraProcessCounter::extend(IDType& reservationID,
00124                                    Glib::TimeVal& expiryTime,
00125                                    Glib::TimeVal duration) {
00126     int amount;
00127     synchMutex.lock();
00128     amount = unsafeCancel(reservationID);
00129     if (amount > 0) {
00130       expiryTime = getExpiryTime(duration);
00131       reservationID = unsafeReserve(amount, expiryTime);
00132     }
00133     else {
00134       expiryTime = HISTORIC;
00135       reservationID = 0;
00136     }
00137     synchMutex.unlock();
00138     synchCond.signal();
00139   }
00140 
00141   int IntraProcessCounter::unsafeGetValue() {
00142     while (unsafeGetNextExpiration() < getCurrentTime()) {
00143       unsafeCancel(selfExpiringReservations.top().getReservationID());
00144       selfExpiringReservations.pop();
00145     }
00146     return value;
00147   }
00148 
00149   int IntraProcessCounter::unsafeCancel(IDType reservationID) {
00150     std::map<IDType, int>::iterator resIter = reservations.find(reservationID);
00151     int amount = 0;
00152     if (resIter != reservations.end()) {
00153       amount = resIter->second;
00154       value += amount;
00155       reservations.erase(resIter);
00156     }
00157     return amount;
00158   }
00159 
00160   Counter::IDType IntraProcessCounter::unsafeReserve(int amount,
00161                                                      Glib::TimeVal expiryTime) {
00162     IDType reservationID = nextReservationID++;
00163     value -= amount;
00164     reservations[reservationID] = amount;
00165     if (expiryTime < ETERNAL)
00166       selfExpiringReservations.push(getExpirationReminder(expiryTime,
00167                                                           reservationID));
00168     return reservationID;
00169   }
00170 
00171   Glib::TimeVal IntraProcessCounter::unsafeGetNextExpiration() {
00172     if (selfExpiringReservations.empty())
00173       return ETERNAL;
00174     else
00175       return selfExpiringReservations.top().getExpiryTime();
00176   }
00177 
00178 }