00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #if 0
00014 Todo stuff:
00015 New definitions:
00016 sbbuffer - old sbstr. Abbrev & struct "sbbuff". Macro SBBUFF
00017 (or SBBUF?)
00018 sbstring - list of sds. Abbrev sbstr. Macro SBSTR.
00019 Should *sbstr == *sdblk? Yeah.
00020 sbfile - as before. Macro SBFILE. (or SBFIL?)
00021
00022 Try to get zero-length sdblks flushed on the fly,
00023 rather than waiting for moby GC. Also, need to set
00024 up compaction of SD freelist, as well as SM freelist.
00025 Make SM freelist compact self-invoked by SBM_MGET?
00026 Any need for phys disk ptrs other than for tempfile?
00027 Can do sbm_forn through SDblks to find active sdfiles
00028 so list isn''t needed for that.
00029 Can sdback be flushed? (not needed for keeping list sorted,
00030 or for searching it -- only used when linking
00031 blocks in or out of list.) Perhaps use circular list?
00032 If list only used for tmpfile, then to link in/out could
00033 always start from sfptr1 of tmpfile? Sure, but slow?
00034 Last SD on phys list could belong to no logical list,
00035 and denote free space on tmpfile?
00036
00037 --------------------------
00038
00039 An "open" SBBUFFER will allow one to read, write, insert into,
00040 and delete from a sbstring (a logical character string). "Dot" refers
00041 to the current logical character position, which is where all
00042 operations must happen; sb_fseek must be used to change this location.
00043 There are several states that the I/O can be in:
00044 !SBCUR ----CLOSED----
00045 All other elements, including SBIOP, should also be 0.
00046 Dot is 0.
00047 SBCUR && !SBIOP ----OPEN/IDLE----
00048 SBCUR points to a SD block (its SDMEM may or may not exist)
00049 SBIOP==0 (otherwise it would be open/ready)
00050 Dot is SBDOT + SBOFF.
00051 R/Wleft must be 0.
00052 SBCUR && SBIOP ----OPEN/READY----
00053 SBCUR points to a SDBLK (SDMEM must exist!)
00054 SBIOP exists.
00055 Dot is SBDOT + offset into SMBLK. SBOFF is ignored!
00056 SB_WRIT flag is set if "smuse" must be updated.
00057 The R/Wleft counts are set up:
00058 1. Rleft 0, Wleft 0 -- Since SBIOP is set, must assume
00059 counts are too.
00060 So this means at end of text, no room left.
00061 Otherwise would imply that setup needs doing.
00062 2. Rleft N, Wleft 0 -- At beg or middle of text
00063 3. Rleft 0, Wleft N -- At end of text
00064 4. Rleft N, Wleft N -- Shouldn''t ever happen
00065
00066 Note that Rleft is always correct. Wleft is sometimes
00067 set 0 in order to force a call to determine real state.
00068
00069 Note that SBIOP alone is a sufficient test for being OPEN/READY.
00070
00071 The important thing about updating the smblk is to ensure that the "smuse"
00072 field is correct. This can only be changed by writing or deleting. We assume
00073 that deletions always update immediately, thus to determine if an update
00074 is necessary, see if SB_WRIT is set. If so, update smuse before doing
00075 anything but more writing!!!!
00076
00077 The SDBLK must be marked "modified" whenever a write operation is
00078 done. We try to do this only the first time, by keeping Wleft zero
00079 until after the first write. This is also when SB_WRIT gets set.
00080 However, if in overwrite mode, Wleft must be kept zero in order to
00081 force the proper actions; SB_WRIT is also not turned on since smuse
00082 will not change. Note that at EOF, overwrite becomes the same thing
00083 as insert and is treated identically...
00084
00085 If a SBLK has an in-core copy but no disk copy, it can be
00086 freely modified. Otherwise, modifications should preferably split
00087 the block so as to retain "pure" blocks as long as possible. "Pure" blocks
00088 can always have their in-core versions flushed immediately (unless for
00089 compaction purposes they''ll need to be written out in the same GC pass).
00090 Alternatively, mods can simply mark the disk copy "free" and go
00091 ahead as if no such copy existed.
00092 No additions or changes to a pure block are allowed, but
00093 deletions from the end or beginning are always allowed. All other
00094 changes must split or insert new blocks to accomplish the changes.
00095
00096 Locking:
00097 SDBLKs are subject to unpredictable relocation, compaction,
00098 and garbage collecting. There are three ways in which a SDBLK can
00099 remain fixed:
00100
00101 1. The SDBLK has the SD_LOCK flag set. This flag is used whenever
00102 a SBBUF''s SBCUR is pointing to this SDBLK.
00103 2. The SDBLK has the SD_LCK2 flag set. This flag is used only
00104 during execution of various internal routines and should
00105 not be seen anywhere during execution of user code.
00106 3. The SDBLK has no back-pointer (is first block in a sbstring).
00107 Such SDBLKs cannot be relocated (since it is not known
00108 what may be pointing to them) but unlike the other 2 cases
00109 they are still subject to compaction with succeeding SDBLKs.
00110
00111 The SDBLK must be locked with SD_LOCK for as long as it is being
00112 pointed to by SBCUR. The sole exception is when a SBBUF in the
00113 OPEN/IDLE state is pointing to the first SDBLK of a sbstring; this
00114 sdblk is guaranteed not to be moved, since sdblks without a
00115 back-pointer are never moved. SD_LOCK is asserted as soon as the state
00116 changes to OPEN/READY, of course. The internal routines take pains to
00117 always move SD_LOCK as appropriate. Note that only one SD in a
00118 sbstring can ever have SD_LOCK turned on. SD_LCK2 is an auxiliary flag
00119 which may appear in more than one SDBLK, for use by low-level routines
00120 for various temporary reasons; either will prevent the SDBLK from being
00121 modified in any way by the storage compactor.
00122
00123 SEEKs are a problem because it''s unclear at seek time what will happen
00124 next, so the excision of the smblk can''t be optimized. If the seek
00125 happens to land in a sdblk with an existing smblk, there''s no problem;
00126 but if it''s a sdblk alone, how to decide which part of it to read in???
00127 If next action is:
00128 write - split up sdblk and create new one. Read nothing in.
00129 read - read in 512 bytes starting at disk blk boundary if possible
00130 else read in 128 bytes starting with selected char
00131 (include beg of sdblk if less than 64 chars away)
00132 overwrite - as for read.
00133 backread - like read but position at end of sdblk.
00134 delete - split up sdblk, read nothing in.
00135
00136 We solve this through the OPEN/IDLE state, where SBIOP == 0 means SBOFF
00137 points to logical offset from start of current sdblk, so that the seek
00138 need not take any action. Only when a specific operation is requested
00139 will the transition to OPEN/READY take place, at which time we''ll know
00140 what the optimal excision strategy is. The routine SBX_READY performs
00141 this function.
00142
00143 The physical links (SDFORW and SDBACK) are only valid when SDFILE is
00144 set (likewise for SDLEN and SDADDR). In other words, mungs to a sdblk
00145 must check SDFILE to see whether or not the phys links should be
00146 altered. Normally they aren''t except during sdblk creation, deletion,
00147 or swapout, no matter how much the sdblk gets shuffled around
00148 logically. The disk physical list is kept sorted in order of starting
00149 addresses. The text blocks indicated can overlap. When a GC is
00150 necessary, the code must figure out how much space is actually free.
00151
00152 -------------- Old woolgathering, ignore rest of this page ---------------
00153
00154 Question: should 512-byte buffers be maintained, one for each SBFILE?
00155 Or should the in-core text be hacked up to serve for buffering?
00156 Question is where to point the READ/WRITE system calls. Currently,
00157 they are pointed directly at the in-core text, and there are no
00158 auxiliary buffers.
00159
00160 If use auxiliary buffers:
00161 How to handle flushing, when changing location etc?
00162 Could be clever about reading from large disk block, only
00163 get part of it into buffer instead of splitting up in order to
00164 read a "whole" block.
00165 Problem: sbstrings can include pieces of several different files.
00166 Hard to maintain just one buffer per FD without hacking
00167 done on one sbstring screwing that on another.
00168 If don''t use buffers:
00169 Need to have a "chars-left" field in mem blocks, so know how
00170 much more can be added. Will need heuristics for how much
00171 extra space to allocate.
00172 #endif
00173
00174
00175
00176 #include <stdio.h>
00177 #include "sb.h"
00178
00179 #ifndef V6
00180 #define V6 0
00181 #endif
00182
00183 #if V6
00184 #include <stat.h>
00185 #else
00186 #include <sys/types.h>
00187 #include <sys/stat.h>
00188 #if MINIX
00189 #include <fcntl.h>
00190 #else
00191 #include <sys/file.h>
00192 #endif
00193 #endif
00194
00195 extern int errno;
00196 extern char *strerror();
00197
00198
00199 SBFILE sbv_tf;
00200 int (*sbv_debug)();
00201
00202
00203
00204
00205
00206
00207 #define SK_READF 0
00208 #define SK_READB (0|SKM_0BACK|SKM_EOB)
00209 #define SK_WRITEF (0|SKM_EOB)
00210 #define SK_DELF (4|SKM_0BACK)
00211 #define SK_DELB (4|SKM_EOB)
00212 #define SKM_0BACK 01
00213
00214 #define SKM_EOB 02
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232 SBBUF *
00233 sb_open(sbp,sdp)
00234 SBBUF *sbp;
00235 SBSTR *sdp;
00236 { register struct sdblk *sd;
00237 register int cnt;
00238 register WORD *clrp;
00239
00240 if(!sbp) return((SBBUF *)0);
00241 if((sd = sdp) == 0)
00242 { sd = sbx_ndget();
00243 clrp = (WORD *) sd;
00244 cnt = rnddiv(sizeof(struct sdblk));
00245 do { *clrp++ = 0; } while(--cnt);
00246 sd->sdflags = SD_NID;
00247 }
00248 else if(sd->slback)
00249 return((SBBUF *)0);
00250
00251 clrp = (WORD *) sbp;
00252 cnt = rnddiv(sizeof(SBBUF));
00253 do { *clrp++ = 0; } while(--cnt);
00254
00255 sbp->sbcur = sd;
00256
00257
00258
00259
00260
00261 return(sbp);
00262 }
00263
00264
00265
00266
00267
00268
00269 SBSTR *
00270 sb_close(sbp)
00271 SBBUF *sbp;
00272 { register SBBUF *sb;
00273 register struct sdblk *sd;
00274
00275 if((sb = sbp) == 0)
00276 return((SBSTR *)0);
00277 sb_rewind(sb);
00278 sd = sb->sbcur;
00279 sb->sbcur = 0;
00280 sb->sbflags = 0;
00281 return(sd);
00282 }
00283
00284
00285
00286
00287
00288 sb_setovw(sbp)
00289 SBBUF *sbp;
00290 { register SBBUF *sb;
00291 if(sb=sbp)
00292 { sb->sbflags |= SB_OVW;
00293 sb->sbwleft = 0;
00294 }
00295 }
00296
00297 sb_clrovw(sbp)
00298 SBBUF *sbp;
00299 { register SBBUF *sb;
00300 if(sb=sbp) sb->sbflags &= ~SB_OVW;
00301 }
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315 struct sbfile *sbv_ftab[SB_NFILES];
00316
00317 chroff
00318 sbx_fdlen(fd)
00319 int fd;
00320 {
00321 #if !V6
00322 struct stat statb;
00323 #else
00324 struct statb statb;
00325 chroff len;
00326 struct {int hiwd ; int lowd;} foo;
00327 #endif
00328
00329 if(fstat(fd,&statb) < 0) return((chroff)-1);
00330 #if V6
00331 len = statb.i_size1;
00332 len.hiwd = statb.i_size0 & 0377;
00333 return(len);
00334 #else
00335 return((chroff)statb.st_size);
00336 #endif
00337 }
00338
00339 SBSTR *
00340 sb_fduse(ifd)
00341 int ifd;
00342 { register struct sdblk *sd;
00343 register struct sbfile *sf;
00344 register int fd;
00345 chroff len;
00346
00347 if((fd = ifd) < 0 || SB_NFILES <= fd
00348 || sbv_ftab[fd])
00349 return((SBSTR *)0);
00350 if((len = sbx_fdlen(fd)) < 0) return((SBSTR *)0);
00351 sbv_ftab[fd]= sf = (struct sbfile *)sbx_malloc(sizeof(struct sbfile));
00352 sf->sffd = fd;
00353 sf->sfptr1 = sd = sbx_ndget();
00354 sf->sflen = len;
00355 sd->slforw = 0;
00356 sd->slback = 0;
00357 sd->sdforw = 0;
00358 sd->sdback = 0;
00359 sd->sdmem = 0;
00360 sd->sdfile = sf;
00361 sd->sdlen = len;
00362 sd->sdaddr = 0;
00363 return(sd);
00364 }
00365
00366
00367
00368
00369
00370
00371
00372 sb_fdcls(ifd)
00373 int ifd;
00374 { register int fd;
00375
00376 if((fd = ifd) >= 0)
00377 { if(fd >= SB_NFILES) return(0);
00378 return(sbx_fcls(sbv_ftab[fd]));
00379 }
00380 fd = SB_NFILES-1;
00381 do {
00382 sbx_fcls(sbv_ftab[fd]);
00383 } while(--fd);
00384 return(1);
00385 }
00386
00387 sbx_fcls(sfp)
00388 struct sbfile *sfp;
00389 { register struct sbfile *sf;
00390 register int fd;
00391
00392 if((sf = sfp)==0
00393 || sf == &sbv_tf)
00394 return(0);
00395 fd = sf->sffd;
00396 if(sbv_ftab[fd] != sf)
00397 return(sbx_err(0,"SF table inconsistency"));
00398 if(sf->sfptr1)
00399 return(0);
00400 close(fd);
00401 sbv_ftab[fd] = 0;
00402 free(sf);
00403 }
00404
00405
00406
00407
00408 sb_fdinp(sb, fd)
00409 register SBBUF *sb;
00410 int fd;
00411 { register struct sdblk *sd;
00412 register struct sbfile *sf;
00413
00414 if((sf = sbv_ftab[fd]) == 0
00415 || (sd = sb->sbcur) == 0)
00416 return(0);
00417 sd = sbx_beg(sd);
00418 for(; sd; sd = sd->slforw)
00419 if(sd->sdfile == sf)
00420 return(1);
00421 return(0);
00422 }
00423
00424
00425
00426
00427 sb_fsave(sb,fd)
00428 register SBBUF *sb;
00429 int fd;
00430 {
00431 sbx_smdisc(sb);
00432 return(sbx_aout(sbx_beg(sb->sbcur), 2, fd));
00433 }
00434
00435
00436
00437
00438
00439
00440
00441 int
00442 sb_sgetc(sb)
00443 register SBBUF *sb;
00444 {
00445 if(--(sb->sbrleft) >= 0)
00446 return sb_uchartoint(*sb->sbiop++);
00447
00448
00449 sb->sbrleft = 0;
00450 if(sb->sbcur == 0
00451 || (int)sbx_ready(sb,SK_READF,0,SB_BUFSIZ) <= 0)
00452 return(EOF);
00453 return(sb_sgetc(sb));
00454 }
00455
00456
00457
00458
00459
00460
00461 int
00462 sb_sputc(sb,ch)
00463 register SBBUF *sb;
00464 int ch;
00465 {
00466 register struct sdblk *sd;
00467
00468 if(--(sb->sbwleft) >= 0) return(*sb->sbiop++ = ch);
00469
00470 sb->sbwleft = 0;
00471 if((sd = sb->sbcur) == 0)
00472 return(EOF);
00473 if(sb->sbflags&SB_OVW)
00474 { if(sb->sbiop &&
00475 --sb->sbrleft >= 0)
00476 { sd->sdflags |= SD_MOD;
00477 return(*sb->sbiop++ = ch);
00478 }
00479
00480 if((int)sbx_ready(sb,SK_READF,0,SB_BUFSIZ) > 0)
00481 return(sb_sputc(sb,ch));
00482
00483
00484 }
00485
00486
00487 if((int)sbx_ready(sb,SK_WRITEF,SB_SLOP,SB_BUFSIZ) <= 0)
00488 return(EOF);
00489 sb->sbflags |= SB_WRIT;
00490 sb->sbcur->sdflags |= SD_MOD;
00491 return(sb_sputc(sb,ch));
00492 }
00493
00494
00495
00496
00497
00498
00499
00500 int
00501 sb_speekc(sb)
00502 register SBBUF *sb;
00503 {
00504 if (sb->sbrleft <= 0)
00505 { if (sb_sgetc(sb) == EOF)
00506 return EOF;
00507 sb_backc(sb);
00508 }
00509 return sb_uchartoint(*sb->sbiop);
00510 }
00511
00512
00513
00514
00515
00516 int
00517 sb_rgetc(sb)
00518 register SBBUF *sb;
00519 {
00520 register struct smblk *sm;
00521 register struct sdblk *sd;
00522
00523 if((sd=sb->sbcur) && (sm = sd->sdmem)
00524 && sb->sbiop > sm->smaddr)
00525 { if(sb->sbflags&SB_WRIT)
00526 { sm->smuse = sb->sbiop - sm->smaddr;
00527 sb->sbwleft = 0;
00528 sb->sbflags &= ~SB_WRIT;
00529 }
00530 sb->sbrleft++;
00531 return sb_uchartoint(*--sb->sbiop);
00532 }
00533 if((int)sbx_ready(sb,SK_READB,SB_BUFSIZ,0) <= 0)
00534 return(EOF);
00535 return(sb_rgetc(sb));
00536 }
00537
00538
00539
00540
00541 sb_rdelc(sbp)
00542 SBBUF *sbp;
00543 { register SBBUF *sb;
00544 register struct sdblk *sd;
00545
00546 if(((sb=sbp)->sbflags&SB_WRIT)
00547 && sb->sbiop > (sd = sb->sbcur)->sdmem->smaddr)
00548 { sb->sbwleft++;
00549 sb->sbiop--;
00550 sd->sdflags |= SD_MOD;
00551 return;
00552 }
00553 else sb_deln(sb,(chroff) -1);
00554 }
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567 sb_deln(sbp, num)
00568 SBBUF *sbp;
00569 chroff num;
00570 {
00571 register struct sdblk *sd;
00572
00573 if(sd = sb_killn(sbp,num))
00574 sbs_del(sd);
00575 }
00576
00577
00578
00579
00580 struct sdblk *
00581 sb_killn(sbp, num)
00582 SBBUF *sbp;
00583 chroff num;
00584 { register SBBUF *sb;
00585 register struct sdblk *sd, *sd2;
00586 struct sdblk *sdr, *sdx;
00587 chroff savdot;
00588
00589 if((sd = sbx_xcis((sb=sbp),num,&sdr,&savdot)) == 0)
00590 return((struct sdblk *)0);
00591
00592 sb->sbcur->sdflags &= ~SD_LOCK;
00593
00594
00595
00596
00597 if(num >= 0)
00598 sb->sbdot = savdot;
00599
00600
00601 sd2 = sdr;
00602 if(sd2 = sd2->slforw)
00603 { sb->sbcur = sd2;
00604 sb->sboff = 0;
00605 }
00606 else if(sdx = sd->slback)
00607 { sb->sbcur = sdx;
00608 sb->sboff = (sdx->sdmem ?
00609 sdx->sdmem->smuse : sdx->sdlen);
00610 sb->sbdot -= sb->sboff;
00611 }
00612 else sb_open(sb,(SBSTR *)0);
00613
00614
00615 if(sd->slback)
00616 { if(sd->slback->slforw = sd2)
00617 sd2->slback = sd->slback;
00618 sd->slback = 0;
00619 }
00620 else if(sd2) sd2->slback = 0;
00621 (sd2 = sdr)->slforw = 0;
00622
00623 sb->sbcur->sdflags |= SD_LOCK;
00624 sd->sdflags &= ~SD_LCK2;
00625 sd2->sdflags &= ~SD_LCK2;
00626 return(sd);
00627 }
00628
00629
00630
00631
00632 SBSTR *
00633 sb_cpyn(sbp,num)
00634 SBBUF *sbp;
00635 chroff num;
00636 { register SBBUF *sb;
00637 register struct sdblk *sd, *sd2;
00638 struct sdblk *sdr;
00639 chroff savloc;
00640
00641 sb = sbp;
00642 if((sd = sbx_xcis(sb,num,&sdr,&savloc)) == 0)
00643 return((SBSTR *)0);
00644 sd2 = sbx_scpy(sd,sdr);
00645 sb_seek(sb,-num,1);
00646 return(sd2);
00647
00648
00649
00650 }
00651
00652
00653
00654
00655 sb_sins(sbp,sdp)
00656 SBBUF *sbp;
00657 struct sdblk *sdp;
00658 { register SBBUF *sb;
00659 register struct sdblk *sd, *sdx;
00660 chroff inslen;
00661
00662 if((sb = sbp)==0
00663 || (sd = sdp) == 0)
00664 return(0);
00665 if(sd->slback)
00666 return(0);
00667 if((sdx = (struct sdblk *)sbx_ready(sb,SK_DELB)) == 0)
00668 return(0);
00669 inslen = sbs_len(sd);
00670
00671 sd->slback = sdx;
00672 if(sdx->slforw)
00673 { while(sd->slforw)
00674 sd = sd->slforw;
00675 sd->slforw = sdx->slforw;
00676 sd->slforw->slback = sd;
00677 }
00678 sdx->slforw = sdp;
00679 sb->sboff += inslen;
00680 return(1);
00681 }
00682
00683
00684
00685
00686
00687 SBSTR *
00688 sbs_cpy(sdp)
00689 SBSTR *sdp;
00690 { return(sbx_scpy(sdp,(struct sdblk *)0));
00691 }
00692
00693
00694
00695 sbs_del(sdp)
00696 SBSTR *sdp;
00697 { register struct sdblk *sd;
00698
00699 if(sd = sdp)
00700 while(sd = sbx_ndel(sd));
00701 }
00702
00703
00704
00705
00706
00707
00708 SBSTR *
00709 sbs_app(sdp,sdp2)
00710 struct sdblk *sdp,*sdp2;
00711 { register struct sdblk *sd, *sdx;
00712
00713 if(sd = sdp)
00714 { while(sdx = sd->slforw)
00715 sd = sdx;
00716 if(sd->slforw = sdx = sdp2)
00717 sdx->slback = sd;
00718 }
00719 return(sdp);
00720 }
00721
00722
00723
00724 chroff
00725 sbs_len(sdp)
00726 SBSTR *sdp;
00727 { register struct sdblk *sd;
00728 register struct smblk *sm;
00729 chroff len;
00730
00731 if((sd = sdp)==0) return((chroff)0);
00732 len = 0;
00733 for(; sd ; sd = sd->slforw)
00734 { if(sm = sd->sdmem)
00735 len += (chroff)sm->smuse;
00736 else len += sd->sdlen;
00737 }
00738 return(len);
00739 }
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753 sb_seek(sbp, coff, flg)
00754 SBBUF *sbp;
00755 chroff coff;
00756 int flg;
00757 { register SBBUF *sb;
00758 register struct smblk *sm;
00759 register struct sdblk *sd;
00760 SBMO moff;
00761
00762 sb = sbp;
00763 if((sd = sb->sbcur) == 0) return(-1);
00764 if(sb->sbiop == 0)
00765 { switch(flg)
00766 { case 0: if(coff == 0)
00767 return(sb_rewind(sb));
00768 sb->sboff = coff - sb->sbdot;
00769 break;
00770 case 1: sb->sboff += coff;
00771 break;
00772 case 2: sb->sboff += sb_ztell(sb) + coff;
00773 break;
00774 default: return(-1);
00775 }
00776 sbx_norm(sb,0);
00777 return(0);
00778 }
00779 if((sm = sd->sdmem) == 0)
00780 return(sbx_err(-1,"SDMEM 0"));
00781 moff = sb->sbiop - sm->smaddr;
00782 if(sb->sbflags&SB_WRIT)
00783 { sm->smuse = moff;
00784 sb->sbflags &= ~SB_WRIT;
00785 }
00786 sb->sbwleft = 0;
00787 switch(flg)
00788 { case 0:
00789 coff -= sb->sbdot + (chroff)moff;
00790
00791 case 1:
00792 break;
00793
00794 case 2:
00795 coff += sb_ztell(sb);
00796 break;
00797 default: return(-1);
00798 }
00799
00800
00801 if (-(chroff)moff <= coff && coff <= sb->sbrleft)
00802 {
00803 sb->sbiop += coff;
00804 sb->sbrleft -= coff;
00805 return(0);
00806 }
00807
00808
00809 sb->sbrleft = 0;
00810 sb->sbiop = 0;
00811 sb->sboff = coff + (chroff)moff;
00812 sbx_norm(sb,0);
00813 return(0);
00814 }
00815
00816
00817
00818
00819
00820 sb_rewind(sbp)
00821 SBBUF *sbp;
00822 { register SBBUF *sb;
00823 register struct sdblk *sd;
00824
00825 if((sb = sbp)==0) return;
00826 sbx_smdisc(sb);
00827 (sd = sb->sbcur)->sdflags &= ~SD_LOCK;
00828 sd = sbx_beg(sd);
00829
00830
00831 sb->sbcur = sd;
00832 sb->sbdot = 0;
00833 sb->sboff = 0;
00834 }
00835
00836
00837
00838
00839
00840 chroff
00841 sb_tell(sbp)
00842 SBBUF *sbp;
00843 { register SBBUF *sb;
00844 register struct smblk *sm;
00845 register struct sdblk *sd;
00846
00847 if((sd = (sb=sbp)->sbcur) == 0)
00848 return((chroff)-1);
00849 if(sb->sbiop == 0)
00850 return(sb->sbdot + sb->sboff);
00851 if((sm = sd->sdmem) == 0)
00852 return(sbx_err(0,"SDMEM 0"));
00853 return(sb->sbdot + (unsigned)(sb->sbiop - sm->smaddr));
00854 }
00855
00856
00857
00858
00859 chroff
00860 sb_ztell(sbp)
00861 SBBUF *sbp;
00862 { register SBBUF *sb;
00863 register struct smblk *sm;
00864 register struct sdblk *sd;
00865
00866 if((sd = (sb=sbp)->sbcur) == 0)
00867 return((chroff)0);
00868 if(sb->sbiop && (sm = sd->sdmem))
00869 { if(sb->sbflags&SB_WRIT)
00870 return(sbs_len(sd->slforw));
00871
00872
00873
00874
00875 return(sbs_len(sd) - (sb->sbiop - sm->smaddr));
00876 }
00877 else
00878 return(sbs_len(sd) - sb->sboff);
00879 }
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919 struct sdblk *
00920 sbx_ready(sbp,type,cmin,cmax)
00921 SBBUF *sbp;
00922 int type;
00923 SBMO cmin,cmax;
00924 { register SBBUF *sb;
00925 register struct sdblk *sd;
00926 register struct smblk *sm;
00927 int cnt, slop, rem;
00928 SBMO moff;
00929
00930 if((sd = (sb=sbp)->sbcur) == 0)
00931 return(0);
00932 if(sb->sbiop)
00933 { if((sm = sd->sdmem)==0)
00934 return(0);
00935 moff = sb->sbiop - sm->smaddr;
00936 switch(type)
00937 {
00938 case SK_READF:
00939 if(sb->sbrleft > 0)
00940 return(1);
00941 sbx_smdisc(sb);
00942 if((sd = sbx_next(sb)) == 0)
00943 return(-1);
00944 break;
00945
00946 case SK_READB:
00947 if(moff)
00948 { if(sb->sbflags&SB_WRIT)
00949 { sm->smuse = moff;
00950 sb->sbflags &= ~SB_WRIT;
00951 }
00952 sb->sbwleft = 0;
00953 return(1);
00954 }
00955 sbx_smdisc(sb);
00956 break;
00957
00958 case SK_WRITEF:
00959 if(sb->sbrleft <= 0)
00960 sb->sbwleft = sm->smlen - moff;
00961 if(sb->sbwleft > 0)
00962 return(1);
00963
00964 sbx_smdisc(sb);
00965 break;
00966
00967 case SK_DELF:
00968 if(sb->sbrleft <= 0)
00969 { sbx_smdisc(sb);
00970 return(sbx_next(sb));
00971 }
00972 sbx_smdisc(sb);
00973 if(moff == 0)
00974 return(sd);
00975 break;
00976
00977 case SK_DELB:
00978 if(sb->sbrleft <= 0)
00979 { sbx_smdisc(sb);
00980 return(sd);
00981 }
00982 sbx_smdisc(sb);
00983 break;
00984
00985 default:
00986 return(0);
00987 }
00988 }
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999 sd = sbx_norm(sb,type);
01000 sm = sd->sdmem;
01001 switch(type)
01002 {
01003 case SK_READB:
01004 if(sb->sboff == 0)
01005 return(-1);
01006 if(sm) goto sekr2;
01007 else goto sekr1;
01008
01009 case SK_READF:
01010 if(sm) goto sekr2;
01011 if(sb->sboff == sd->sdlen)
01012 return(-1);
01013 sekr1: slop = SB_SLOP;
01014 sekr3: if(sb->sboff > cmin+slop)
01015 {
01016 sbx_split(sd,(chroff)(sb->sboff - cmin));
01017 sd = sbx_next(sb);
01018 sb->sboff = cmin;
01019
01020 }
01021 if(sd->sdlen > sb->sboff+cmax+slop)
01022 sbx_split(sd,(chroff)(sb->sboff+cmax));
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034 cnt = sd->sdlen;
01035 if(rem = rndrem(sd->sdaddr))
01036 cnt += rem;
01037 if(sm == 0)
01038 { sm = sbx_mget(SB_SLOP,cnt);
01039 if(sm->smlen < cnt)
01040 { slop = 0;
01041 cmin = 0;
01042 cmax = sm->smlen - (WDSIZE-1);
01043 if(type == SK_READB)
01044 { cmin = cmax; cmax = 0; }
01045 goto sekr3;
01046 }
01047 }
01048 else if(sm->smlen < cnt)
01049 { sbx_err(0,"Readin blksiz err");
01050 if((cmax /= 2) > 0) goto sekr3;
01051 return(0);
01052 }
01053 if(rem)
01054 { sm = sbx_msplit(sm, (SBMO)rem);
01055 sbm_mfree(sm->smback);
01056 }
01057 sd->sdmem = sm;
01058 sm->smuse = sd->sdlen;
01059
01060 if(sd->sdfile == 0)
01061 return(sbx_err(0,"No file"));
01062 if(!sbx_rdf(sd->sdfile->sffd, sm->smaddr, sm->smuse,
01063 1, sd->sdaddr))
01064 return(sbx_err(0,"Readin SD: %o", sd));
01065
01066
01067 sekr2: sbx_sbrdy(sb);
01068 sb->sbwleft = 0;
01069 break;
01070
01071 case SK_WRITEF:
01072 if(sm == 0)
01073 {
01074 if(sd->sdlen)
01075 { sbx_split(sd, sb->sboff);
01076 sd = sbx_next(sb);
01077 if(sd->sdlen)
01078
01079 sbx_split(sd, (chroff) 0);
01080 }
01081 goto sekwget;
01082 }
01083
01084
01085 moff = sm->smuse;
01086 if(sb->sboff == moff)
01087 { if(sm->smlen > moff)
01088 goto sekw;
01089 if(sm->smforw
01090 && (sm->smforw->smflags
01091 & (SM_USE|SM_NXM))==0
01092 && (sd->sdflags&SD_MOD)
01093 && sm->smlen < cmax)
01094 {
01095
01096
01097
01098 cmin = cmax - sm->smlen;
01099 if(cmin&01) cmin++;
01100 if(sm->smforw->smlen <= cmin)
01101 { sbm_mmrg(sm);
01102 goto sekw;
01103 }
01104 sm->smforw->smlen -= cmin;
01105 sm->smforw->smaddr += cmin;
01106 sm->smlen += cmin;
01107 goto sekw;
01108 }
01109
01110 if(sd->slforw && (sm = sd->slforw->sdmem)
01111 && sm->smuse == 0
01112 && sm->smlen)
01113 { sd = sbx_next(sb);
01114 goto sekw;
01115 }
01116 }
01117
01118
01119 sbx_split(sd, sb->sboff);
01120 if(sd->sdmem)
01121 { sd = sbx_next(sb);
01122 if(sd->sdmem)
01123 sbx_split(sd, (chroff) 0);
01124 }
01125
01126
01127 sekwget: sd->sdmem = sm = sbx_mget(cmin,cmax);
01128 sm->smuse = 0;
01129 sekw: sbx_sbrdy(sb);
01130 return(1);
01131
01132 case SK_DELF:
01133 if(sb->sboff == 0)
01134 return(sd);
01135 sbx_split(sd, sb->sboff);
01136 return(sbx_next(sb));
01137
01138 case SK_DELB:
01139 if(sb->sboff !=
01140 (sm ? (chroff)(sm->smuse) : sd->sdlen))
01141 sbx_split(sd, sb->sboff);
01142 return(sd);
01143 break;
01144
01145 default:
01146 return(0);
01147 }
01148 return(1);
01149 }
01150
01151 struct sdblk *
01152 sbx_next (sbp)
01153 SBBUF *sbp;
01154 { register SBBUF *sb;
01155 register struct sdblk *sd, *sdf;
01156 if((sdf = (sd = (sb=sbp)->sbcur)->slforw) == 0)
01157 return((struct sdblk *)0);
01158 sb->sbdot += (sd->sdmem ? (chroff)sd->sdmem->smuse : sd->sdlen);
01159 sb->sboff = 0;
01160 sd->sdflags &= ~SD_LOCK;
01161 sdf->sdflags |= SD_LOCK;
01162 sb->sbcur = sdf;
01163 return(sdf);
01164 }
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189 struct sdblk *
01190 sbx_norm(sbp,mode)
01191 SBBUF *sbp;
01192 int mode;
01193 { register struct sdblk *sd;
01194 register struct smblk *sm;
01195 register SBBUF *sb;
01196 chroff len;
01197
01198 if((sd = (sb=sbp)->sbcur) == 0)
01199 { sb->sbdot = 0;
01200 sb->sboff = 0;
01201 return(sd);
01202 }
01203 sd->sdflags &= ~SD_LOCK;
01204
01205 if(sb->sboff >= (mode&01))
01206 for(;;)
01207 { if(sm = sd->sdmem)
01208 len = sm->smuse;
01209 else len = sd->sdlen;
01210 if(sb->sboff <= len)
01211 if(sb->sboff < len
01212 || (mode&SKM_0BACK))
01213 { if((mode&SKM_EOB)
01214 && sb->sboff == 0
01215 && sd->slback)
01216 { sd = sd->slback;
01217 sb->sboff = (sm = sd->sdmem)
01218 ? (chroff)(sm->smuse) : sd->sdlen;
01219 sb->sbdot -= sb->sboff;
01220 }
01221 break;
01222 }
01223 if(sd->slforw == 0)
01224 { sb->sboff = len;
01225 break;
01226 }
01227 sd = sd->slforw;
01228 sb->sboff -= len;
01229 sb->sbdot += len;
01230 }
01231 else
01232 for(;;)
01233 { if(sd->slback == 0)
01234 { sb->sboff = 0;
01235 sb->sbdot = 0;
01236 break;
01237 }
01238 sd = sd->slback;
01239 if(sm = sd->sdmem)
01240 len = sm->smuse;
01241 else len = sd->sdlen;
01242 sb->sbdot -= len;
01243 if((sb->sboff += len) >= 0)
01244 if(sb->sboff > 0
01245 || !(mode&SKM_0BACK))
01246 { if((mode&SKM_EOB) == 0
01247 && sb->sboff == len
01248 && sd->slforw)
01249 { sd = sd->slforw;
01250 sb->sboff = 0;
01251 sb->sbdot += len;
01252 }
01253 break;
01254 }
01255 }
01256 sb->sbcur = sd;
01257 sd->sdflags |= SD_LOCK;
01258 return(sd);
01259 }
01260
01261
01262 struct sdblk *
01263 sbx_beg(sdp)
01264 struct sdblk *sdp;
01265 { register struct sdblk *sd, *sdx;
01266 if(sd = sdp)
01267 while(sdx = sd->slback)
01268 sd = sdx;
01269 return(sd);
01270 }
01271
01272
01273 sbx_smdisc(sbp)
01274 SBBUF *sbp;
01275 { register SBBUF *sb;
01276 register struct smblk *sm;
01277 register struct sdblk *sd;
01278
01279 sb = sbp;
01280 if((sd = sb->sbcur) == 0
01281 || (sm = sd->sdmem) == 0)
01282 return;
01283 if(sb->sbflags&SB_WRIT)
01284 { sm->smuse = sb->sbiop - sm->smaddr;
01285 sb->sbflags &= ~SB_WRIT;
01286 }
01287 sb->sboff = sb->sbiop - sm->smaddr;
01288 sb->sbiop = 0;
01289 sb->sbrleft = sb->sbwleft = 0;
01290 }
01291
01292 sbx_sbrdy(sbp)
01293 SBBUF *sbp;
01294 { register SBBUF *sb;
01295 register struct sdblk *sd;
01296 register struct smblk *sm;
01297
01298 if((sd = (sb=sbp)->sbcur) == 0
01299 || (sm = sd->sdmem) == 0)
01300 return;
01301 sd->sdflags |= SD_LOCK;
01302 sb->sbiop = sm->smaddr + sb->sboff;
01303 if(sb->sbrleft = sm->smuse - sb->sboff)
01304 sb->sbwleft = 0;
01305 else sb->sbwleft = sm->smlen - sm->smuse;
01306 }
01307
01308
01309
01310
01311
01312 struct sdblk *
01313 sbx_scpy(sdp,sdlast)
01314 struct sdblk *sdp, *sdlast;
01315 { register struct sdblk *sd, *sd2, *sdn;
01316 struct sdblk *sdr;
01317
01318 if((sd = sdp) == 0) return((struct sdblk *)0);
01319 sdn = 0;
01320 do {
01321 sd->sdflags |= SD_LCK2;
01322 sd2 = sbx_sdcpy(sd);
01323 if(sd2->slback = sdn)
01324 { sdn->slforw = sd2;
01325 sdn->sdflags &= ~SD_LOCKS;
01326 }
01327 else sdr = sd2;
01328 sdn = sd2;
01329 sd->sdflags &= ~SD_LCK2;
01330 } while(sd != sdlast && (sd = sd->slforw));
01331 sd2->slforw = 0;
01332 sd2->sdflags &= ~SD_LOCKS;
01333 return(sdr);
01334 }
01335
01336
01337
01338
01339
01340
01341
01342 struct sdblk *
01343 sbx_sdcpy(sdp)
01344 struct sdblk *sdp;
01345 { register struct sdblk *sd, *sd2;
01346 register struct smblk *sm, *sm2;
01347
01348 if((sd = sdp) == 0) return((struct sdblk *)0);
01349 sd2 = sbx_ndget();
01350 bcopy((SBMA)sd, (SBMA)sd2, sizeof(struct sdblk));
01351 sd2->slforw = 0;
01352 sd2->slback = 0;
01353 if(sd2->sdfile)
01354 { sd->sdforw = sd2;
01355 sd2->sdback = sd;
01356 if(sd2->sdforw)
01357 sd2->sdforw->sdback = sd2;
01358 }
01359 if(sm = sd2->sdmem)
01360 { if(sm2 = sbm_mget(sm->smuse,sm->smuse))
01361 { bcopy(sm->smaddr,sm2->smaddr,sm->smuse);
01362 sm2->smuse = sm->smuse;
01363 sd2->sdmem = sm2;
01364 }
01365 else
01366 { if(sd2->sdflags&SD_MOD)
01367 sbx_aout(sd2,1);
01368 sd2->sdmem = 0;
01369 }
01370 }
01371 return(sd2);
01372 }
01373
01374
01375
01376
01377
01378
01379
01380
01381 struct sdblk *
01382 sbx_xcis(sbp,num,asd2,adot)
01383 SBBUF *sbp;
01384 chroff num, *adot;
01385 struct sdblk **asd2;
01386 { register SBBUF *sb;
01387 register struct sdblk *sd, *sd2;
01388 int dirb;
01389
01390 if((sb = sbp) == 0) return((struct sdblk *)0);
01391 dirb = 0;
01392 if(num == 0) return((struct sdblk *)0);
01393 if(num < 0) dirb++;
01394
01395 if((sd = (struct sdblk *)
01396 sbx_ready(sb, (dirb ? SK_DELB : SK_DELF))) == 0)
01397 return((struct sdblk *)0);
01398 sd->sdflags |= SD_LCK2;
01399 *adot = sb->sbdot;
01400 sb->sboff += num;
01401
01402 if((sd2 = (struct sdblk *)
01403 sbx_ready(sb,(dirb ? SK_DELF : SK_DELB))) == 0)
01404 { sd->sdflags &= ~SD_LCK2;
01405 return(
01406 (struct sdblk *)sbx_err(0,"KILLN SD2 failed"));
01407 }
01408 sd2->sdflags |= SD_LCK2;
01409
01410
01411
01412
01413 if(dirb)
01414 {
01415
01416
01417
01418
01419 if(sd->slforw == sd2)
01420 { sd->sdflags &= ~SD_LCK2;
01421 sd = sd2;
01422 }
01423 else
01424 {
01425
01426 *asd2 = sd;
01427 return(sd2);
01428 }
01429 }
01430 *asd2 = sd2;
01431 return(sd);
01432 }
01433
01434
01435
01436
01437
01438
01439
01440
01441 struct sdblk *
01442 sbx_split(sdp, coff)
01443 struct sdblk *sdp;
01444 chroff coff;
01445 { register struct sdblk *sd, *sdf, *sdx;
01446
01447 if((sd=sdp) == 0)
01448 return((struct sdblk *)0);
01449 sd->sdflags |= SD_LOCK;
01450 if(sd->sdflags&SD_MOD)
01451 sbx_npdel(sd);
01452 sdf = sbx_ndget();
01453 bcopy((SBMA)sd, (SBMA)sdf, (sizeof (struct sdblk)));
01454
01455
01456
01457 if(coff == 0)
01458 {
01459 if(sdf->sdfile)
01460 { if(sdx = sdf->sdback)
01461 sdx->sdforw = sdf;
01462 else sdf->sdfile->sfptr1 = sdf;
01463 if(sdx = sdf->sdforw)
01464 sdx->sdback = sdf;
01465 }
01466 sdx = sd;
01467 goto nulsdx;
01468 }
01469 else if(sd->sdmem)
01470 if(coff >= sd->sdmem->smuse)
01471 goto nulsdf;
01472 else sdf->sdmem = sbx_msplit(sd->sdmem, (SBMO)coff);
01473 else if(coff >= sd->sdlen)
01474 nulsdf: { sdx = sdf;
01475 nulsdx: sdx->sdforw = 0;
01476 sdx->sdback = 0;
01477 sdx->sdmem = 0;
01478 sdx->sdfile = 0;
01479 sdx->sdlen = 0;
01480 sdx->sdaddr = 0;
01481 goto nulskp;
01482 }
01483 if(sd->sdfile)
01484 { sdf->sdlen -= coff;
01485 sdf->sdaddr += coff;
01486 sd->sdlen = coff;
01487
01488
01489
01490
01491
01492
01493
01494 if(sdf->sdlen > 0)
01495 { while((sdx = sd->sdforw)
01496 && sdf->sdaddr > sdx->sdaddr)
01497 sd = sdx;
01498 sdf->sdback = sd;
01499 if(sdf->sdforw = sd->sdforw)
01500 sdf->sdforw->sdback = sdf;
01501 sd->sdforw = sdf;
01502 sd = sdp;
01503 }
01504 else
01505 { sdf->sdforw = 0;
01506 sdf->sdback = 0;
01507 sdf->sdfile = 0;
01508 }
01509 }
01510
01511 nulskp: sdf->slback = sd;
01512 if(sd->slforw)
01513 sd->slforw->slback = sdf;
01514 sd->slforw = sdf;
01515
01516 sdf->sdflags &= ~SD_LOCKS;
01517 return(sd);
01518 }
01519
01520
01521
01522
01523 struct smblk *
01524 sbx_msplit(smp, size)
01525 struct smblk *smp;
01526 SBMO size;
01527 { register struct smblk *sm, *smx;
01528 register int lev;
01529
01530 lev = 0;
01531 while((smx = sbm_split((sm = smp), size)) == 0)
01532 sbx_comp(SB_BUFSIZ,lev++);
01533 if(sm->smlen >= sm->smuse)
01534 smx->smuse = 0;
01535 else
01536 { smx->smuse = sm->smuse - sm->smlen;
01537 sm->smuse = sm->smlen;
01538 }
01539 return(smx);
01540 }
01541
01542
01543
01544
01545
01546
01547 struct sdblk *
01548 sbx_ndel(sdp)
01549 struct sdblk *sdp;
01550 { register struct sdblk *sd, *sdx;
01551 register struct smblk *sm;
01552
01553 sd = sdp;
01554 if(sm = sd->sdmem)
01555 { sbm_mfree(sm);
01556 sd->sdmem = 0;
01557 }
01558 if(sdx = sd->slback)
01559 sdx->slforw = sd->slforw;
01560 if(sd->slforw)
01561 sd->slforw->slback = sdx;
01562
01563
01564 if(sd->sdfile)
01565 sbx_npdel(sd);
01566
01567 sdx = sd->slforw;
01568 sbx_ndfre(sd);
01569 return(sdx);
01570 }
01571
01572 sbx_npdel(sdp)
01573 struct sdblk *sdp;
01574 { register struct sdblk *sd, *sdx;
01575 register struct sbfile *sf;
01576
01577 if((sf = (sd=sdp)->sdfile) == 0)
01578 return;
01579 if(sdx = sd->sdback)
01580 sdx->sdforw = sd->sdforw;
01581 else
01582 sf->sfptr1 = sd->sdforw;
01583 if(sdx = sd->sdforw)
01584 sdx->sdback = sd->sdback;
01585 sd->sdfile = 0;
01586 sd->sdlen = 0;
01587 }
01588
01589
01590 struct sdblk *sbx_nfl;
01591
01592 struct sdblk *
01593 sbx_ndget()
01594 { register struct sdblk *sd;
01595 register int lev;
01596
01597 lev = 0;
01598 while((sd = sbx_nfl) == 0
01599
01600 && (sd = sbm_nmak((sizeof (struct sdblk)),SM_DNODS)) == 0)
01601
01602 sbx_comp(sizeof(struct sdblk)*SM_DNODS,lev++);
01603
01604 sbx_nfl = sd->slforw;
01605 sd->sdflags = SD_NID;
01606 return(sd);
01607 }
01608
01609 sbx_ndfre(sdp)
01610 struct sdblk *sdp;
01611 { register struct sdblk *sd;
01612 (sd = sdp)->sdflags = 0;
01613 sd->slforw = sbx_nfl;
01614 sbx_nfl = sd;
01615 }
01616
01617 SBMA
01618 sbx_malloc(size)
01619 unsigned size;
01620 {
01621 register int lev;
01622 register SBMA res;
01623
01624 lev = 0;
01625 while((res = (SBMA)malloc(size)) == 0)
01626 sbx_comp(size,lev++);
01627 return(res);
01628 }
01629
01630 struct smblk *
01631 sbx_mget(cmin,cmax)
01632 SBMO cmin, cmax;
01633 { register struct smblk *sm;
01634 register int lev, csiz;
01635
01636 lev = 0;
01637 csiz = cmax;
01638 for(;;)
01639 { if(sm = sbm_mget(csiz,cmax))
01640 return(sm);
01641 sbx_comp(csiz,lev++);
01642 if(sm = sbm_mget(csiz,cmax))
01643 return(sm);
01644 if((csiz >>= 1) < cmin)
01645 csiz = cmin;
01646 }
01647 }
01648
01649 chroff sbv_taddr;
01650 struct sdblk *sbv_tsd;
01651
01652 #define sbx_qlk(sd) (sd->sdflags&SD_LOCKS)
01653
01654 #if 0
01655 This is the compaction routine, which is the key to the
01656 entire scheme. Paging text to and from disk is trivial, but the
01657 ability to merge blocks is the important thing since it allows
01658 flushing the pointer information as well as the actual text! This
01659 eliminates fragmentation as a fatal problem.
01660 There are a variety of ways that storage can be reclaimed:
01661
01662 - "pure" in-core blocks can be flushed instantly.
01663 - "impure" incore blocks can be written to tempfile storage and flushed.
01664 - The SM node freelist can be compacted so as to flush memory which is
01665 used for nothing but holding free nodes.
01666 - The SD node freelist can be compacted, ditto.
01667 - SBBUFs can be compacted, by:
01668 - Merging logically & physically adjacent on-disk pieces
01669 - merging logically & physically adjacent in-core pieces
01670 - merging logically adjacent in-core pieces
01671 - merging logically adjacent disk pieces, by reading in
01672 and then writing out to tempfile storage.
01673 Worst case would reduce whole sbstr to single tempfile block.
01674
01675 Problems:
01676 What is "optimal" algorithm for typical usage?
01677 Must go over all code to make sure right things get locked
01678 and unlocked to avoid having rug pulled out from under.
01679 Could have optional "registration table" for sbstruc; if exist
01680 in table, can check during GC. If find one, can first
01681 do sbx_smdisc and then repoint sbcur to 1st block,
01682 with sbdot of 0 and sboff of sb_tell(). This allows
01683 reducing whole thing to one block even tho "locked".
01684 Never touch stuff locked with SD_LCK2, though.
01685 Also may need way to protect the sbstr SD actually being
01686 pointed to by current sbx routine processing.
01687 Could have count of # nodes free for SM and SD; don''t GC
01688 unless # is some number greater than size of a node block!
01689 Have different levels of compaction; pass level # down thru calls
01690 so as to invoke progressively sterner compaction measures.
01691 Can invoke sbx_comp with any particular level!
01692 Must have list somewhere of SBBUFs? or maybe OK to scan core
01693 for SM_DNODS, then scan sdblks?
01694 Screw: could happen that stuff gets flushed (cuz pure) or even
01695 written out to tempfile, and then we have to read it back
01696 in so as to compact more stuff into tempfile... how to avoid?
01697 If pure stuff small and next to impure stuff, merge?
01698 Some calls just want to get another free node and don''t need
01699 new core. How to indicate this? How to decide between
01700 freeing up used nodes, and creating new node freelist?
01701 #endif
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712 extern struct smblk *sbm_list;
01713 sbx_comp(cmin,lev)
01714 int cmin, lev;
01715 { int sbx_sdgc();
01716
01717 if(lev > 100)
01718 abort();
01719 if(lev > 10)
01720 return(sbx_err(0,"GC loop, cannot free block of size %d",
01721 cmin));
01722
01723
01724 sbm_nfor(SM_DNODS,sizeof(struct sdblk),sbx_sdgc,lev);
01725 }
01726
01727
01728 sbx_sdgc(sdp,lev)
01729 struct sdblk *sdp;
01730 int lev;
01731 { register struct sdblk *sd, *sdf;
01732 register struct smblk *sm;
01733 struct smblk *smf, *sbm_exp ();
01734 SBMO more;
01735
01736 sd = sdp;
01737 if(sbx_qlk(sd)) return(0);
01738 sm = sd->sdmem;
01739 sdf = sd->slforw;
01740 if (lev < 4) goto lev3;
01741
01742
01743
01744 while((sdf = sd->slback) && !sbx_qlk(sdf))
01745 sd = sdf;
01746 if((sdf = sd->slforw) == 0
01747 || sbx_qlk(sdf))
01748 { if(sm = sd->sdmem)
01749 { if(sd->sdflags&SD_MOD)
01750 sbx_aout(sd, 1);
01751 sbm_mfree(sm);
01752 sd->sdmem = 0;
01753 }
01754 return(0);
01755 }
01756
01757 sbx_aout(sd, 0);
01758 return(0);
01759
01760 lev3:
01761 lev2:
01762 lev1: if(lev >= 1)
01763 { if(!sm || !sdf) return(0);
01764 while(((smf = sdf->sdmem) && !(sdf->sdflags&SD_LOCKS)
01765 && (more = smf->smuse + sm->smuse) < SB_BUFSIZ) )
01766 { if(sm->smforw != smf
01767 && more > sm->smlen)
01768 { sm = sbm_exp(sm,more);
01769 if(!sm) return(0);
01770 sd->sdmem = sm;
01771 }
01772 bcopy(smf->smaddr,
01773 sm->smaddr + sm->smuse, smf->smuse);
01774 sm->smuse = more;
01775 if(sm->smforw == smf)
01776 { sdf->sdmem = 0;
01777 sbm_mmrg(sm);
01778 if(sm->smlen > more+SB_SLOP)
01779 sbm_mfree(sbm_split(sm, more));
01780
01781
01782 }
01783 sd->sdflags |= SD_MOD;
01784 if(sdf = sbx_ndel(sdf))
01785 continue;
01786 return(0);
01787 }
01788 }
01789
01790 if(lev <= 0)
01791
01792 { if(sm)
01793 { if(sm->smuse == 0)
01794 sd->sdlen = 0;
01795 else if((sd->sdflags&SD_MOD) == 0
01796 && sm->smuse > 64)
01797 { sbm_mfree(sm);
01798 sd->sdmem = 0;
01799 goto lev0adj;
01800 }
01801 else goto lev0adj;
01802 }
01803
01804 if(sd->sdlen == 0
01805 && sd->slback)
01806 { sbx_ndel(sd);
01807 if((sd = sdf) == 0)
01808 return(0);
01809 sdf = sd->slforw;
01810 }
01811 lev0adj:
01812
01813
01814
01815 if((sd->sdflags&SD_MOD) == 0
01816 && sdf && (sdf->sdflags&(SD_LOCKS|SD_MOD)) == 0
01817 && sd->sdfile && (sd->sdfile == sdf->sdfile)
01818 && (sd->sdaddr + sd->sdlen) == sdf->sdaddr )
01819 { sd->sdlen += sdf->sdlen;
01820 sbx_ndel(sdf);
01821 if(sm = sd->sdmem)
01822 { sbm_mfree(sm);
01823 sd->sdmem = 0;
01824 }
01825 }
01826 return(0);
01827 }
01828 return(0);
01829 }
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848 sbx_aout(sdp,flag,fd)
01849 struct sdblk *sdp;
01850 int flag, fd;
01851 { register struct sdblk *sd;
01852 register struct smblk *sm;
01853 register int cnt;
01854 int ifd, ofd, skflg, rem;
01855 chroff inlen;
01856 extern SBMA sbm_lowaddr;
01857 char buf[SB_BUFSIZ+16];
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872 int botchflg;
01873 chroff outptr, inptr;
01874
01875 if((sd = sdp)==0) return;
01876 ofd = sbv_tf.sffd;
01877 if(flag==0)
01878 { sbx_tset(sbx_qlen(sd),0);
01879 outptr = sbv_taddr;
01880 }
01881 else if (flag==1)
01882
01883 { if(sm = sd->sdmem)
01884 { cnt = rndrem(sm->smaddr - sbm_lowaddr);
01885 sbx_tset((chroff)(sm->smuse),cnt);
01886 }
01887 else
01888 { cnt = rndrem(sd->sdaddr);
01889 sbx_tset(sd->sdlen, cnt);
01890 }
01891 outptr = sbv_taddr;
01892 }
01893 else
01894 { ofd = fd;
01895 outptr = 0;
01896 }
01897
01898 for(; sd;)
01899 { if(flag==0 && sbx_qlk(sd))
01900 break;
01901 if(sm = sd->sdmem)
01902 { if(cnt = sm->smuse)
01903 if(write(ofd, sm->smaddr, cnt) != cnt)
01904 return(sbx_err(errno,"Swapout wrt err"));
01905 outptr += cnt;
01906 if(flag==0)
01907 { sd->sdmem = 0;
01908 sbm_mfree(sm);
01909 }
01910 inlen = cnt;
01911 }
01912 else if(inlen = sd->sdlen)
01913 { if(sd->sdfile == 0)
01914 return(sbx_err(errno,"Sdfile 0, SD %o",sd));
01915
01916 botchflg = ((ifd = sd->sdfile->sffd) == ofd) ? 1 : 0;
01917 skflg = 1;
01918 inptr = sd->sdaddr;
01919
01920
01921
01922
01923 rem = rndrem(inptr);
01924 cnt = SB_BUFSIZ - (int)(inptr%SB_BUFSIZ);
01925 while(inlen > 0)
01926 {
01927 if(inlen < cnt) cnt = inlen;
01928 if(!sbx_rdf(ifd, buf+rem, cnt, skflg, inptr))
01929 return(sbx_err(errno,"Swapout err, SD %o",sd));
01930
01931 if(skflg = botchflg)
01932 { if(lseek(ofd,outptr,0) < 0)
01933 return(sbx_err(errno,
01934 "Swapout sk err"));
01935 inptr += cnt;
01936 }
01937 if(write(ofd, buf+rem, cnt) != cnt)
01938 return(sbx_err(errno,
01939 "Swapout wrt err"));
01940 outptr += cnt;
01941 inlen -= cnt;
01942 cnt = SB_BUFSIZ;
01943 rem = 0;
01944 }
01945 inlen = sd->sdlen;
01946 }
01947
01948
01949 if(flag == 2)
01950 goto donxt;
01951 if(sd != sdp)
01952 { sdp->sdlen += inlen;
01953 sd = sbx_ndel(sd);
01954 continue;
01955 }
01956
01957
01958 if(sd->sdfile
01959 && sd != sbv_tsd)
01960 sbx_npdel(sd);
01961 sd->sdlen = inlen;
01962 sd->sdfile = &sbv_tf;
01963 sd->sdaddr = sbv_taddr;
01964 sd->sdflags &= ~SD_MOD;
01965
01966
01967 if(sd == sbv_tsd)
01968 goto next;
01969 if(sd->sdback = sbv_tsd)
01970 { sd->sdforw = sbv_tsd->sdforw;
01971 sd->sdback->sdforw = sd;
01972 }
01973 else
01974 { sd->sdforw = sbv_tf.sfptr1;
01975 sbv_tf.sfptr1 = sd;
01976 }
01977 if(sd->sdforw)
01978 sd->sdforw->sdback = sd;
01979
01980 next: if(flag==1)
01981 break;
01982 donxt: sd = sd->slforw;
01983 }
01984 return(0);
01985 }
01986
01987
01988 chroff
01989 sbx_qlen(sdp)
01990 struct sdblk *sdp;
01991 { register struct sdblk *sd;
01992 register struct smblk *sm;
01993 chroff len;
01994
01995 len = 0;
01996 for(sd = sdp; sd && !sbx_qlk(sd); sd = sd->slforw)
01997 if(sm = sd->sdmem)
01998 len += (chroff)sm->smuse;
01999 else len += sd->sdlen;
02000 return(len);
02001 }
02002
02003
02004
02005
02006
02007
02008
02009
02010 sbx_tset(loff, align)
02011 chroff loff;
02012 int align;
02013 { register int fd;
02014
02015 if(sbv_tf.sffd <= 0)
02016 {
02017
02018
02019
02020
02021
02022
02023 #ifdef O_T20_WILD
02024 extern char *tmpnam();
02025 fd = open(tmpnam((char *)NULL),
02026 O_RDWR | O_CREAT | O_TRUNC | O_BINARY);
02027 if(fd < 0)
02028 return(sbx_err(0,"Swapout creat err"));
02029 #else
02030 static char fcp[] = "/tmp/sbd.XXXXXX";
02031 if((fd = creat(mktemp(fcp),0600)) < 0)
02032 return(sbx_err(0,"Swapout creat err"));
02033
02034 close(fd);
02035 if((fd = open(fcp,2)) < 0)
02036 return(sbx_err(0,"Swapout open err"));
02037 unlink(fcp);
02038 #endif
02039
02040 sbv_tf.sffd = fd;
02041 sbv_tf.sfptr1 = 0;
02042 sbv_ftab[fd] = &sbv_tf;
02043 sbv_taddr = 0;
02044 return;
02045 }
02046 sbv_tsd = sbx_ffnd(&sbv_tf, loff+align, &sbv_taddr);
02047 sbv_taddr += align;
02048 if(lseek(sbv_tf.sffd, sbv_taddr, 0) < 0)
02049 return(sbx_err(0,"Swapout seek err: (%d,%ld,0) %d %s",
02050 sbv_tf.sffd, sbv_taddr, errno, strerror(errno)));
02051
02052 }
02053
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063 struct sdblk *
02064 sbx_ffnd(sfp, size, aloc)
02065 SBFILE *sfp;
02066 chroff size, *aloc;
02067 { register struct sdblk *sd, *sds, *sdl;
02068 chroff cur;
02069
02070 cur = 0;
02071 sds = 0;
02072 sd = sfp->sfptr1;
02073 redo: for(; sd ; sd = (sds=sd)->sdforw)
02074 { if(cur < sd->sdaddr)
02075 { if(size <= (sd->sdaddr - cur))
02076 break;
02077 }
02078 else if(cur >=(sd->sdaddr + sd->sdlen))
02079 continue;
02080
02081 cur = sd->sdaddr + sd->sdlen;
02082 cur = (long)rndup(cur);
02083 }
02084 *aloc = cur;
02085
02086
02087
02088
02089
02090 sdl = sd;
02091 for(sd = sfp->sfptr1; sd; sd = sd->sdforw)
02092 { if(cur < sd->sdaddr)
02093 { if(size <= (sd->sdaddr - cur))
02094 continue;
02095 }
02096 else if(cur >= (sd->sdaddr + sd->sdlen))
02097 continue;
02098
02099 sbx_err(0,"FFND blew it, but recovered. SD %o siz %ld",
02100 sd, size);
02101 sd = (sds = sdl)->sdforw;
02102 goto redo;
02103 }
02104
02105
02106 return(sds);
02107 }
02108
02109 sbx_rdf(fd,addr,cnt,skflg,loc)
02110 register int fd;
02111 char *addr;
02112 int skflg;
02113 chroff loc;
02114 { register int rres, eres;
02115 long lres;
02116 char *errtyp, *ftyp;
02117 chroff curlen;
02118
02119 errno = 0;
02120 if(skflg && (lres = lseek(fd, (long)loc, 0)) == -1)
02121 { errtyp = "Sk err";
02122 goto errhan;
02123 }
02124 if((rres = read(fd, addr, cnt)) != cnt)
02125 { lres = rres;
02126 errtyp = "Rd err";
02127 goto errhan;
02128 }
02129 return(rres);
02130 errhan:
02131 eres = errno;
02132 if(fd == sbv_tf.sffd)
02133 { ftyp = "(swap)";
02134 curlen = 0;
02135 }
02136 else {
02137 ftyp = "";
02138 curlen = sbx_fdlen(fd);
02139 if(sbv_ftab[fd] &&
02140 (curlen != sbv_ftab[fd]->sflen))
02141 if(sbx_rugpull(fd))
02142 return(cnt);
02143 }
02144 sbx_err(0,"%s %d:%s, %ld:(%d%s,%o,%d)=%ld (fl %ld)",
02145 errtyp, eres, strerror(eres),
02146 loc, fd, ftyp, addr, cnt, lres,
02147 curlen);
02148 return(0);
02149 }
02150
02151
02152
02153
02154
02155
02156
02157
02158
02159
02160
02161
02162 sbx_rugpull(fd)
02163 register int fd;
02164 { int sbx_unpur();
02165
02166
02167
02168
02169 sbm_nfor(SM_DNODS, sizeof(struct sdblk), sbx_unpur, sbv_ftab[fd]);
02170
02171 if((int)sbv_debug == 1 || !sbv_debug)
02172 return(0);
02173 return((*sbv_debug)(2,(int *)0,"",fd));
02174 }
02175 sbx_unpur(sd, sf)
02176 register struct sdblk *sd;
02177 register struct sbfile *sf;
02178 { if(sd->sdfile == sf
02179 && sd->sdmem)
02180 sd->sdflags |= SD_MOD;
02181 }
02182
02183 sbx_err(val,str,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12)
02184 char *str;
02185 { int *sptr;
02186
02187 sptr = (int *) &sptr;
02188 sptr += 5;
02189 if((int)sbv_debug == 1)
02190 { abort();
02191 }
02192 if(sbv_debug)
02193 (*sbv_debug)(1,*sptr,str,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12);
02194 return(val);
02195 }