1 /*****************************************************************************\
3 * Name : memory_limiter *
4 * Author : Chris Koeritz *
6 *******************************************************************************
7 * Copyright (c) 2001-$now By Author. This program is free software; you can *
8 * redistribute it and/or modify it under the terms of the GNU General Public *
9 * License as published by the Free Software Foundation; either version 2 of *
10 * the License or (at your option) any later version. This is online at: *
11 * http://www.fsf.org/copyleft/gpl.html *
12 * Please send any updates to: fred@gruntose.com *
13 \*****************************************************************************/
16 #include "memory_limiter.h"
18 #include <basis/functions.h>
22 using namespace basis;
24 namespace structures {
27 #define LOG(to_print) printf("%s\n", astring(to_print).s())
29 class ml_memory_record
34 ml_memory_record(int initial) : _usage(initial) {}
39 class ml_memory_state_meter : public int_hash<ml_memory_record>
42 ml_memory_state_meter() : int_hash<ml_memory_record>(10) {}
47 memory_limiter::memory_limiter(int overall_limit, int individual_limit)
48 : _overall_limit(overall_limit),
49 _individual_limit(individual_limit),
51 _individual_sizes(new ml_memory_state_meter)
55 memory_limiter::~memory_limiter()
57 WHACK(_individual_sizes);
60 void memory_limiter::reset()
63 _individual_sizes->reset();
66 const int_set &memory_limiter::individuals_listed() const
67 { return _individual_sizes->ids(); }
69 ml_memory_record *memory_limiter::find_individual(int individual) const
71 ml_memory_record *to_return = NULL_POINTER;
72 if (!_individual_sizes->find(individual, to_return)) return NULL_POINTER;
73 // no record for that guy.
77 int memory_limiter::individual_usage(int individual) const
79 ml_memory_record *found = find_individual(individual);
84 int memory_limiter::individual_space_left(int individual) const
86 if (!individual_limit()) return 0;
87 return individual_limit() - individual_usage(individual);
90 astring memory_limiter::text_form(int indent) const
93 astring indentat(' ', indent);
95 astring allowed = overall_limit()?
96 astring(astring::SPRINTF, "%dK", overall_limit() / KILOBYTE)
98 astring avail = overall_limit()?
99 astring(astring::SPRINTF, "%dK", overall_space_left() / KILOBYTE)
102 to_return += astring(astring::SPRINTF, "Overall Limit=%s, Allocations=%dK, "
103 "Free Space=%s", allowed.s(), overall_usage() / KILOBYTE, avail.s());
106 int_set individuals = _individual_sizes->ids();
107 for (int i = 0; i < individuals.elements(); i++) {
108 astring allowed = individual_limit()?
109 astring(astring::SPRINTF, "%dK", individual_limit() / KILOBYTE)
111 astring avail = individual_limit()?
112 astring(astring::SPRINTF, "%dK",
113 individual_space_left(individuals[i]) / KILOBYTE) : "unlimited";
115 to_return += indentat + astring(astring::SPRINTF, "individual %d: "
116 "Limit=%s, Used=%dK, Free=%s", individuals[i], allowed.s(),
117 individual_usage(individuals[i]) / KILOBYTE, avail.s());
120 if (!individuals.elements()) {
121 to_return += indentat + "No allocations owned currently.";
127 bool memory_limiter::okay_allocation(int individual, int memory_desired)
129 FUNCDEF("okay_allocation");
130 // check the overall allocation limits first.
132 && (_overall_size + memory_desired > _overall_limit) ) return false;
133 // now check sanity of this request.
134 if (_individual_limit && (memory_desired > _individual_limit) ) return false;
135 // now check the allocations per user.
136 ml_memory_record *found = find_individual(individual);
138 _individual_sizes->add(individual, new ml_memory_record(0));
139 found = find_individual(individual);
141 LOG("ERROR: adding a new record to the memory state!");
145 if (_individual_limit
146 && (found->_usage + memory_desired > _individual_limit) )
148 found->_usage += memory_desired;
149 _overall_size += memory_desired;
153 bool memory_limiter::record_deletion(int individual, int memory_deleted)
155 if (memory_deleted < 0) return false; // bogus.
156 // make sure the individual exists.
157 ml_memory_record *found = find_individual(individual);
158 if (!found) return false;
159 // the individual must have actually allocated at least that much previously.
160 if (found->_usage < memory_deleted) return false;
161 // okay, we think that's reasonable.
162 found->_usage -= memory_deleted;
163 _overall_size -= memory_deleted;
164 // clean out an empty locker.
165 if (!found->_usage) _individual_sizes->zap(individual);