Roxen.git/server/etc/modules/Roxen.pmod:1:
/*
- * $Id: Roxen.pmod,v 1.3 1999/05/10 23:21:21 grubba Exp $
+ * $Id: Roxen.pmod,v 1.4 1999/05/12 21:42:14 grubba Exp $
*
* Various helper functions.
*
* Henrik Grubbström 1999-05-03
*/
/*
* TODO:
*
* o Quota: Fix support for the index file.
Roxen.git/server/etc/modules/Roxen.pmod:45:
array(string) index_acc;
int acc_scale;
int next_offset;
static class QuotaEntry
{
string name;
int data_offset;
+ static int usage;
static int quota;
static void store()
{
LOCK();
- QD_WRITE(sprintf("QuotaEntry::store(): Quota for %O is now %O\n",
- name, quota));
+ QD_WRITE(sprintf("QuotaEntry::store(): Usage for %O is now %O(%O)\n",
+ name, usage, quota));
data_file->seek(data_offset);
- data_file->write(sprintf("%4c", quota));
+ data_file->write(sprintf("%4c", usage));
UNLOCK();
}
static void read()
{
LOCK();
data_file->seek(data_offset);
string s = data_file->read(4);
- quota = 0;
- sscanf(s, "%4c", quota);
+ usage = 0;
+ sscanf(s, "%4c", usage);
- QD_WRITE(sprintf("QuotaEntry::read(): Quota for %O is %O\n",
- name, quota));
+ QD_WRITE(sprintf("QuotaEntry::read(): Usage for %O is %O(%O)\n",
+ name, usage, quota));
UNLOCK();
}
- void create(string n, int d_o)
+ void create(string n, int d_o, int q)
{
- QD_WRITE(sprintf("QuotaEntry(%O, %O)\n", n, d_o));
+ QD_WRITE(sprintf("QuotaEntry(%O, %O, %O)\n", n, d_o, q));
name = n;
data_offset = d_o;
-
+ quota = q;
read();
}
int check_quota(string uri, int amount)
{
- QD_WRITE(sprintf("QuotaEntry::check_quota(%O, %O): quota:%d\n",
- uri, amount, quota));
+ QD_WRITE(sprintf("QuotaEntry::check_quota(%O, %O): usage:%d(%d)\n",
+ uri, amount, usage, quota));
-
+ if (!quota) {
+ // No quota at all.
+ return 0;
+ }
+
if (amount == 0x7fffffff) {
// Workaround for FTP.
return 1;
}
- return(amount <= quota);
+ return(usage + amount <= quota);
}
int allocate(string uri, int amount)
{
- QD_WRITE(sprintf("QuotaEntry::allocate(%O, %O): quota:%d => %d\n",
- uri, amount, quota, quota - amount));
+ QD_WRITE(sprintf("QuotaEntry::allocate(%O, %O): usage:%d => %d(%d)\n",
+ uri, amount, usage, usage + amount, quota));
- quota -= amount;
+ usage += amount;
store();
- return(quota >= 0);
+ return(usage <= quota);
}
int deallocate(string uri, int amount)
{
return(allocate(uri, -amount));
}
- int get_quota(string uri)
+ int get_usage(string uri)
{
- return quota;
+ return usage;
}
- void set_quota(string uri, int amount)
+ void set_usage(string uri, int amount)
{
- quota = amount;
+ usage = amount;
store();
}
#if !constant(set_weak_flag)
static int refs;
void add_ref()
{
refs++;
Roxen.git/server/etc/modules/Roxen.pmod:151: Inside #if !constant(set_weak_flag)
}
}
static class QuotaProxy
{
static object(QuotaEntry) master;
function(string, int:int) check_quota;
function(string, int:int) allocate;
function(string, int:int) deallocate;
- function(string, int:void) set_quota;
- function(string:int) get_quota;
+ function(string, int:void) set_usage;
+ function(string:int) get_usage;
void create(object(QuotaEntry) m)
{
master = m;
master->add_ref();
check_quota = master->check_quota;
allocate = master->allocate;
deallocate = master->deallocate;
- set_quota = master->set_quota;
- get_quota = master->get_quota;
+ set_usage = master->set_usage;
+ get_usage = master->get_usage;
}
void destroy()
{
master->free_ref();
}
#endif /* !constant(set_weak_flag) */
}
- static object read_entry(int offset)
+ static object read_entry(int offset, int|void quota)
{
- QD_WRITE(sprintf("QuotaDB::read_entry(%O)\n", offset));
+ QD_WRITE(sprintf("QuotaDB::read_entry(%O, %O)\n", offset, quota));
catalog_file->seek(offset);
string data = catalog_file->read(READ_BUF_SIZE);
if (data == "") {
- QD_WRITE(sprintf("QuotaDB::read_entry(%O): At EOF\n", offset));
+ QD_WRITE(sprintf("QuotaDB::read_entry(%O, %O): At EOF\n",
+ offset, quota));
return 0;
}
int len;
int data_offset;
string key;
sscanf(data[..7], "%4c%4c", len, data_offset);
if (len > sizeof(data)) {
Roxen.git/server/etc/modules/Roxen.pmod:205:
if (sizeof(key) != len) {
error(sprintf("Failed to read catalog entry at offset %d.\n"
"len: %d, sizeof(key):%d\n",
offset, len, sizeof(key)));
}
} else {
key = data[8..len-1];
}
- return QuotaEntry(key, data_offset);
+ return QuotaEntry(key, data_offset, quota);
}
static object open(string fname, int|void create_new)
{
object f = Stdio.File();
string mode = create_new?"rwc":"rw";
if (!f->open(fname, mode)) {
error(sprintf("Failed to open quota file %O.\n", fname));
}
Roxen.git/server/etc/modules/Roxen.pmod:254:
{
// FIXME: Actually make an index file.
array(string) new_keys = sort(indices(new_entries_cache));
int prev;
array(int) new_index = ({});
foreach(new_keys, string key) {
int lo;
int hi = sizeof(index_acc);
- while(lo < hi-1) {
+ if (hi) {
+ do {
int probe = (lo + hi)/2;
if (!index_acc[probe]) {
object e = read_entry(index[probe * acc_scale]);
index_acc[probe] = e->name;
}
if (index_acc[probe] < key) {
lo = probe;
} else if (index_acc[probe] > key) {
hi = probe;
} else {
/* Found */
// Shouldn't happen...
break;
}
- }
+ } while(lo < hi-1);
+
if (lo < hi-1) {
// Found...
// Shouldn't happen, but...
// Skip to the next key...
continue;
}
lo *= acc_scale;
hi *= acc_scale;
- while (lo < hi-1) {
+ do {
int probe = (lo + hi)/2;
object e = read_entry(index[probe]);
if (e->name < key) {
lo = probe;
} else if (e->name > key) {
hi = probe;
} else {
/* Found */
// Shouldn't happen...
break;
}
- }
+ } while (lo < hi-1);
if (lo < hi-1) {
// Found...
// Shouldn't happen, but...
// Skip to the next key...
continue;
}
new_index += index[prev..lo] + ({ new_entries_cache[key] });
prev = hi;
-
+ } else {
+ new_index += ({ new_entries_cache[key] });
}
-
+ }
LOCK();
object index_file = open(base + ".index.new", 1);
string to_write = sprintf("%@4c", new_index);
if (index_file->write(to_write) != sizeof(to_write)) {
index_file->close();
rm(base + ".index.new");
} else {
mv(base + ".index.new", base + ".index");
Roxen.git/server/etc/modules/Roxen.pmod:325:
index = new_index;
init_index_acc();
UNLOCK();
foreach(new_keys, string key) {
m_delete(new_entries_cache, key);
}
}
- static object low_lookup(string key)
+ static object low_lookup(string key, int quota)
{
- QD_WRITE(sprintf("QuotaDB::low_lookup(%O)\n", key));
+ QD_WRITE(sprintf("QuotaDB::low_lookup(%O, %O)\n", key, quota));
int cat_offset;
if (!zero_type(cat_offset = new_entries_cache[key])) {
- return read_entry(cat_offset);
+ QD_WRITE(sprintf("QuotaDB::low_lookup(%O, %O): "
+ "Found in new entries cache.\n", key, quota));
+ return read_entry(cat_offset, quota);
}
/* Try the index file. */
/* First use the accellerated index. */
int lo;
int hi = sizeof(index_acc);
- while(lo < hi-1) {
+ if (hi) {
+ do {
int probe = (lo + hi)/2;
if (!index_acc[probe]) {
- object e = read_entry(index[probe * acc_scale]);
+ object e = read_entry(index[probe * acc_scale], quota);
index_acc[probe] = e->name;
if (key == e->name) {
/* Found in e */
QD_WRITE(sprintf("QuotaDB:low_lookup(%O): In acc: Found at %d\n",
key, probe * acc_scale));
return e;
}
}
if (index_acc[probe] < key) {
lo = probe+1;
} else if (index_acc[probe] > key) {
hi = probe;
} else {
/* Found */
QD_WRITE(sprintf("QuotaDB:low_lookup(%O): In acc: Found at %d\n",
key, probe * acc_scale));
- return read_entry(index[probe * acc_scale]);
+ return read_entry(index[probe * acc_scale], quota);
}
- }
+ } while(lo < hi-1);
/* Not in the accellerated index, so go to disk. */
lo *= acc_scale;
hi *= acc_scale;
- while (lo < hi-1) {
+ do {
int probe = (lo + hi)/2;
- object e = read_entry(index[probe]);
+ object e = read_entry(index[probe], quota);
if (e->name < key) {
lo = probe+1;
} else if (e->name > key) {
hi = probe;
} else {
/* Found */
QD_WRITE(sprintf("QuotaDB:low_lookup(%O): Found at %d\n",
key, probe));
return e;
}
-
+ } while (lo < hi-1);
}
QD_WRITE(sprintf("QuotaDB::low_lookup(%O): Not found\n", key));
return 0;
}
object lookup(string key, int quota)
{
QD_WRITE(sprintf("QuotaDB::lookup(%O, %O)\n", key, quota));
Roxen.git/server/etc/modules/Roxen.pmod:409:
if (res = active_objects[key]) {
QD_WRITE(sprintf("QuotaDB::lookup(%O, %O): User in active objects.\n",
key, quota));
#if constant(set_weak_flag)
return res;
#else /* !constant(set_weak_flag) */
return QuotaProxy(res);
#endif /* constant(set_weak_flag) */
}
- if (res = low_lookup(key)) {
+ if (res = low_lookup(key, quota)) {
active_objects[key] = res;
#if constant(set_weak_flag)
return res;
#else /* !constant(set_weak_flag) */
return QuotaProxy(res);
#endif /* constant(set_weak_flag) */
}
QD_WRITE(sprintf("QuotaDB::lookup(%O, %O): New user.\n", key, quota));
Roxen.git/server/etc/modules/Roxen.pmod:432:
data_file->seek(-1);
data_file->read(1);
catalog_file->seek(next_offset);
// We should now be at EOF.
int data_offset = data_file->tell();
// Initialize.
- if (data_file->write(sprintf("%4c", quota)) != 4) {
+ if (data_file->write(sprintf("%4c", 0)) != 4) {
error(sprintf("write() failed for quota data file!\n"));
}
string entry = sprintf("%4c%4c%s", sizeof(key)+8, data_offset, key);
if (catalog_file->write(entry) != sizeof(entry)) {
error(sprintf("write() failed for quota catalog file!\n"));
}
new_entries_cache[key] = next_offset;
next_offset = catalog_file->tell();
if (sizeof(new_entries_cache) > CACHE_SIZE_LIMIT) {
rebuild_index();
}
// low_lookup will always succeed at this point.
- return low_lookup(key);
+ return low_lookup(key, quota);
}
void create(string base_name, int|void create_new)
{
base = base_name;
catalog_file = open(base_name + ".cat", create_new);
data_file = open(base_name + ".data", create_new);
object index_file = open(base_name + ".index", 1);