1 module hunt.cache.memory;
2 
3 import hunt.cache.cache;
4 import hunt.cache.store;
5 import hunt.cache.nullable;
6 import hunt.cache.Radix;
7 
8 import core.stdc.stdlib;
9 import core.stdc.string;
10 import core.stdc.time;
11 
12 import std.stdio;
13 
14 public:
15 class MemoryCache 
16 {
17 
18 //interface
19 
20 	Nullable!V get(V)(string key)
21 	{
22 		synchronized(this)
23 		{
24 			return get_inter!V(key);
25 		}
26 	}
27 
28 	Nullable!V[string] getall(V)(string[] keys)
29 	{
30 		Nullable!V[string] mapv;
31 		synchronized(this)
32 		{
33 			foreach(k ; keys)
34 			mapv[k] = get_inter!V(k);
35 		}
36 
37 		return mapv;
38 	}
39 
40 	bool containsKey(string key)
41 	{
42 		synchronized(this){
43 			return find_inter(key , true);
44 		}
45 	}
46 	
47 	void put(V)(string key ,  V v , uint expired = 0)
48 	{
49 		synchronized(this)
50 		{
51 			put_inter(key , v , expired);
52 		}
53 	}
54 
55 	bool putifAbsent(V)(string key ,  V v)
56 	{
57 		synchronized(this)
58 		{
59 			if(!find_inter(key , false))
60 			{	
61 				put_inter(key , v , 0);
62 				return true;
63 			}
64 			return false;	
65 		}		
66 	}
67 
68 	void putAll(V)( V[string] maps , uint expired = 0)
69 	{
70 		synchronized(this){
71 			foreach(k , v ; maps)
72 			{
73 				put_inter(k , v , expired);
74 			}
75 		}
76 	}
77 	
78 	bool remove(string key)
79 	{
80 		synchronized(this)
81 		{
82 			return remove_inter(key);
83 		}
84 	}
85 
86 	void removeAll(string[] keys)
87 	{
88 		synchronized(this)
89 		{
90 			foreach( k ; keys)
91 			{
92 				remove_inter(k);
93 			}
94 		}
95 	}
96 
97 	void clear()
98 	{
99 		synchronized(this){
100 			rax_data.Clear();
101 			rax_time.Clear();
102 		}
103 	}
104 
105 	this(string args = "")
106 	{
107 		rax_data = rax.New();
108 		rax_time = rax.New();
109 	}
110 
111 	~this()
112 	{
113 		rax.Free(rax_data);
114 		rax.Free(rax_time);
115 	}
116 
117 protected:
118 
119 	rax *rax_data;
120 	rax *rax_time;
121 
122 	bool find_inter(string key , bool free)
123 	{
124 		Nullable!uint tick = get_inter!uint(rax_time , key);
125 		if(tick.isnull)
126 		{
127 			void *data;
128 			return rax_data.find(cast(ubyte[])key ,data);
129 		}
130 		else{
131 			uint now = cast(uint)time(null);
132 			if( tick.origin < now )
133 			{
134 				if(free)
135 				{
136 					remove_inter(key);
137 				}
138 				return false;
139 			}
140 			else{
141 				return true;
142 			}
143 		}
144 	}
145 
146 	Nullable!V get_inter(V)(string key)
147 	{
148 		Nullable!uint tick =  get_inter!uint(rax_time , key);
149 
150 		if(tick.isnull)	//not set ttl
151 		{
152 			return get_inter!V(rax_data , key);
153 		}
154 		else{
155 			uint now = cast(uint)time(null);
156 			if( tick.origin < now) // remove
157 			{
158 				remove_inter(key);
159 				return Nullable!V.init;
160 			}
161 			else
162 			{
163 				return get_inter!V(rax_data , key);
164 			}
165 		}
166 	}
167 
168 	Nullable!V get_inter(V)(rax *r ,string key)
169 	{
170 		void *data;
171 		if (!r.find(cast(ubyte[])key , data))
172 			return Nullable!V.init;
173 
174 		uint len;
175 		memcpy(&len , data , 4);
176 		byte[] byDatas = new byte[len];
177 		memcpy(byDatas.ptr , data + 4, len);
178 		return DeserializeToObject!V(byDatas);
179 	}
180 
181 	void put_inter(V)(string key , V v , uint expired)
182 	{
183 		if(expired == 0)
184 			put_inter(rax_data , key , v);
185 		else{
186 			put_inter!uint(rax_time , key , expired + cast(uint)time(null));
187 			put_inter(rax_data , key , v);
188 		}
189 	}
190 
191 	void put_inter(V)(rax *r , string key ,  V v)
192 	{
193 		byte[] data = SerializeToByte(v);
194 
195 		void *value = malloc(data.length + 4);
196 		uint len = cast(uint) data.length;
197 		memcpy(value , &len , 4);
198 		memcpy(value + 4 , data.ptr , data.length);
199 		r.Insert(cast(ubyte[])key , value);
200 	}
201 
202 	bool remove_inter(string key)
203 	{
204 		if(rax_data.Remove(cast(ubyte[])key))
205 		{
206 			rax_time.Remove(cast(ubyte[])key);
207 			return true;
208 		}
209 
210 		return false;
211 	}
212 
213 	bool remove_inter(rax *r , string key)
214 	{	
215 		return r.Remove(cast(ubyte[])key);	
216 	}
217 }