vedelete.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /*
  24. * COMPONENT_NAME: austext
  25. *
  26. * FUNCTIONS: compare_dba
  27. * d99_to_dba
  28. * delete_addrs
  29. * print_counters
  30. * print_dots
  31. * ve_delete
  32. *
  33. * ORIGINS: 27
  34. *
  35. *
  36. * (C) COPYRIGHT International Business Machines Corp. 1993,1995
  37. * All Rights Reserved
  38. * Licensed Materials - Property of IBM
  39. * US Government Users Restricted Rights - Use, duplication or
  40. * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  41. */
  42. /*************************** VEDELETE.C ****************************
  43. * $XConsortium: vedelete.c /main/6 1996/08/12 13:21:16 cde-ibm $
  44. * Implements the opera OE_DELETE_RECID and OE_DELETE_BATCH functions.
  45. * For each dba in usrblk.dbatab (count is in usrblk.dbcount):
  46. * deletes header rec, text blobs, and user notes;
  47. * database addresses on inverted index file;
  48. * and associated words and stems btree references.
  49. *
  50. * $Log$
  51. * Revision 2.2 1995/10/26 14:22:06 miker
  52. * Added prolog.
  53. *
  54. * Revision 2.1 1995/09/22 22:29:07 miker
  55. * Freeze DtSearch 0.1, AusText 2.1.8
  56. *
  57. * Revision 1.10 1995/09/05 19:22:46 miker
  58. * Made usrblk, ausapi_msglist global. Deleted obsolete socblk refs.
  59. * Minor name changes for DtSearch.
  60. *
  61. * Revision 1.9 1995/07/18 22:30:58 miker
  62. * Delete msglist arg from vista_abort() function calls.
  63. */
  64. #include "SearchE.h"
  65. #include <ctype.h>
  66. #include <stdlib.h>
  67. #include "vista.h"
  68. #define PROGNAME "VEDELETE"
  69. #define SKIP_UPDATE 0
  70. #define UPDATE_WORD 1
  71. #define DELETE_WORD 2
  72. #define WORDS_PER_DOT 1000
  73. #define MAX_REC_READ 128 /* Max number of addresses to be read from
  74. * database addresses file. 128 *
  75. * sizeof(DB_ADDR) = 512 bytes. This is the
  76. * size of one block read from hard disk. */
  77. /************ GLOBAL VARIABLES ***************/
  78. static struct or_hwordrec got_hword;
  79. static struct or_lwordrec got_lword;
  80. static struct or_swordrec got_sword;
  81. static int vistano;
  82. static FILE *dtbs_addr_fp;
  83. static int debugging = FALSE;
  84. static int verbose_debugging = FALSE;
  85. static char *keyptr = NULL;
  86. static long updated_words, deleted_words, skipped_words;
  87. static long freed_bytes;
  88. static DtSrINT16
  89. recslots;
  90. static long word_count, dot_count;
  91. /********************************/
  92. /* */
  93. /* print_dots */
  94. /* */
  95. /********************************/
  96. /* Called for every single database word.
  97. * Prints a dot for every WORDS_PER_DOT word,
  98. * a space every 10 dots, and a new line every 50 dots.
  99. */
  100. static void print_dots (void)
  101. {
  102. word_count++;
  103. if (word_count % WORDS_PER_DOT == 0) {
  104. word_count = 0;
  105. fputc ('.', aa_stderr);
  106. dot_count++;
  107. if (dot_count % 50 == 0) {
  108. fputc ('\n', aa_stderr);
  109. dot_count = 0;
  110. }
  111. else if (dot_count % 10 == 0)
  112. fputc (' ', aa_stderr);
  113. fflush (aa_stderr);
  114. }
  115. return;
  116. } /* print_dots() */
  117. /********************************/
  118. /* */
  119. /* d99_to_dba */
  120. /* */
  121. /********************************/
  122. /* Convert d99 dba format (the record NUMBER in the high
  123. * 3 bytes, and statistical info in lower byte)
  124. * to vista dba format (d00 file number in high byte,
  125. * slot number in lower 3 bytes). The conversion
  126. * accounts for the number of slots each record requires,
  127. * as well as an offset for the dbrec in slot #1.
  128. * (There is no slot #0 in vista; that's a NULL_DBA).
  129. * Formula: subtract 1, multiply by num reclots per rec, add 2.
  130. */
  131. static DB_ADDR d99_to_dba (DB_ADDR d99)
  132. {
  133. #define D00_HIBYTE ((DB_ADDR) OR_D00 << 24)
  134. /* Move hi 3 bytes to lo 3 bytes and zero out hi byte */
  135. d99 >>= 8;
  136. return D00_HIBYTE | ((--d99) * (DB_ADDR) recslots + 2);
  137. } /* d99_to_dba() */
  138. /********************************/
  139. /* */
  140. /* compare_dba */
  141. /* */
  142. /********************************/
  143. static int compare_dba (const void *dba1, const void *dba2)
  144. {
  145. DB_ADDR *i = (DB_ADDR *) dba1;
  146. DB_ADDR *j = (DB_ADDR *) dba2;
  147. if (*i < *j)
  148. return -1;
  149. if (*i > *j)
  150. return 1;
  151. return 0;
  152. } /* compare_dba() */
  153. /********************************/
  154. /* */
  155. /* delete_addrs */
  156. /* */
  157. /********************************/
  158. /* This function is called for each word in the database.
  159. * It reads and rewrites all the dbas in the d99 file for the word,
  160. * deleting those that are listed in the usrblk dba table.
  161. * Return - UPDATE_WORD if there are still some dba's in the
  162. * d99 file for this word.
  163. * Return - DELETE_WORD if all the dba's in the d99 were in
  164. * the usrblk table.
  165. * Return - SKIP_UPDATE if none of the dba's in the d99 file
  166. * were in the usrblk table.
  167. */
  168. static int delete_addrs (void)
  169. {
  170. DB_ADDR copy_addrs[MAX_REC_READ];
  171. DB_ADDR word_addrs[MAX_REC_READ];
  172. DB_ADDR vista_dba;
  173. char *dba_eq;
  174. int not_done = TRUE;
  175. int i, addrs_found;
  176. size_t num_reads, num_writes, ncopy;
  177. DtSrINT32 num_addrs, num_found;
  178. long read_offset, write_offset;
  179. if (fseek (dtbs_addr_fp, got_hword.or_hwoffset, SEEK_SET)) {
  180. printf (PROGNAME "80 "
  181. "fseek failed on '%s%s.d99'. Offset=%ld. Word='%s'.\n",
  182. usrblk.dblk->path, usrblk.dblk->name,
  183. (long) got_hword.or_hwoffset, keyptr);
  184. DtSearchExit (99);
  185. }
  186. write_offset = ftell (dtbs_addr_fp);
  187. if (got_hword.or_hwoffset != write_offset) {
  188. printf (PROGNAME "88 ftell failed on '%s%s.d99'."
  189. " hwoffset=%ld write_offset=%ld.\n",
  190. usrblk.dblk->path, usrblk.dblk->name,
  191. (long)got_hword.or_hwoffset, write_offset);
  192. DtSearchExit (99);
  193. }
  194. num_addrs = got_hword.or_hwaddrs;
  195. addrs_found = FALSE;
  196. num_found = 0;
  197. /* OUTER LOOP: for each block of dbas */
  198. while (not_done) {
  199. ncopy = 0;
  200. /*
  201. * read only a single block of max recs, or fewer dba's if this is
  202. * the last block
  203. */
  204. if (num_addrs > MAX_REC_READ) {
  205. num_reads = MAX_REC_READ;
  206. num_addrs -= MAX_REC_READ;
  207. }
  208. else {
  209. not_done = FALSE;
  210. num_reads = num_addrs;
  211. }
  212. if (fread (word_addrs, sizeof (DB_ADDR), num_reads, dtbs_addr_fp)
  213. != num_reads) {
  214. puts ("\n\r" PROGNAME "98 "
  215. "AusText is shutting down due to corrupted k2x/d99 links.");
  216. DtSearchExit (99);
  217. }
  218. /* INNER LOOP: each dba in this block */
  219. for (i = 0; i < num_reads; i++) {
  220. vista_dba = d99_to_dba (ntohl (word_addrs[i]));
  221. dba_eq = (char *) bsearch (
  222. &vista_dba, /* key to search for */
  223. usrblk.dbatab, /* start of the table */
  224. usrblk.dbacount, /* # elems in the table */
  225. sizeof (DB_ADDR), /* size of each elem */
  226. compare_dba); /* my compare function */
  227. if (dba_eq != NULL) {
  228. /*
  229. * HIT! the passed word links to this dba. Don't copy the dba
  230. * to copy array.
  231. */
  232. num_found++;
  233. addrs_found = TRUE;
  234. }
  235. else {
  236. /* MISS! Keep the dba by copying it to the copy array */
  237. copy_addrs[ncopy++] = htonl (word_addrs[i]);
  238. }
  239. } /* end INNER LOOP for each dba in curr block */
  240. if (addrs_found) {
  241. /*
  242. * Once we start deleting dba's: save the curr 'read' loc, write
  243. * the shorter 'copy' array to the output file at the curr
  244. * 'write' loc, update the 'write' loc ptr, restore the 'read'
  245. * loc.
  246. */
  247. read_offset = ftell (dtbs_addr_fp);
  248. if (read_offset <= 0L) {
  249. printf (PROGNAME "169 ftell failed on '%s%s.d99'.\n",
  250. usrblk.dblk->path, usrblk.dblk->name);
  251. DtSearchExit (99);
  252. }
  253. if (fseek (dtbs_addr_fp, write_offset, SEEK_SET)) {
  254. printf (PROGNAME "175 fseek to %ld failed on '%s%s.d99'.\n",
  255. write_offset, usrblk.dblk->path, usrblk.dblk->name);
  256. DtSearchExit (99);
  257. }
  258. num_writes = fwrite (copy_addrs, sizeof (DB_ADDR),
  259. ncopy, dtbs_addr_fp);
  260. if (num_writes != ncopy) {
  261. printf (PROGNAME "283 fwrite at pos %ld failed on '%s%s.d99'.\n"
  262. " Wrote %lu dba's instead of %lu dba's.\n",
  263. write_offset, usrblk.dblk->path, usrblk.dblk->name,
  264. (unsigned long) num_writes, (unsigned long) ncopy);
  265. DtSearchExit (99);
  266. }
  267. write_offset = ftell (dtbs_addr_fp);
  268. if (write_offset <= 0L) {
  269. printf (PROGNAME "191 ftell failed on '%s%s.d99'.\n",
  270. usrblk.dblk->path, usrblk.dblk->name);
  271. DtSearchExit (99);
  272. }
  273. if (fseek (dtbs_addr_fp, read_offset, SEEK_SET)) {
  274. printf (PROGNAME "198 fseek to %ld failed on '%s%s.d99'.\n",
  275. read_offset, usrblk.dblk->path, usrblk.dblk->name);
  276. DtSearchExit (99);
  277. }
  278. } /* end if (addrs_found) */
  279. else {
  280. /* [do nothing, leave this block as is, just incr write ptr] */
  281. write_offset = ftell (dtbs_addr_fp);
  282. if (write_offset <= 0L) {
  283. printf (PROGNAME "208 ftell failed on '%s%s.d99'.\n",
  284. usrblk.dblk->path, usrblk.dblk->name);
  285. DtSearchExit (99);
  286. }
  287. }
  288. } /* end OUTER LOOP for this word */
  289. if (addrs_found) {
  290. got_hword.or_hwaddrs -= num_found;
  291. got_hword.or_hwfree += num_found;
  292. if (got_hword.or_hwaddrs < 0) {
  293. printf (PROGNAME "220 duplicate dbas for '%s' in '%s%s.d99'.\n",
  294. keyptr, usrblk.dblk->path, usrblk.dblk->name);
  295. DtSearchExit (99);
  296. }
  297. if (got_hword.or_hwaddrs == 0) {
  298. deleted_words++;
  299. freed_bytes += sizeof (DB_ADDR) * got_hword.or_hwfree;
  300. return DELETE_WORD;
  301. }
  302. else {
  303. /*
  304. * @@@ fill out newly freed dba positions with FF's as debugging
  305. * aid?
  306. */
  307. updated_words++;
  308. return UPDATE_WORD;
  309. }
  310. } /* end if (addrs_found) */
  311. skipped_words++;
  312. return SKIP_UPDATE;
  313. } /* delete_addrs() */
  314. /****************************************/
  315. /* */
  316. /* print_counters */
  317. /* */
  318. /****************************************/
  319. /* Initializes accumulators, or generates msg
  320. * of accumulator status and empties the accumulators.
  321. */
  322. static void print_counters (char *wordtype)
  323. {
  324. char msgbuf[256];
  325. static long totupdwords, totdelwords, totskipwords;
  326. static long totfreedbytes;
  327. if (wordtype == NULL) {
  328. /* initialize buckets */
  329. totupdwords = totdelwords = totskipwords = 0L;
  330. updated_words = deleted_words = skipped_words = 0L;
  331. freed_bytes = totfreedbytes = 0L;
  332. }
  333. else if ((long) wordtype == -1L) {
  334. /* final totals msg */
  335. sprintf (msgbuf, PROGNAME " Batch Totals: "
  336. "updated %ld, deleted %ld, unaffected %ld.\n"
  337. " Old word count = %ld, New word count = %ld.\n"
  338. " Freed %ld total bytes in d99 file.\n"
  339. ,totupdwords, totdelwords, totskipwords
  340. ,totupdwords + totdelwords + totskipwords
  341. ,totupdwords + totskipwords
  342. ,totfreedbytes);
  343. DtSearchAddMessage (msgbuf);
  344. }
  345. else {
  346. /* regular progress msg */
  347. sprintf (msgbuf, PROGNAME " %ld %s Words: "
  348. "%ld updated, %ld deleted, %ld unaffected.\n"
  349. " Freed %ld bytes in d99 file."
  350. ,updated_words + deleted_words + skipped_words
  351. ,wordtype
  352. ,updated_words, deleted_words, skipped_words
  353. ,freed_bytes
  354. );
  355. DtSearchAddMessage (msgbuf);
  356. totupdwords += updated_words;
  357. totdelwords += deleted_words;
  358. totskipwords += skipped_words;
  359. totfreedbytes += freed_bytes;
  360. updated_words = deleted_words = skipped_words = freed_bytes = 0L;
  361. }
  362. return;
  363. } /* print_counters() */
  364. /****************************************/
  365. /* */
  366. /* ve_delete */
  367. /* */
  368. /****************************************/
  369. /* First do Gendler's code: words, stems, and inverted indexes.
  370. * If it goes down, at least the database itself won't be corrupted.
  371. * Then do Russell's code: delete text blobs, misc recs,
  372. * and the object records. If it goes down here, only one
  373. * or two records will be corrupted and none of Gendler's
  374. * word searches will retrieve records yet to be deleted.
  375. * The total database record count is adjusted between the
  376. * loops because it's only used for Gendler's code.
  377. * Addresses in usrblk.dbatab are PRESUMED VALID object records.
  378. @@@@@@ still one bug left. Semantic inverted index files (d97, d98)
  379. @@@@@@ not yet updated. But cborodin reindexes everything every time
  380. @@@@@@ it runs so only failures will occur for semantic searches (rare),
  381. @@@@@@ after tomita deletions (rare), before cborodin runs (common).
  382. @@@@@@ Since this window is very small and no database corruption
  383. @@@@@@ can occur, by order of management I'm to fix it later.
  384. @@@@@@ The fix is: include the same module used in cborodin to reindex
  385. @@@@@@ completely. On a 3 gig database that takes about 2 minutes.
  386. */
  387. void ve_delete (void)
  388. {
  389. DB_ADDR dba;
  390. char charbuf[200 + DtSrMAX_DB_KEYSIZE];
  391. int i, j;
  392. int ret_code;
  393. DtSrINT32 *reccount = &usrblk.dblk->dbrec.or_reccount;
  394. DtSrINT16 maxwordsz = usrblk.dblk->dbrec.or_maxwordsz;
  395. int dbacount = usrblk.dbacount;
  396. if (dbacount < 1) {
  397. NOTHING_TO_DO:
  398. DtSearchAddMessage (PROGNAME"336 "
  399. "Database address table is empty; nothing to delete!");
  400. usrblk.retncode = OE_NOOP;
  401. return;
  402. }
  403. recslots = usrblk.dblk->dbrec.or_recslots;
  404. vistano = usrblk.dblk->vistano;
  405. dtbs_addr_fp = usrblk.dblk->iifile;
  406. debugging = ((usrblk.debug & USRDBG_DELETE) != 0L);
  407. verbose_debugging = ((usrblk.debug & USRDBG_VERBOSE) != 0L);
  408. print_counters (NULL); /* initialize all counters */
  409. if (debugging) {
  410. fprintf (aa_stderr, PROGNAME "185 "
  411. "db='%s' vistano=%d maxwordsz=%d dbacount=%d.\n",
  412. usrblk.dblk->name, vistano, (int)maxwordsz, dbacount);
  413. if (verbose_debugging)
  414. for (i = 0; i < dbacount; i++) {
  415. dba = usrblk.dbatab[i];
  416. CRSET (PROGNAME "178", &dba, vistano);
  417. CRREAD (PROGNAME "179", OR_OBJKEY, charbuf, vistano);
  418. fprintf (aa_stderr, " #%d\tdba=%ld:%ld key='%s'\n",
  419. i, (long) dba>>24, (long) dba & 0xffffff, charbuf);
  420. }
  421. }
  422. /* Sort the array of database addresses.
  423. * After sorting, eliminate any duplicate dba's
  424. * and adjust dbacount if necessary.
  425. */
  426. qsort (usrblk.dbatab, (size_t)dbacount, sizeof(DB_ADDR), compare_dba);
  427. for (i = 1; i < dbacount; i++) {
  428. if (usrblk.dbatab[i-1] != usrblk.dbatab[i])
  429. continue;
  430. dba = usrblk.dbatab[i];
  431. sprintf (charbuf, PROGNAME"370 Duplicate dba = %ld:%ld ignored.",
  432. (long)dba>>24, (long)(dba & 0x00ffffff));
  433. DtSearchAddMessage (charbuf);
  434. if (debugging)
  435. fprintf (aa_stderr, "%s\n", charbuf);
  436. /* subloop moves rest of table up by one */
  437. for (j = i + 1; j < dbacount; j++)
  438. usrblk.dbatab[j-1] = usrblk.dbatab[j];
  439. dbacount--;
  440. usrblk.dbacount = dbacount; /* in case caller uses this */
  441. }
  442. if (dbacount < 1)
  443. goto NOTHING_TO_DO;
  444. if (debugging) {
  445. fprintf (aa_stderr, PROGNAME"355 "
  446. "After sorting dbatab, dbacount=%d.\n", dbacount);
  447. if (verbose_debugging)
  448. for (i = 0; i < dbacount; i++) {
  449. dba = usrblk.dbatab[i];
  450. CRSET (PROGNAME "358", &dba, vistano);
  451. CRREAD (PROGNAME "359", OR_OBJKEY, charbuf, vistano);
  452. fprintf (aa_stderr, " #%d\tdba=%ld:%ld key='%s'\n",
  453. i, (long)dba>>24, (long)(dba & 0x00ffffff), charbuf);
  454. }
  455. }
  456. /*
  457. * There are 3 identical Gendler Loops, one for each possible group of
  458. * word sizes: swords, lwords, and hwords. To speed up this lengthy
  459. * process, only those loops will be executed as determined by database's
  460. * maxwordsz. However delete_addrs() function always uses the
  461. * buffer for huge words, so the necessary fields will be copied into
  462. * that buffer for the smaller word sizes.
  463. */
  464. /*--------- Gendler's SWORD Loop ---------*/
  465. /* every database has short words */
  466. fprintf (aa_stderr, PROGNAME "368 "
  467. "Entering SHORT word loop. Each dot = %d words.\n",
  468. WORDS_PER_DOT);
  469. fflush (aa_stderr);
  470. word_count = 0;
  471. dot_count = 0;
  472. updated_words = skipped_words = deleted_words = 0L;
  473. freed_bytes = 0L;
  474. KEYFRST (PROGNAME "203", OR_SWORDKEY, vistano);
  475. while (db_status == S_OKAY) {
  476. print_dots();
  477. RECREAD (PROGNAME "182", &got_sword, vistano);
  478. got_hword.or_hwoffset = ntohl (got_sword.or_swoffset);
  479. got_hword.or_hwaddrs = ntohl (got_sword.or_swaddrs);
  480. got_hword.or_hwfree = ntohl (got_sword.or_swfree);
  481. keyptr = got_sword.or_swordkey;
  482. ret_code = delete_addrs();
  483. if (ret_code == UPDATE_WORD) {
  484. got_sword.or_swoffset = htonl (got_hword.or_hwoffset);
  485. got_sword.or_swaddrs = htonl (got_hword.or_hwaddrs);
  486. got_sword.or_swfree = htonl (got_hword.or_hwfree);
  487. RECWRITE (PROGNAME "183", &got_sword, vistano);
  488. }
  489. else if (ret_code == DELETE_WORD) {
  490. DELETE (PROGNAME "184", vistano);
  491. }
  492. KEYNEXT (PROGNAME "196", OR_SWORDKEY, vistano);
  493. } /* end loop on each sword */
  494. print_counters ("Short");
  495. /* end SWORDs */
  496. /*--------- Gendler's LWORD Loop ---------*/
  497. fprintf (aa_stderr, PROGNAME "398 "
  498. "Entering LONG word loop. Each dot = %d words.\n",
  499. WORDS_PER_DOT);
  500. fflush (aa_stderr);
  501. word_count = 0;
  502. dot_count = 0;
  503. updated_words = skipped_words = deleted_words = 0L;
  504. freed_bytes = 0L;
  505. KEYFRST (PROGNAME "243", OR_LWORDKEY, vistano);
  506. while (db_status == S_OKAY) {
  507. print_dots();
  508. RECREAD (PROGNAME "246", &got_lword, vistano);
  509. got_hword.or_hwoffset = ntohs (got_lword.or_lwoffset);
  510. got_hword.or_hwaddrs = ntohs (got_lword.or_lwaddrs);
  511. got_hword.or_hwfree = ntohs (got_lword.or_lwfree);
  512. keyptr = got_lword.or_lwordkey;
  513. ret_code = delete_addrs ();
  514. if (ret_code == UPDATE_WORD) {
  515. got_lword.or_lwoffset = htons (got_hword.or_hwoffset);
  516. got_lword.or_lwaddrs = htons (got_hword.or_hwaddrs);
  517. got_lword.or_lwfree = htons (got_hword.or_hwfree);
  518. RECWRITE (PROGNAME "252", &got_lword, vistano);
  519. }
  520. else if (ret_code == DELETE_WORD) {
  521. DELETE (PROGNAME "256", vistano);
  522. }
  523. KEYNEXT (PROGNAME "258", OR_LWORDKEY, vistano);
  524. } /* end LONGs */
  525. print_counters ("Long");
  526. /*--------- Gendler's HWORD Loop --------- */
  527. fprintf (aa_stderr, PROGNAME "429 "
  528. "Entering HUGE word loop. Each dot = %d words.\n",
  529. WORDS_PER_DOT);
  530. fflush (aa_stderr);
  531. word_count = 0;
  532. dot_count = 0;
  533. updated_words = skipped_words = deleted_words = 0L;
  534. freed_bytes = 0L;
  535. KEYFRST (PROGNAME "280", OR_HWORDKEY, vistano);
  536. while (db_status == S_OKAY) {
  537. print_dots();
  538. RECREAD (PROGNAME "284", &got_hword, vistano);
  539. NTOHS (got_hword.or_hwoffset);
  540. NTOHS (got_hword.or_hwaddrs);
  541. NTOHS (got_hword.or_hwfree);
  542. keyptr = got_hword.or_hwordkey;
  543. ret_code = delete_addrs ();
  544. if (ret_code == UPDATE_WORD) {
  545. HTONS (got_hword.or_hwoffset);
  546. HTONS (got_hword.or_hwaddrs);
  547. HTONS (got_hword.or_hwfree);
  548. RECWRITE (PROGNAME "289", &got_hword, vistano);
  549. }
  550. else if (ret_code == DELETE_WORD) {
  551. DELETE (PROGNAME "293", vistano);
  552. }
  553. KEYNEXT (PROGNAME "295", OR_HWORDKEY, vistano);
  554. } /* end HUGEs */
  555. print_counters ("Huge");
  556. /* print final batch totals */
  557. print_counters ((char *) -1);
  558. /*--------- Russell's Loop ---------*/
  559. fprintf (aa_stderr,
  560. PROGNAME"470 All words processed. Now deleting %d objects...\n",
  561. dbacount);
  562. for (i = 0; i < dbacount; i++) {
  563. dba = usrblk.dbatab[i];
  564. if (verbose_debugging) {
  565. fprintf (aa_stderr, PROGNAME "471 "
  566. "Deleting object #%2d,\tdba %ld:%ld.\n",
  567. i, (long)dba>>24, (long)(dba & 0x00ffffff));
  568. fflush (aa_stderr);
  569. }
  570. /* Delete blobs. Use real d_csoset at first call
  571. * so we can print out fancy error msg.
  572. */
  573. d_csoset (OR_OBJ_BLOBS, &dba, vistano);
  574. if (db_status != 0) {
  575. fputs (vista_msg(PROGNAME"152"), aa_stderr);
  576. fprintf (aa_stderr, PROGNAME"153 Abort: "
  577. "vistano=%d, dbatab #%d (out of %d), dba=%ld:%ld.\n",
  578. vistano, i, dbacount, (long)dba>>24, (long)(dba & 0x00ffffff));
  579. fflush (aa_stderr);
  580. DtSearchExit (53);
  581. }
  582. FINDFM (PROGNAME "155", OR_OBJ_BLOBS, vistano);
  583. while (db_status != S_EOS) {
  584. DISDEL (PROGNAME "158", vistano);
  585. FINDFM (PROGNAME "159", OR_OBJ_BLOBS, vistano);
  586. }
  587. /* Delete misc records (old user notes, abstracts, fzkeys) */
  588. CSOSET (PROGNAME "142", OR_OBJ_MISCS, &dba, vistano);
  589. FINDFM (PROGNAME "145", OR_OBJ_MISCS, vistano);
  590. while (db_status != S_EOS) {
  591. DISDEL (PROGNAME "148", vistano);
  592. FINDFM (PROGNAME "149", OR_OBJ_MISCS, vistano);
  593. }
  594. /* Pull the final plug by deleting the object record itself */
  595. CRSET (PROGNAME "200", &dba, vistano);
  596. DISDEL (PROGNAME "201", vistano);
  597. } /* end of Russell's loop */
  598. /* Adjust total record count */
  599. *reccount -= dbacount;
  600. if (*reccount < 0)
  601. *reccount = 0;
  602. RECFRST (PROGNAME "355", OR_DBREC, vistano); /* seqtl retrieval */
  603. if (db_status != S_OKAY)
  604. vista_abort (PROGNAME"356");
  605. HTONL (*reccount);
  606. CRWRITE (PROGNAME "341", OR_RECCOUNT, reccount, vistano);
  607. if (db_status != S_OKAY)
  608. vista_abort (PROGNAME"342");
  609. usrblk.retncode = OE_OK;
  610. return;
  611. } /* ve_delete() */
  612. /*************************** VEDELETE.C ****************************/