1: # include <stdio.h> 2: # include <ingres.h> 3: # include <aux.h> 4: # include <lock.h> 5: # include <pv.h> 6: # include <sccs.h> 7: # include <opsys.h> 8: # include <sys/dir.h> 9: 10: SCCSID(@(#)purge.c 8.3 1/31/86) 11: 12: /* 13: ** PURGE DATABASE 14: ** 15: ** This stand-alone routine cleans up a database. This includes: 16: ** 17: ** - Destroy temporary relations, i.e., relations with names 18: ** beginning with "_SYS". 19: ** - Destroy expired relations 20: ** - Clean out junk files, such as core, etc. 21: ** - As a suggested future expansion, reformat relations which 22: ** have many overflow pages, or heaps with lots of old 23: ** deleted tuples, etc. 24: ** 25: ** It may be called by the ingres superuser or by the dba of 26: ** a database. There are two modes. The first is where databases 27: ** to be purged are explicitly named. If none are named, then 28: ** all databases owned by the particular user (or all databases 29: ** if the INGRES superuser) are purged. 30: ** 31: ** Flags: 32: ** -p enable the purge feature, i.e., clean out expired 33: ** relations as well as temporary relations. 34: ** -s attempt to run in superuser mode. The user must be 35: ** login "ingres" for this to succeed. 36: ** -a ask the user before each database. 37: ** -f clean out rather than report junk files. 38: ** 39: ** (8/2/82 peter@lbl-unix) 40: ** allow dba to destroy user relations by suitable manipulation 41: ** of Usercode 42: ** added ExitFn = nullfn() to avoid untimely aborts on syserrs. 43: ** (5/13/83 peter@lbl-csam) 44: ** folded in new directory rootines for 4.1c-bsd 45: */ 46: 47: 48: char All; 49: char Superuser; 50: char Ask; 51: char Purge; 52: char Clean; 53: extern int Wait_action; 54: extern int Status; 55: extern char *Usercode; 56: long Today; 57: short tTdbu[100]; 58: extern int (*ExitFn)(); 59: 60: main(argc, argv) 61: int argc; 62: char *argv[]; 63: { 64: register char *db; 65: register int i; 66: char fake[256]; 67: extern char *getnxtdb(); 68: extern int null_fn(); 69: 70: argv[argc] = NULL; 71: # ifdef xTTR1 72: tTrace(argv, 'T', tTdbu, 100); 73: # endif 74: 75: /* set up arguments and operating modes */ 76: initialize(argc, argv); 77: time(&Today); 78: # ifdef xTTR2 79: tTfp(10, 2, "Usercode: %.2s\n", Usercode); 80: # endif 81: 82: /* Assign ExitFn so syserr (e.g. from destroy) does not cause aborts */ 83: ExitFn = null_fn; 84: 85: while (db = getnxtdb()) 86: { 87: purgedb(db); 88: } 89: printf("\npurge completed\n"); 90: } 91: 92: 93: rubproc() 94: { 95: unldb(); 96: exit(-1); 97: } 98: 99: 100: 101: /* 102: ** PURGE DATABASE 103: ** 104: ** The database is purged of temporaries, expired relations, and 105: ** junk. 106: */ 107: 108: extern DESC Reldes; 109: DESC Btreesec; 110: int Btree_fd; 111: char *Fileset; 112: 113: #ifndef rewinddir 114: typedef DIR FILE; 115: #endif 116: extern DIR *opendir(); 117: extern struct direct *readdir(); 118: 119: 120: purgedb(db) 121: register char *db; 122: { 123: struct relation rel, key; 124: TID rtid, rlimtid; 125: register int i; 126: register char c; 127: long l; 128: DIR *dirp; 129: struct direct *dp; 130: int darg[3]; 131: PARM pv[2]; 132: char pbuff[MAXNAME + 1]; 133: char *fname; 134: #ifndef rewinddir 135: char fnambuf[DIRSIZ + 1]; 136: #endif 137: 138: # ifdef xTTR2 139: tTfp(11, 0, "entered purgedb(%s)\n", db); 140: # endif 141: printf("Database %s", db); 142: if (!ask("? ")) 143: return; 144: if (!Ask) 145: printf(":\n"); 146: acc_init(); 147: 148: /* set exclusive lock on data base */ 149: # ifdef xTTR2 150: tTfp(11, 1, "calling db_lock(%d)\n", M_EXCL); 151: # endif 152: db_lock(M_EXCL); 153: 154: /* open the relation relation for read-write */ 155: opencatalog("relation", OR_WRITE); 156: 157: if (find(&Reldes, NOKEY, &rtid, &rlimtid)) 158: { 159: printf("\tcannot find in %s\n", db); 160: closecatalog(TRUE); /* really close cache */ 161: unldb(); /* unlock the database */ 162: acc_close(); 163: return; 164: } 165: 166: while (get(&Reldes, &rtid, &rlimtid, &rel, 1) == 0) 167: { 168: i = 0; 169: 170: /* check for temp rel */ 171: if (bequal(rel.relid, "_SYS", 4)) 172: { 173: printf("\t%.14s: temporary", rel.relid); 174: i++; 175: } 176: else if (rel.relsave < Today && rel.relsave != 0) 177: { 178: printf("\t%.14s: expired", rel.relid); 179: if (Purge) 180: if (ask("\n\t\tPURGE? ")) 181: i++; 182: } 183: else 184: i = -1; 185: 186: /* if this relation should be purged -- call (local) destroy */ 187: if (i > 0) 188: { 189: char *usave; 190: printf("\tpurging\n"); 191: 192: /* allow DBA to purge other users relations */ 193: usave = 0; 194: if (!bequal(rel.relowner, Usercode, 2)) { 195: usave = Usercode; 196: Usercode = rel.relowner; 197: } 198: 199: /* set up parameter vector for destroy */ 200: bmove(rel.relid, pbuff, MAXNAME); 201: pbuff[MAXNAME] = '\0'; 202: pv[0].pv_type = PV_STR; 203: pv[0].pv_val.pv_str = pbuff; 204: pv[1].pv_type = PV_EOF; 205: pv[1].pv_val.pv_str = NULL; 206: if (destroy(1, pv) != 0) 207: syserr("cannot destroy %s\n", pbuff); 208: if (usave) 209: Usercode = usave; 210: closecatalog(FALSE); /* to flush */ 211: } 212: else if (i == 0) 213: printf("\t\t(not purged)\n"); 214: } 215: 216: /* open the directory to check for extra files */ 217: if ((dirp = opendir(".")) == NULL) 218: { 219: printf("\tcannot open .\n"); 220: closecatalog(TRUE); /* really */ 221: unldb(); /* unlock the database */ 222: acc_close(); 223: return; 224: } 225: 226: /* scan the directory */ 227: for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { 228: 229: #ifdef rewinddir 230: fname = dp->d_name; 231: if (dp->d_namlen <= 2) 232: continue; 233: #else rewinddir 234: strncpy(fnambuf, dp->d_name, DIRSIZ); 235: fnambuf[DIRSIZ] = '\0'; 236: fname = fnambuf; 237: if (!strcmp(fname, ".") || !strcmp(fname, "..")) 238: continue; 239: #endif rewinddir 240: 241: /* throw out legitimate files */ 242: if (sequal(fname, "admin")) 243: continue; 244: 245: /* always purge _SYS files */ 246: if (!bequal(fname, "_SYS", 4)) 247: { 248: if (fname[13] != 0) 249: { 250: /* it might be a relation */ 251: clearkeys(&Reldes); 252: setkey(&Reldes, &key, fname, RELID); 253: setkey(&Reldes, &key, &fname[MAXNAME], RELOWNER); 254: if (getequal(&Reldes, &key, &rel, &rtid) <= 0) 255: { 256: /* it is a relation (or should be saved) */ 257: continue; 258: } 259: } 260: 261: /* it is a funny file!!! */ 262: if (!Clean) 263: { 264: printf("\t%s: file (not unlinked)\n", fname); 265: continue; 266: } 267: } 268: 269: /* purge the file */ 270: printf("\tunlinking %s\n", fname); 271: if (unlink(fname)) 272: printf("\tcannot unlink\n"); 273: } 274: closecatalog(TRUE); /* close catalogs */ 275: unldb(); /* unlock the database */ 276: acc_close(); 277: closedir(dirp); 278: }