1
  
2
  
3
  
4
  
5
  
6
  
7
  
8
  
9
  
10
  
11
  
12
  
13
  
14
  
15
  
16
  
17
  
18
  
19
  
20
  
21
  
22
  
23
  
24
  
25
  
26
  
27
  
28
  
29
  
30
  
31
  
32
  
33
  
34
  
35
  
36
  
37
  
38
  
39
  
40
  
41
  
42
  
43
  
44
  
45
  
46
  
47
  
48
  
49
  
50
  
51
  
52
  
53
  
54
  
55
  
56
  
57
  
58
  
59
  
60
  
61
  
62
  
63
  
64
  
65
  
66
  
67
  
68
  
69
  
70
  
71
  
72
  
73
  
74
  
75
  
76
  
77
  
78
  
79
  
80
  
81
  
82
  
83
  
84
  
85
  
86
  
87
  
88
  
89
  
90
  
91
  
92
  
93
  
94
  
95
  
96
  
97
  
98
  
99
  
100
  
101
  
102
  
103
  
104
  
105
  
106
  
107
  
108
  
109
  
110
  
111
  
112
  
113
  
114
  
115
  
116
  
117
  
118
  
119
  
120
  
/* 
 * A RAM-based storage manager. 
 * by Francesco Chemolli <kinkie@roxen.com> 
 * (C) 2000 Roxen IS 
 * 
 * $Id: Memory.pike,v 1.1 2000/07/02 20:15:57 kinkie Exp $ 
 * 
 * This storage manager provides the means to save data to memory. 
 * In this manager I'll add reference documentation as comments to 
 * interfaces. It will be organized later in a more comprehensive format 
 * 
 * Settings will be added later. 
 */ 
 
class Data { 
 
  inherit Cache.Data; 
   
  int _size=0; 
  mixed _data=0; 
   
  void create(void|mixed value, void|int abs_expire_time,  
              void|float preciousness) { 
    _data=value; 
    atime=ctime=time(1); 
    if (abs_expire_time) etime=abs_expire_time; 
    if (preciousness) cost=preciousness; 
  } 
   
  int size() { 
    if (_size) return _size; 
    return (_size=recursive_low_size(_data)); 
  } 
   
  mixed data() { 
    return _data; 
  } 
   
} 
 
inherit Cache.Storage.Base; 
 
private mapping(string:mixed) data=([]); 
 
 
/* 
 * First an iterator over the contents. 
 * Since accesses to the data are not serialized to increase efficiency 
 * there are a few guidelines that must be followed in order to maintain 
 * consistency. 
 * 
 * First off, only one entity must be using the iterator at one time. 
 * That's not as bad as it seems, as the only entity needing to enumerate 
 * the entries in cache is the expiration policy manager, and there can 
 * be only one for each storage manager. 
 * 
 * The enumerator over the cache is initialized by a call to first(). 
 * Subsequent calls to next() return following entries in the cache. 
 * While it is guarranteed that each and all entries in the cache  
 * will be iterated upon by the enumerator, their order is NOT guarranteed 
 * to remain consistent across calls. 
 */ 
 
// these are used by the enumerator. While entries might be deleted while 
// enumerating, it won't bite us. 
private array(string) iter=0; 
private int current=0; 
 
int(0..0)|string first() { 
  iter=indices(data); 
  current=0; 
  return next(); 
} 
 
int(0..0)|string next() { 
  if (iter && current < sizeof(iter)) 
    return iter[current++]; 
  iter=0; 
  return 0; 
} 
 
/* 
 * Guess what these do? 
 * I leave the data-object creation here, so that the storage manager 
 * can choose whatever data-class it pleases 
 */ 
void set(string key, mixed value, 
         void|int absolute_expire,  
         void|float preciousness) { 
  data[key]=Data(value,absolute_expire,preciousness); 
} 
 
// fetches some data from the cache. If notouch is set, don't touch the 
// data from the cache (meant to be used by the storage manager only) 
int(0..0)|Cache.Data get(string key, void|int notouch) { 
  mixed tmp; 
  tmp=data[key]; 
  if (!notouch && tmp) tmp->touch(); 
  return tmp; 
} 
 
void aget(string key,  
          function(string,int(0..0)|Cache.Data:void) callback) { 
  mixed rv=get(key); 
  callback(key,rv); 
} 
 
Cache.Data|int(0..0) delete(string key, void|int(0..1) hard) { 
  object(Cache.Data) rv=data[key]; 
  if (hard) { 
    destruct(rv->value()); 
    m_delete(data,key); 
    return 0; 
  } 
  m_delete(data,key); 
  return rv; 
}