ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/freezethaw.C
Revision: 1.5
Committed: Tue Jan 9 21:32:42 2007 UTC (17 years, 5 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.4: +1 -1 lines
Log Message:
- added $cf::WAIT_FOR_TICK*
- tuned map-scheduler and player-scheduler
- added $op->inv_recursive
- added objects_size/objects($index) and actives_size/actives($index)
  for access to the object and actives vector.
- more robust player loader
- removed _perl_data attribute support
- SIGINT/TERM/HUP are now safe as they are handled synchronously.
- replaced LOOK_OBJ by client_visible
- cleanups

File Contents

# Content
1 /*****************************************************************************/
2 /* CrossFire, A roguelike realtime multiplayer game */
3 /*****************************************************************************/
4
5 /*
6 * This code is placed under the GNU General Public Licence (GPL)
7 *
8 * Copyright (C) 2006 by Marc Lehmann <crossfire@schmorp.de>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #include "global.h" // bug in cfperl.h, doesn't include interface_class stuff
26 #include "logger.h"
27 #include "cfperl.h"
28 #include "kw_hash.h"
29
30 object_freezer::object_freezer ()
31 : dynbuf (128 * 1024, 64 * 1024)
32 {
33 av = newAV ();
34 }
35
36 object_freezer::~object_freezer ()
37 {
38 SvREFCNT_dec (av);
39 }
40
41 void
42 object_freezer::put (attachable *ext)
43 {
44 ext->optimise ();
45
46 if (ext->self)
47 {
48 int idx = AvFILLp ((AV *)av) + 1;
49 av_store (av, idx, newRV_inc ((SV *)ext->self));
50
51 add ((void *)"oid ", 4);
52 add ((sint32)idx);
53 add ('\n');
54 }
55 }
56
57 bool
58 object_freezer::save (const char *path)
59 {
60 CALL_BEGIN (3);
61 CALL_ARG_SV (newSVpv (path, 0));
62 CALL_ARG_SV (newRV_noinc (newSVpvn ((char *)linearise (), size ())));
63 CALL_ARG_SV (newRV_inc ((SV *)av));
64 CALL_CALL ("cf::object_freezer_save", G_VOID | G_DISCARD);
65 CALL_END;
66 }
67
68 char *
69 object_freezer::as_string ()
70 {
71 CALL_BEGIN (2);
72 CALL_ARG_SV (newRV_noinc (newSVpvn ((char *)linearise (), size ())));
73 CALL_ARG_SV (newRV_inc ((SV *)av));
74 CALL_CALL ("cf::object_freezer_as_string", G_SCALAR);
75
76 char *res = count > 0
77 ? strdup (SvPVX (POPs))
78 : strdup ("[fatal error]");
79
80 CALL_END;
81
82 return res;
83 }
84
85 int
86 fprintf (object_freezer &freezer, const char *format, ...)
87 {
88 va_list ap;
89
90 va_start (ap, format);
91
92 int len = vsnprintf ((char *)freezer.force (1024), 1024, format, ap);
93
94 if (len >= 0)
95 freezer.alloc (len);
96
97 va_end (ap);
98 }
99
100 int
101 fputs (const char *s, object_freezer &freezer)
102 {
103 freezer.add (s);
104 }
105
106 static const char thawer_eof[] = "\n\n\n\0\0\0";
107
108 object_thawer::object_thawer (const char *path)
109 : name (strdup (path))
110 {
111 static const char eof[] = "\n\n\n\0\0\0";
112
113 av = 0;
114 text = 0;
115 line = 0;
116
117 if (path)
118 {
119 CALL_BEGIN (1);
120 CALL_ARG_SV (newSVpv (path, 0));
121 CALL_CALL ("cf::object_thawer_load", G_ARRAY);
122
123 if (count == 2)
124 {
125 // second value - perl objects
126 {
127 SV *sv = POPs;
128 if (SvROK (sv))
129 av = (AV *)SvREFCNT_inc (SvRV (sv));
130 }
131
132 // first value - text part, pad with 3 zeroes
133 {
134 SV *sv = POPs;
135 STRLEN len;
136 char *sv_ = SvPVbyte (sv, len);
137 text = newSV (len + sizeof (eof));
138 SvCUR_set (text, len);
139 memcpy (SvPVX (text), sv_, len);
140 memcpy (SvEND (text), eof, sizeof (eof)); // just to be sure
141
142 line = SvPVX (text);
143 }
144 }
145
146 CALL_END;
147 }
148 }
149
150 object_thawer::object_thawer (const char *data, AV *perlav)
151 : name (strdup ("(memory stream"))
152 {
153 av = perlav;
154 text = newSVpv (data, 0);
155 sv_catpv (text, thawer_eof);
156 line = SvPVbyte_nolen (text);
157 }
158
159 void
160 object_thawer::get (attachable *obj, int oid)
161 {
162 if (!av || oid < 0) // this is actually an error of sorts
163 return;
164
165 SV **svp = av_fetch ((AV *)av, oid, 0);
166
167 if (!svp || !SvROK (*svp))
168 {
169 printf ("trying to thaw duplicate or never-issued oid %d, ignoring.\n", oid);
170 return;
171 }
172
173 if (!SvROK (*svp))
174 {
175 LOG (llevError, "deserialised perl object is not an RV");
176 return;
177 }
178
179 HV *hv = (HV *)SvRV (*svp);
180
181 if (SvTYPE (hv) != SVt_PVHV)
182 {
183 LOG (llevError, "deserialised perl object is not a PVHV");
184 return;
185 }
186
187 if (obj->self)
188 {
189 // the hard way(?)
190
191 // the dirty blues: "just" swap the XPVHV's
192 swap (SvANY (obj->self), SvANY (hv));
193
194 // do not swap magic, though
195 swap (SvMAGIC (obj->self), SvMAGIC (hv));
196 }
197 else
198 {
199 // the easy way(?)
200
201 obj->self = hv;
202 SvRV_set (*svp, &PL_sv_undef);
203
204 sv_magicext ((SV *)obj->self, 0, PERL_MAGIC_ext, &attachable::vtbl, (char *)obj, 0);
205
206 // borrow a refcount for the perl object
207 obj->flags |= attachable::F_BORROWED;
208 obj->refcnt_dec ();
209 }
210
211 obj->reattach ();
212 }
213
214 object_thawer::~object_thawer ()
215 {
216 if (text) SvREFCNT_dec (text);
217 if (av) SvREFCNT_dec (av);
218
219 free ((void *)name);
220 }
221
222 char *
223 fgets (char *s, int n, object_thawer &thawer)
224 {
225 char *p = thawer.line;
226 char *q = s;
227
228 if (!p)
229 return 0;
230
231 while (--n)
232 {
233 if (!*p)
234 break;
235
236 *q++ = *p;
237
238 if (*p++ == '\n')
239 break;
240 }
241
242 *q = 0;
243 thawer.line = p;
244
245 return s == q ? 0 : s;
246 }
247
248 keyword
249 object_thawer::get_kv ()
250 {
251 if (!line)
252 return KW_EOF;
253
254 for (;;)
255 {
256 char *p = line;
257
258 if (!*p)
259 return KW_EOF;
260
261 // parse keyword
262 while (*p > ' ')
263 p++;
264
265 int klen = p - line;
266
267 if (*p++ != '\n')
268 {
269 // parse value
270 while (*(unsigned char *)p <= ' ' && *p != '\n') // skip 0x01 .. 0x20
271 ++p;
272
273 last_value = p;
274
275 while (*p != '\n')
276 p++;
277
278 *p++ = 0;
279 }
280 else
281 last_value = 0;
282
283 line [klen] = 0;
284 keyword_idx *kw = kw_lex::match (line, klen);
285
286 //printf ("KV %d<%s,%s>\n", kw ? kw->index : 0, line, last_value);//D
287
288 last_keyword = line;
289 line = p;
290
291 if (kw)
292 return kw->index;
293 else if (!*last_keyword || *last_keyword == '#')
294 ; // empty/comment line
295 else
296 return KW_ERROR;
297 }
298 }
299
300 void
301 object_thawer::skip_kv (keyword kw)
302 {
303 shstr ml;
304
305 switch (kw)
306 {
307 case KW_msg: get_ml (KW_endmsg , ml); break;
308 case KW_lore: get_ml (KW_endlore , ml); break;
309 case KW_maplore: get_ml (KW_endmaplore, ml); break;
310 }
311 }
312
313 void
314 object_thawer::get (shstr &sh) const
315 {
316 if (last_value)
317 sh = last_value;
318 else
319 {
320 sh = "<value missing>";
321 LOG (llevError, "keyword \"%s\" requires value, substituting with <value missing>\n", last_keyword);//TODO: add filename
322 }
323 }
324
325 void
326 object_thawer::get_ml (keyword kend, shstr &sh)
327 {
328 char kw[128];
329
330 int klen = keyword_len [kend];
331
332 kw [0] = '\n';
333 memcpy (kw + 1, keyword_str [kend], klen);
334 kw [klen + 1] = '\n';
335 kw [klen + 2] = 0;
336
337 // first test for completely empty msg... "endXXX\n"
338 if (!strncmp (line, kw + 1, klen + 1))
339 {
340 sh = 0;
341
342 line += klen + 1;
343
344 return;
345 }
346 else
347 {
348 // multi-line strings are delimited by "\nendXXX\n" or "endXXX\n" (NULL)
349
350 char *end = strstr (line, kw);
351
352 if (!end)
353 {
354 sh = 0;
355 return;
356 }
357
358 *end = 0;
359 sh = line;
360
361 line = end + keyword_len [kend] + 1;
362
363 while (*line++ != '\n')
364 ;
365 }
366 }
367
368 sint32
369 object_thawer::get_sint32 () const
370 {
371 char *p = last_value;
372
373 if (!p)
374 return 0;
375
376 sint32 val = 0;
377 bool negate;
378
379 if (*p == '-')
380 {
381 negate = true;
382 ++p;
383 }
384 else
385 negate = false;
386
387 do
388 {
389 val *= 10;
390 val += *p++ - '0';
391 }
392 while (*p);
393
394 return negate ? -val : val;
395 }
396
397 sint64
398 object_thawer::get_sint64 () const
399 {
400 return last_value ? atoll (last_value) : 0;
401 }
402
403 double
404 object_thawer::get_double () const
405 {
406 return last_value ? atof (last_value) : 0;
407 }
408