1 // This may look like C code, but it is really -*- C++ -*-
2
3 // ------------------------------------------------------------------
4 // The Goldware Library
5 // Copyright (C) 1990-1999 Odinn Sorensen
6 // Copyright (C) 1999-2000 Alex. S. Aganichev
7 // ------------------------------------------------------------------
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Library General Public
10 // License as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
12 //
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Library General Public License for more details.
17 //
18 // You should have received a copy of the GNU Library General Public
19 // License along with this program; if not, write to the Free
20 // Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 // MA 02111-1307, USA
22 // ------------------------------------------------------------------
23 // $Id: gmohuds2.cpp,v 1.6 2011/12/17 21:46:02 stas_degteff Exp $
24 // ------------------------------------------------------------------
25 // Hudson / Goldbase msgbase handling
26 // ------------------------------------------------------------------
27
28
29 // ------------------------------------------------------------------
30
31 template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
raw_close()32 void _HudsWide<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::raw_close()
33 {
34 GFTRK("HudsRawClose");
35
36 fhtxt.Close();
37 fhhdr.Close();
38 fhidx.Close();
39 fhinf.Close();
40 fhlrd.Close();
41 fhtoi.Close();
42 fhusr.Close();
43
44 GFTRK(0);
45 }
46
47
48 // ------------------------------------------------------------------
49
50 template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
test_open(gfile & __file,const char * __fname,int __oaccess)51 void _HudsWide<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::test_open(gfile &__file, const char* __fname, int __oaccess)
52 {
53 GFTRK("HudsTestOpen");
54
55 long _tries = 0;
56 __oaccess |= O_RDWR|O_BINARY;
57
58 do
59 {
60 Path _testfn;
61 strcpy(_testfn, AddPath(path, __fname));
62 int _omode = (__oaccess & O_CREAT) ? S_STDRW : S_STDRD;
63
64 __file.Open(_testfn, __oaccess, WideSharemode, _omode);
65 if (!__file.isopen())
66 {
67 if (errno == ENOENT)
68 {
69 if (_tries == 0)
70 {
71 __oaccess |= O_CREAT;
72 _tries++;
73 continue;
74 }
75 }
76
77 // Request the other program to unlock
78 if (errno != ENOENT)
79 TouchFile(AddPath(path, "mbunlock.now"));
80
81 // Tell the world
82 if (PopupLocked(++_tries, false, _testfn) == false)
83 {
84 // User requested to exit
85 WideLog->ErrOpen();
86 raw_close();
87 WideLog->printf("! A %s msgbase file could not be opened.", __HUDSON ? HUDS_NAME : GOLD_NAME);
88 WideLog->printf(": %s.", _testfn);
89 WideLog->ErrOSInfo();
90 OpenErrorExit();
91 }
92 }
93 }
94 while (!__file.isopen());
95
96 // Remove the popup window
97 if (_tries)
98 PopupLocked(0, 0, NULL);
99
100 GFTRK(0);
101 }
102
103
104 // ------------------------------------------------------------------
105
106 template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
raw_open(int __oaccess,int __all)107 void _HudsWide<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::raw_open(int __oaccess, int __all) {
108
109 GFTRK("HudsRawOpen");
110
111 test_open(fhidx, __HUDSON ? "msgidx" HUDS_EXT : "msgidx" GOLD_EXT, __oaccess);
112 test_open(fhinf, __HUDSON ? "msginfo" HUDS_EXT : "msginfo" GOLD_EXT, __oaccess);
113 test_open(fhlrd, __HUDSON ? "lastread" HUDS_EXT : "lastread" GOLD_EXT, __oaccess);
114 test_open(fhtoi, __HUDSON ? "msgtoidx" HUDS_EXT : "msgtoidx" GOLD_EXT, __oaccess);
115 if (__all)
116 {
117 test_open(fhhdr, __HUDSON ? "msghdr" HUDS_EXT : "msghdr" GOLD_EXT, __oaccess);
118 test_open(fhtxt, __HUDSON ? "msgtxt" HUDS_EXT : "msgtxt" GOLD_EXT, __oaccess);
119 test_open(fhusr, __HUDSON ? "users" HUDS_EXT : "users" GOLD_EXT, __oaccess);
120 }
121
122 GFTRK(0);
123 }
124
125
126 // ------------------------------------------------------------------
127
128 template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
raw_open_scan()129 void _HudsWide<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::raw_open_scan() {
130
131 GFTRK("HudsRawOpenScan");
132
133 raw_open(0, false);
134
135 GFTRK(0);
136 }
137
138
139 // ------------------------------------------------------------------
140
141 template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
refresh()142 void _HudsWide<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::refresh() {
143
144 GFTRK("HudsRefresh");
145
146 // (Re)Allocate memory to hold the complete MSGIDX.BBS/DAT
147 msgidxsize = fhidx.FileLength();
148 msgidxptr = (HudsIdx*)throw_realloc(msgidxptr, (uint)(msgidxsize+sizeof(HudsIdx)));
149
150 // Load MSGIDX.BBS/DAT
151 fhidx.LseekSet(0);
152 fhidx.Read(msgidxptr, (uint)msgidxsize);
153
154 // Load MSGINFO.BBS/DAT
155 fhinf.LseekSet(0);
156 fhinf.Read(&msginfo, sizeof(HudsInfo));
157
158 // Load LASTREAD.BBS/DAT
159 fhlrd.LseekSet(userno*sizeof(HudsLast));
160 fhlrd.Read(lastrec, sizeof(HudsLast));
161
162 GFTRK(0);
163 }
164
165
166 // ------------------------------------------------------------------
167
168 template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
open()169 void _HudsWide<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::open() {
170
171 GFTRK("HudsWideOpen");
172
173 isopen = 1;
174 iswideopen = true;
175 ispmscanned = false;
176 iswidescanned = false;
177 raw_open_scan();
178 lock();
179
180 GFTRK(0);
181 }
182
183
184 // ------------------------------------------------------------------
185
186 template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
close()187 void _HudsWide<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::close() {
188
189 GFTRK("HudsWideClose");
190
191 unlock();
192 raw_close();
193 throw_release(msgidxptr);
194 throw_release(pmscan);
195 throw_release(scn);
196 iswideopen = false;
197 isopen = 0;
198
199 GFTRK(0);
200 }
201
202
203 // ------------------------------------------------------------------
204
205 template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
lock()206 void _HudsWide<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::lock() {
207
208 GFTRK("HudsLock");
209
210 if(not islocked and WideCanLock) {
211
212 long _tries = 0;
213
214 // Try to get the lock
215 while (fhinf.Lock(sizeof(HudsInfo)+1, 1) == -1)
216 {
217 // Tell the world
218 if(PopupLocked(++_tries, true, AddPath(path, __HUDSON ? "msginfo" HUDS_EXT : "msginfo" GOLD_EXT)) == false) {
219
220 // User requested to exit
221 WideLog->ErrLock();
222 raw_close();
223 WideLog->printf("! A %s msgbase file could not be locked.", __HUDSON ? HUDS_NAME : GOLD_NAME);
224 WideLog->printf(": %smsginfo%s.", path, __HUDSON ? HUDS_EXT : GOLD_EXT);
225 WideLog->ErrOSInfo();
226 LockErrorExit();
227 }
228
229 // Request the other program to unlock
230 TouchFile(AddPath(path, "mbunlock.now"));
231 }
232
233 // Remove the popup window
234 if(_tries)
235 PopupLocked(0, 0, NULL);
236
237 // We got the lock
238 islocked = true;
239 }
240
241 // Refresh msgbase data
242 refresh();
243
244 GFTRK(0);
245 }
246
247
248 // ------------------------------------------------------------------
249
250 template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
unlock()251 void _HudsWide<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::unlock() {
252
253 GFTRK("HudsUnlock");
254
255 if (islocked and WideCanLock)
256 {
257 fhinf.Unlock(sizeof(HudsInfo)+1, 1);
258 islocked = false;
259 }
260
261 GFTRK(0);
262 }
263
264
265 // ------------------------------------------------------------------
266
267 template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
lock()268 void _HudsArea<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::lock() {
269
270 wide->lock();
271 }
272
273
274 // ------------------------------------------------------------------
275
276 template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
unlock()277 void _HudsArea<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::unlock() {
278
279 wide->unlock();
280 }
281
282
283 // ------------------------------------------------------------------
284
285 template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
scan()286 void _HudsWide<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::scan() {
287
288 GFTRK("HudsWideScan");
289
290 iswidescanned = true;
291
292 // Alloc scan array
293 throw_free(scn);
294 scn = (HudsScan*)throw_calloc((__HUDSON ? HUDS_MAXBOARD : GOLD_MAXBOARD), sizeof(HudsScan));
295
296 // Board and scan array pointer
297 register int _board;
298 register HudsScan* _scan = scn;
299
300 // Init wide scan array
301 _board = 0;
302 while(_board < (__HUDSON ? HUDS_MAXBOARD : GOLD_MAXBOARD)) {
303 _scan->active = msginfo.active[_board];
304 _scan->lastread = lastrec[_board];
305 _board++;
306 _scan++;
307 }
308
309 // Setup MSGIDX pointer and counters
310 register HudsIdx* _msgidx_ptr = msgidxptr;
311 register uint _msgidx_count = 0;
312 register uint _msgidx_total = (uint)(msgidxsize/sizeof(HudsIdx));
313 int _invalidboards = 0;
314
315 // Scan the index
316 while(_msgidx_count < _msgidx_total) {
317
318 // Is the msg not deleted?
319 if(_msgidx_ptr->msgno != (__HUDSON ? HUDS_DELETEDMSGNO : GOLD_DELETEDMSGNO)) {
320
321 register int _idxboard = _msgidx_ptr->board;
322 if(_idxboard and (_idxboard <= (__HUDSON ? HUDS_MAXBOARD : GOLD_MAXBOARD))) {
323
324 _scan = scn + (_idxboard - 1);
325
326 // Get message number
327 _scan->lastmsgno = _msgidx_ptr->msgno;
328 _scan->count++;
329
330 // Set first message number
331 if(not _scan->firstmsgno)
332 _scan->firstmsgno = _scan->lastmsgno;
333
334 // Set lastread pointer
335 if((_scan->lastmsgno >= _scan->lastread) and (_scan->lastreadreln == 0)) {
336 _scan->lastreadfound = _scan->lastmsgno;
337 _scan->lastreadreln = _scan->count - (_scan->lastmsgno != _scan->lastread ? 1 : 0);
338 }
339 }
340 else {
341 _invalidboards++;
342 }
343 }
344
345 // Go to next record
346 _msgidx_count++;
347 _msgidx_ptr++;
348 }
349
350 if(_invalidboards) {
351 WideLog->printf("! Found %u msgs with an invalid board number (0 or >%u).", _invalidboards, (__HUDSON ? HUDS_MAXBOARD : GOLD_MAXBOARD));
352 WideLog->printf("! In the %s msgbase at %s.", __HUDSON ? HUDS_NAME : GOLD_NAME, path);
353 WideLog->printf(": Info: Your msgbase may be partially corrupted.");
354 WideLog->printf("+ Advice: Run a msgbase index rebuild/recover utility.");
355 }
356
357 // Check/fix boards
358 _board = 0;
359 _scan = scn;
360 while(_board < (__HUDSON ? HUDS_MAXBOARD : GOLD_MAXBOARD)) {
361
362 // Check/fix lastreads
363 if(_scan->count and (_scan->lastreadfound != _scan->lastread)) {
364 if(_scan->lastread > _scan->lastmsgno)
365 _scan->lastreadreln = _scan->count;
366 else if(_scan->lastread < _scan->firstmsgno)
367 _scan->lastreadreln = 0;
368 }
369
370 if(WideDebug) {
371 WideLog->printf("- b:%u: t:%u, l:%u, fm:%u, hm:%u, lr:%u, u:%u",
372 _board,
373 _scan->count,
374 _scan->lastreadreln,
375 _scan->firstmsgno,
376 _scan->lastmsgno,
377 _scan->lastread,
378 userno
379 );
380 }
381
382 // Check active message count and log it if different
383 if(_scan->active != _scan->count) {
384 WideLog->printf("! Counted %u active msgs in %s board %u.", _scan->count, __HUDSON ? HUDS_NAME : GOLD_NAME, _board+1);
385 WideLog->printf("! According to msginfo%s there should be %u active msgs.", __HUDSON ? HUDS_EXT : GOLD_EXT, _scan->active);
386 WideLog->printf(": Info: A program did not update msginfo%s correctly.", __HUDSON ? HUDS_EXT : GOLD_EXT);
387 WideLog->printf("+ Advice: Run a msgbase index rebuild utility.");
388 }
389
390 _board++;
391 _scan++;
392 }
393
394 GFTRK(0);
395 }
396
397
398 // ------------------------------------------------------------------
399
400 template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
raw_scan(int __keep_index)401 void _HudsArea<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::raw_scan(int __keep_index) {
402
403 GFTRK("HudsRawScan");
404
405 if(!wide)
406 wide = (HudsWide*) (__HUDSON ? (void *)hudsonwide : (void *)goldbasewide);
407
408 if(wide->iswideopen and not wide->iswidescanned)
409 wide->scan();
410
411 // Get wide scan data if any
412 if(wide->scn) {
413
414 // Update area data
415 register HudsScan* _scan = wide->scn + (board() - 1);
416 Msgn->SetCount(_scan->count);
417 lastread = _scan->lastreadreln;
418 lastreadentry = _scan->lastreadfound;
419 }
420 else {
421
422 // Open the msgbase if it wasn't already
423 int _was_open = wide->isopen;
424 if(not _was_open)
425 wide->open();
426
427 // Get the number of active msgs in the area
428 register board_t _board = (board_t)board();
429 register uint _active = wide->msginfo.active[_board-1];
430 register msgn_t _lastread = wide->lastrec[_board-1];
431
432 // Setup pointers and counts
433 register uint _msg_count = 0;
434 register HudsIdx* _msgidx_ptr = wide->msgidxptr;
435 register uint _msgidx_count = 0;
436 register uint _msgidx_total = (uint)(wide->msgidxsize/sizeof(HudsIdx));
437 register uint _lastread_reln = 0;
438
439 // (Re)Allocate index
440 if(__keep_index)
441 Msgn->Resize(_active);
442
443 // Index pointers
444 uint32_t* _msgno_ptr = Msgn->tag;
445
446 // Fill index
447 uint _firstmsgno = 0;
448 uint _lastmsgno = 0;
449 uint _lastreadfound = 0;
450 while(_msgidx_count < _msgidx_total) {
451
452 // Is it our board and is the msg not deleted?
453 if((_msgidx_ptr->board == _board) and (_msgidx_ptr->msgno != (__HUDSON ? HUDS_DELETEDMSGNO : GOLD_DELETEDMSGNO))) {
454
455 // Get message number
456 _lastmsgno = _msgidx_ptr->msgno;
457 _msg_count++;
458
459 // Set first message number
460 if(not _firstmsgno)
461 _firstmsgno = _lastmsgno;
462
463 // Transfer data to the index
464 if(__keep_index)
465 *_msgno_ptr++ = _lastmsgno;
466
467 // Set lastread pointer
468 if((_lastmsgno >= _lastread) and (_lastread_reln == 0)) {
469 _lastreadfound = _lastmsgno;
470 _lastread_reln = _msg_count - (_lastmsgno != _lastread ? 1 : 0);
471 }
472
473 // Break loop as soon as we have all we need
474 if(_msg_count == _active)
475 break;
476 }
477
478 // Go to next record
479 _msgidx_count++;
480 _msgidx_ptr++;
481 }
482
483 // If the exact lastread was not found
484 if(_msg_count and (_lastreadfound != _lastread)) {
485
486 // Higher than highest or lower than lowest?
487 if(_lastread > _lastmsgno)
488 _lastread_reln = _msg_count;
489 else if(_lastread < _firstmsgno)
490 _lastread_reln = 0;
491 }
492
493 // Check active message count and log it if different
494 if(_active != _msg_count) {
495 WideLog->printf("! Counted %u active msgs in %s board %u (%s).", _msg_count, __HUDSON ? HUDS_NAME : GOLD_NAME, board(), echoid());
496 WideLog->printf("! According to msginfo%s there should be %u active msgs.", __HUDSON ? HUDS_EXT : GOLD_EXT, _active);
497 WideLog->printf(": Info: A program did not update msginfo%s correctly.", __HUDSON ? HUDS_EXT : GOLD_EXT);
498 WideLog->printf("+ Advice: Run a msgbase index rebuild utility.");
499 }
500
501 // Update area data
502 Msgn->SetCount(_msg_count);
503 lastread = _lastread_reln;
504 lastreadentry = _lastreadfound;
505
506 if(WideDebug) {
507 WideLog->printf("- b:%u: t:%u, l:%u, fm:%u, hm:%u, lr:%u, u:%u",
508 board(),
509 Msgn->Count(),
510 lastread,
511 _firstmsgno,
512 _lastmsgno,
513 _lastread,
514 wide->userno
515 );
516 }
517
518 // Close the msgbase again if we opened it in here
519 if(not _was_open)
520 wide->close();
521 }
522
523 GFTRK(0);
524 }
525
526
527 // ------------------------------------------------------------------
528
529 template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
scan()530 void _HudsArea<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::scan() {
531
532 GFTRK("HudsScan");
533
534 raw_scan(true);
535
536 GFTRK(0);
537 }
538
539
540 // ------------------------------------------------------------------
541
542 template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
scan_area()543 void _HudsArea<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::scan_area() {
544
545 GFTRK("HudsScanArea");
546
547 raw_scan(false);
548
549 GFTRK(0);
550 }
551
552
553 // ------------------------------------------------------------------
554
555 #define HudsIdxCmp(a,b) ((a.board-b.board != 0) ? a.board-b.board : ((int)(a.msgno-b.msgno)))
556
557
558 // ------------------------------------------------------------------
559
560 #define TOIDXBUFSZ 100u
561 #define PMSCANBUFSZ 50u
562
563 template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
realloc_pm_scan()564 void _HudsWide<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::realloc_pm_scan() {
565
566 pmscan = (HudsIdx*)throw_realloc(pmscan, (pmscantotal+PMSCANBUFSZ)*sizeof(HudsIdx));
567 }
568
569
570 // ------------------------------------------------------------------
571
572 template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
scan_pm()573 void _HudsWide<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::scan_pm() {
574
575 GFTRK("HudsWideScanPM");
576
577 if(not iswidescanned)
578 scan();
579
580 ispmscanned = true;
581
582 HudsToIdx* toidxbuf = (HudsToIdx*)throw_calloc(TOIDXBUFSZ, sizeof(HudsToIdx));
583 uint totrecs = (uint)(fhtoi.FileLength() / sizeof(HudsToIdx));
584 HudsIdx* idxptr = msgidxptr;
585 throw_release(pmscan);
586 pmscantotal = 0;
587 int invalidboards = 0;
588 int gotpm, idxboard, umax, u;
589 uint getrecs, rec;
590 HudsToIdx* toidx;
591
592 do {
593
594 rec = 0;
595 gotpm = false;
596 getrecs = MinV(TOIDXBUFSZ, totrecs);
597 fhtoi.Read(toidxbuf, getrecs*sizeof(HudsToIdx));
598
599 for(toidx=toidxbuf; rec<getrecs; idxptr++,toidx++,rec++) {
600
601 // Skip deleted msgs
602 if(idxptr->msgno == (__HUDSON ? HUDS_DELETEDMSGNO : GOLD_DELETEDMSGNO))
603 continue;
604
605 // Skip msgs in invalid boards
606 idxboard = idxptr->board;
607 if(not (idxboard and (idxboard <= (__HUDSON ? HUDS_MAXBOARD : GOLD_MAXBOARD)))) {
608 invalidboards++;
609 continue;
610 }
611
612 // If after lastread
613 if(idxptr->msgno <= scn[idxboard-1].lastreadfound)
614 continue;
615
616 // Convert name string
617 strnp2c(toidx->name, sizeof(HudsToIdx)-1);
618
619 // Is it a PM?
620 umax = (WidePersonalmail & PM_ALLNAMES) ? WideUsernames : 1;
621 for(u=0; u<umax; u++) {
622 if(strieql(toidx->name, WideUsername[u])) {
623 gotpm = true;
624 break;
625 }
626 }
627
628 if(gotpm) {
629 if((pmscantotal % PMSCANBUFSZ) == 0)
630 realloc_pm_scan();
631 pmscan[pmscantotal++] = *idxptr;
632 scn[idxboard-1].pmcount++;
633 gotpm = false;
634 }
635 }
636 totrecs -= getrecs;
637 } while(totrecs);
638
639 throw_free(toidxbuf);
640 pmscan = (HudsIdx*)throw_realloc(pmscan, (pmscantotal+1)*sizeof(HudsIdx));
641
642 // Sort all pm records in board/msgno order
643 for(uint k=pmscantotal >> 1; k; k >>= 1)
644 for(uint i=k; i < pmscantotal; i++)
645 for(uint j=i-k; (j >= 0) and HudsIdxCmp(pmscan[j], pmscan[j+k]) > 0; j-=k) {
646 HudsIdx e = pmscan[j];
647 pmscan[j] = pmscan[j+k];
648 pmscan[j+k] = e;
649 }
650
651 if(invalidboards) {
652 WideLog->printf("! Found %u msgs with an invalid board number (0 or >%u).", invalidboards, (__HUDSON ? HUDS_MAXBOARD : GOLD_MAXBOARD));
653 WideLog->printf("! In the %s msgbase at %s.", __HUDSON ? HUDS_NAME : GOLD_NAME, path);
654 WideLog->printf(": Info: Your msgbase may be partially corrupted.");
655 WideLog->printf("+ Advice: Run a msgbase index rebuild/recover utility.");
656 }
657
658 GFTRK(0);
659 }
660
661
662 // ------------------------------------------------------------------
663
664 template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
scan_area_pm()665 void _HudsArea<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::scan_area_pm() {
666
667 GFTRK("HudsScanAreaPM");
668
669 PMrk->ResetAll();
670
671 if(!wide)
672 wide = (HudsWide*) (__HUDSON ? (void *)hudsonwide : (void *)goldbasewide);
673
674 if(wide->iswideopen and not wide->ispmscanned)
675 wide->scan_pm();
676
677 // Get wide scan data if any
678 if(wide->scn) {
679
680 register board_t _board = (board_t)board();
681 register HudsScan* _scan = wide->scn + (_board - 1);
682
683 if(wide->pmscan) {
684 if(_scan->pmcount) {
685
686 register HudsIdx* pmscanptr = wide->pmscan;
687 while(pmscanptr->board != _board)
688 pmscanptr++;
689
690 register uint n = 0;
691 register uint cnt = _scan->pmcount;
692 while(n < cnt) {
693 PMrk->Append(pmscanptr->msgno);
694 pmscanptr++;
695 n++;
696 }
697 }
698 }
699
700 // Update area data
701 Msgn->SetCount(_scan->count);
702 lastread = _scan->lastreadreln;
703 lastreadentry = _scan->lastreadfound;
704
705 if(WideDebug) {
706 WideLog->printf("- b:%u: t:%u, l:%u, fm:%u, hm:%u, lr:%u, u:%u, pm:%i",
707 _board,
708 _scan->count,
709 _scan->lastreadreln,
710 _scan->firstmsgno,
711 _scan->lastmsgno,
712 _scan->lastread,
713 wide->userno,
714 PMrk->Count()
715 );
716 }
717
718 }
719 else {
720 if(WideDebug)
721 WideLog->printf("- Oops! Fell into empty bracket.");
722 }
723
724 GFTRK(0);
725 }
726
727
728 // ------------------------------------------------------------------
729
730