memory_limiter.cpp

Go to the documentation of this file.
00001 #ifndef MEMORY_LIMITER_IMPLEMENTATION_FILE
00002 #define MEMORY_LIMITER_IMPLEMENTATION_FILE
00003 
00004 /*****************************************************************************\
00005 *                                                                             *
00006 *  Name   : memory_limiter                                                    *
00007 *  Author : Chris Koeritz                                                     *
00008 *                                                                             *
00009 *******************************************************************************
00010 * Copyright (c) 2001-$now By Author.  This program is free software; you can  *
00011 * redistribute it and/or modify it under the terms of the GNU General Public  *
00012 * License as published by the Free Software Foundation; either version 2 of   *
00013 * the License or (at your option) any later version.  This is online at:      *
00014 *     http://www.fsf.org/copyleft/gpl.html                                    *
00015 * Please send any updates to: fred@gruntose.com                               *
00016 \*****************************************************************************/
00017 
00018 #include "int_hash.cpp"
00019 #include "memory_limiter.h"
00020 
00021 #include <basis/function.h>
00022 #include <basis/log_base.h>
00023 
00024 #undef LOG
00025 #define LOG(to_print) CLASS_EMERGENCY_LOG(program_wide_logger(), to_print)
00026 
00027 class ml_memory_record
00028 {
00029 public:
00030   int _usage;
00031 
00032   ml_memory_record(int initial) : _usage(initial) {}
00033 };
00034 
00036 
00037 class ml_memory_state_meter : public int_hash<ml_memory_record>
00038 {
00039 public:
00040   ml_memory_state_meter() : int_hash<ml_memory_record>(10) {}
00041 };
00042 
00044 
00045 memory_limiter::memory_limiter(int overall_limit, int individual_limit)
00046 : _overall_limit(overall_limit),
00047   _individual_limit(individual_limit),
00048   _overall_size(0),
00049   _individual_sizes(new ml_memory_state_meter)
00050 {
00051 }
00052 
00053 memory_limiter::~memory_limiter()
00054 {
00055   WHACK(_individual_sizes);
00056 }
00057 
00058 void memory_limiter::reset()
00059 {
00060   _overall_size = 0;
00061   _individual_sizes->reset();
00062 }
00063 
00064 const int_set &memory_limiter::individuals_listed() const
00065 { return _individual_sizes->ids(); }
00066 
00067 ml_memory_record *memory_limiter::find_individual(int individual) const
00068 {
00069   ml_memory_record *to_return = NIL;
00070   if (!_individual_sizes->find(individual, to_return)) return NIL;
00071     // no record for that guy.
00072   return to_return;
00073 }
00074 
00075 int memory_limiter::individual_usage(int individual) const
00076 {
00077   ml_memory_record *found = find_individual(individual);
00078   if (!found) return 0;
00079   return found->_usage;
00080 }
00081 
00082 int memory_limiter::individual_space_left(int individual) const
00083 {
00084   if (!individual_limit()) return 0;
00085   return individual_limit() - individual_usage(individual);
00086 }
00087 
00088 istring memory_limiter::text_form(int indent) const
00089 {
00090   istring to_return;
00091   istring indentat(' ', indent);
00092 
00093   istring allowed = overall_limit()?
00094       istring(istring::SPRINTF, "%dK", overall_limit() / KILOBYTE)
00095       : "unlimited";
00096   istring avail = overall_limit()?
00097       istring(istring::SPRINTF, "%dK", overall_space_left() / KILOBYTE)
00098       : "unlimited";
00099 
00100   to_return += istring(istring::SPRINTF, "Overall Limit=%s, Allocations=%dK, "
00101       "Free Space=%s", allowed.s(), overall_usage() / KILOBYTE, avail.s());
00102   to_return += log_base::platform_ending();
00103 
00104   int_set individuals = _individual_sizes->ids();
00105   for (int i = 0; i < individuals.elements(); i++) {
00106     istring allowed = individual_limit()?
00107         istring(istring::SPRINTF, "%dK", individual_limit() / KILOBYTE)
00108         : "unlimited";
00109     istring avail = individual_limit()?
00110         istring(istring::SPRINTF, "%dK",
00111         individual_space_left(individuals[i]) / KILOBYTE) : "unlimited";
00112 
00113     to_return += indentat + istring(istring::SPRINTF, "individual %d: "
00114         "Limit=%s, Used=%dK, Free=%s", individuals[i], allowed.s(),
00115         individual_usage(individuals[i]) / KILOBYTE, avail.s());
00116     to_return += log_base::platform_ending();
00117   }
00118   if (!individuals.elements()) {
00119     to_return += indentat + "No allocations owned currently.";
00120     to_return += log_base::platform_ending();
00121   }
00122   return to_return;
00123 }
00124 
00125 bool memory_limiter::okay_allocation(int individual, int memory_desired)
00126 {
00127   FUNCDEF("okay_allocation");
00128   // check the overall allocation limits first.
00129   if (_overall_limit
00130       && (_overall_size + memory_desired > _overall_limit) ) return false;
00131   // now check sanity of this request.
00132   if (_individual_limit && (memory_desired > _individual_limit) ) return false;
00133   // now check the allocations per user.
00134   ml_memory_record *found = find_individual(individual);
00135   if (!found) {
00136     _individual_sizes->add(individual, new ml_memory_record(0));
00137     found = find_individual(individual);
00138     if (!found) {
00139       LOG("ERROR: adding a new record to the memory state!");
00140       return false;
00141     }
00142   }
00143   if (_individual_limit
00144       && (found->_usage + memory_desired > _individual_limit) )
00145     return false; 
00146   found->_usage += memory_desired;
00147   _overall_size += memory_desired;
00148   return true;
00149 }
00150 
00151 bool memory_limiter::record_deletion(int individual, int memory_deleted)
00152 {
00153   if (memory_deleted < 0) return false;  // bogus.
00154   // make sure the individual exists.
00155   ml_memory_record *found = find_individual(individual);
00156   if (!found) return false;
00157   // the individual must have actually allocated at least that much previously.
00158   if (found->_usage < memory_deleted) return false;
00159   // okay, we think that's reasonable.
00160   found->_usage -= memory_deleted;
00161   _overall_size -= memory_deleted;
00162   // clean out an empty locker.
00163   if (!found->_usage) _individual_sizes->zap(individual);
00164   return true;
00165 }
00166 
00167 
00168 #endif //MEMORY_LIMITER_IMPLEMENTATION_FILE
00169 

Generated on Tue Aug 19 04:29:36 2008 for HOOPLE Libraries by  doxygen 1.5.1