home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / APPS / hl10osrc.lzh / Lib / vm.cc < prev   
Text File  |  1994-04-23  |  10KB  |  343 lines

  1. /* -*- Mode: C -*- */
  2. /* vm.cc - PageFile implementation (virtual memory management)
  3.  * Created by Robert Heller on Sat Dec  7 00:19:52 1991
  4.  *
  5.  * ------------------------------------------------------------------
  6.  * Home Libarian by Deepwoods Software
  7.  * Common Class library implementation code
  8.  * ------------------------------------------------------------------
  9.  * Modification History:
  10.  * ------------------------------------------------------------------
  11.  * Contents:
  12.  * ------------------------------------------------------------------
  13.  * 
  14.  * 
  15.  * Copyright (c) 1991,1992 by Robert heller (D/B/A Deepwoods Software)
  16.  *        All Rights Reserved
  17.  * 
  18.  */
  19. #include <stream.h>
  20. #include <vm.h>
  21.  
  22. // File open function.
  23. // Open or create the page file
  24. OpenStatus PageFile::open(char *filename,Direction direction,int flags,int mode,
  25.             Boolean create_if)
  26. {
  27.     OpenStatus result = failure;        // assume failure
  28.     fd = ::open(filename,flags);        // try to open the file
  29.     // failure?
  30.     if (fd < 0) {
  31.         // yes.  create a new file if posible
  32.         if (create_if && (direction == out || direction  == inout)) {
  33. #ifdef OSK
  34.             fd = create(filename,flags,mode); // OSK specific
  35. #else
  36.                fd = ::open(filename,flags|O_CREAT,mode);      // vanila UNIX
  37. #endif
  38.             // still a problem?  give up
  39.             if (fd < 0) return(failure);
  40.             // else note that it is a new file
  41.             result = opennew;
  42.         } else return(failure);
  43.     } else result = openold;            // old file open
  44.     PageFile::direction = direction;        // remember direction
  45.     numpagesincore = 0;                // empty WS
  46.     isopen = true;                    // yes, it is open
  47.     return(result);
  48. }
  49.  
  50. // close a PageFile
  51. void PageFile::close()
  52. {
  53.     // if the file is open...
  54.     if (isopen) {
  55.         for (int i = 0; i < numpagesincore; i++) {
  56.             // write out any dirty pages
  57.             if (pagetable[i].isdirty) {
  58.                 if (!PageWrite(pagetable[i])) {
  59.                     int error = errno;
  60.                     cerr << "%%% PageWrite error. Page no. = " <<
  61.                         pagetable[i].diskpage.record_address <<
  62.                         "\n";
  63.                     exit(error);
  64.                 }
  65.                 pagetable[i].isdirty = false;
  66.             }
  67.             // free up and used core memory
  68.             if (pagetable[i].corepage != 0) {
  69.                 delete pagetable[i].corepage;
  70.                 pagetable[i].corepage = 0;
  71.             }
  72.         }
  73.         // really close the file
  74.         ::close(fd);
  75.         // nope, not open anymore
  76.         isopen = false;
  77.         // no pages core resident
  78.         numpagesincore = 0;
  79.     }
  80. }
  81.  
  82. // Read in a page.  ptentry says which page.
  83. Boolean PageFile::PageRead(PTEntry& ptentry)
  84. {
  85.     //cerr << "*** PageFile::PageRead(): page's disk address is " << 
  86.     //    ptentry.diskpage.record_address << "\n";
  87.     // try to seek to page
  88.     long pos = lseek(fd,ptentry.diskpage.record_address,SEEK_SET);
  89.     // can't seek? fail
  90.     if (pos == -1L) return(false);
  91.     // do we have memory available?
  92.     if (ptentry.corepage == 0) {
  93.         ptentry.corepage = new Page;    // allocate memory if needed
  94.     }
  95.     //cerr << "*** -: page's core address is 0x" <<
  96.     //    form("%08x",ptentry.corepage) << "\n";
  97.     // read in page
  98.     if (read(fd,(char *)(ptentry.corepage),sizeof(Page)) <
  99.         sizeof(Page)) return(false);
  100.     // page is ready and clean
  101.     ptentry.isdirty = false;
  102.     return(true);
  103. }
  104.  
  105. // Write out a page
  106. Boolean PageFile::PageWrite(PTEntry& ptentry)
  107. {
  108.     //cerr << "*** PageFile::PageWrite(): page's disk address is " << 
  109.     //    ptentry.diskpage.record_address <<
  110.     //    ", and its core address is 0x" <<
  111.     //    form("%08x",ptentry.corepage) << "\n";
  112.     // seek to disk space
  113.     long pos = lseek(fd,ptentry.diskpage.record_address,SEEK_SET);
  114.     // if seek failure, return failure
  115.     if (pos == -1L) return(false);
  116.     // write the page
  117.     if (write(fd,(char *)(ptentry.corepage),sizeof(Page)) <
  118.         sizeof(Page)) return(false);
  119.     // no longer dirty...
  120.     ptentry.isdirty = false;
  121.     return(true);
  122. }
  123.  
  124. // Locate a page.  Read the page in if necessary, dumping the least recently
  125. // referenced page to make room
  126. PTEntry & PageFile::FindPage(DiskPage diskpage)
  127. {
  128.     //cerr << "*** in PageFile::FindPage - looking for page " <<
  129.     //    diskpage.record_address << "\n";
  130.     // is page already resident?
  131.     for (int i = 0; i < numpagesincore; i++) {
  132.         if (pagetable[i].diskpage == diskpage) {
  133.             // yes.  promote page to end of table, if it is not
  134.             // already there
  135.             //cerr << "*** -: Page is resident.\n";
  136.             if (i < (numpagesincore-1)) {
  137.                 temp = pagetable[i];
  138.                 for (int j = i+1; j < numpagesincore; j++) {
  139.                     pagetable[j-1] = pagetable[j];
  140.                 }
  141.                 pagetable[numpagesincore-1] = temp;
  142.             }
  143.             //cerr << "*** -: core address is 0x" <<
  144.             //    form("%08x",pagetable[numpagesincore-1].corepage) <<
  145.             //    "\n";
  146.             // return page table entry
  147.             return(pagetable[numpagesincore-1]);
  148.         }
  149.     }
  150.     //cerr << "*** -: Page is non-resident.\n";
  151.     // page not in core.  Is WS (page table) full?
  152.     if (numpagesincore < NumPTEntries) {
  153.         //cerr << "*** -: WS grown.\n";
  154.         // if not, use new entry at the end and increase WS
  155.         pagetable[numpagesincore].diskpage = diskpage;
  156.         if (!PageRead(pagetable[numpagesincore])) {
  157.             int error = errno;
  158.             cerr << "%%% PageRead error: page no. = " <<
  159.                 diskpage.record_address << "\n";
  160.             exit(error);
  161.         }
  162.         numpagesincore++;
  163.         //cerr << "*** -: core address is 0x" <<
  164.         //    form("%08x",pagetable[numpagesincore-1].corepage) <<
  165.         //    "\n";
  166.         return(pagetable[numpagesincore-1]);
  167.     } else {    // otherwise, bump a page
  168.         // if old page is dirty, write it out
  169.         if (pagetable[0].isdirty == true) {
  170.             //cerr << "*** -: Page out " <<
  171.             //    pagetable[0].diskpage.record_address <<
  172.             //    "\n";
  173.             if (!PageWrite(pagetable[0])) {
  174.                 int error = errno;
  175.                 cerr << "%%% PageWrite error: page no. = " <<
  176.                     pagetable[0].diskpage.record_address <<
  177.                     "\n";
  178.                 exit(error);
  179.             }
  180.         }
  181.         // shift pages down
  182.         temp = pagetable[0];
  183.         for (int j = 1; j < numpagesincore; j++) {
  184.             pagetable[j-1] = pagetable[j];
  185.         }
  186.         pagetable[numpagesincore-1] = temp;
  187.         // setup page
  188.         pagetable[numpagesincore-1].diskpage = diskpage;
  189.         if(!PageRead(pagetable[numpagesincore-1])) {
  190.             int error = errno;
  191.             cerr << "%%% PageRead error: page no. = " <<
  192.                 diskpage.record_address << "\n";
  193.             exit(error);
  194.         }
  195.         //cerr << "*** -: core address is 0x" <<
  196.         //    form("%08x",pagetable[numpagesincore-1].corepage) <<
  197.         //    "\n";
  198.         return(pagetable[numpagesincore-1]);
  199.     }
  200. }
  201.  
  202. // allocate a new, fresh page
  203. DiskPage PageFile::NewPage()
  204. {
  205.     DiskPage temppage;        // new page
  206.     long int fill;            // filler to make page address fall
  207.                     // on a sector boundry
  208.     static char buffer[SectorSize];    // filler
  209.     static Boolean init = false;    // init flag
  210.     if (init == false) {        // filler initialization
  211.         memset(buffer,'\0',SectorSize);
  212.         init = true;
  213.     }
  214.     //cerr << "*** in PageFile::NewPage()\n";
  215.     // find eof
  216.     temppage = lseek(fd,0,SEEK_END);
  217.     if (temppage == -1L) return temppage;    // failure??
  218.     // compute filler size
  219.     fill = SectorSize - (temppage.record_address & (SectorSize-1));
  220.     // is filler even needed?
  221.     if (fill == SectorSize) fill = 0;
  222.     if (fill != 0) {
  223.         // yep.  write filler and re-compute page address.
  224.         write(fd,buffer,fill);
  225.         temppage = lseek(fd,0,SEEK_END);
  226.     }
  227.     //cerr << "*** -: new page at " << temppage.record_address << "\n";
  228.     // find a home for this page (code copied from FindPage, with
  229.     // minor mode)
  230.     if (numpagesincore < NumPTEntries) {
  231.         //cerr << "*** -: WS grown.\n";
  232.         pagetable[numpagesincore].diskpage = temppage;
  233.         if (pagetable[numpagesincore].corepage == 0) {
  234.             pagetable[numpagesincore].corepage = new Page;
  235.         }
  236.         //cerr << "*** -: core address is 0x" <<
  237.         //    form("%08x",pagetable[numpagesincore].corepage) <<
  238.         //    "\n";
  239.         memset((char *) pagetable[numpagesincore].corepage,
  240.             '\0',SectorSize);
  241.         if (!PageWrite(pagetable[numpagesincore])) {
  242.             int error = errno;
  243.             cerr << "%%% PageWrite error: page no. = " <<
  244.                 pagetable[numpagesincore].diskpage.record_address <<
  245.                 "\n";
  246.             exit(error);
  247.         }
  248.         pagetable[numpagesincore].isdirty = false;
  249.         numpagesincore++;
  250.         return(pagetable[numpagesincore-1].diskpage);
  251.     } else {
  252.         if (pagetable[0].isdirty == true) {
  253.             //cerr << "*** -: Page out " <<
  254.             //    pagetable[0].diskpage.record_address <<
  255.             //    "\n";
  256.             if (!PageWrite(pagetable[0])) {
  257.                 int error = errno;
  258.                 cerr << "%%% PageWrite error: page no. = " <<
  259.                     pagetable[0].diskpage.record_address <<
  260.                     "\n";
  261.                 exit(error);
  262.             }
  263.         }
  264.         temp = pagetable[0];
  265.         for (int j = 1; j < numpagesincore; j++) {
  266.             pagetable[j-1] = pagetable[j];
  267.         }
  268.         pagetable[numpagesincore-1] = temp;
  269.         pagetable[numpagesincore-1].diskpage = temppage;
  270.         memset((char *) pagetable[numpagesincore-1].corepage,
  271.             '\0',SectorSize);
  272.         //cerr << "*** -: core address is 0x" <<
  273.         //    form("%08x",pagetable[numpagesincore-1].corepage) <<
  274.         //    "\n";
  275.         if (!PageWrite(pagetable[numpagesincore-1])) {
  276.             int error = errno;
  277.             cerr << "%%% PageWrite error: page no. = " <<
  278.                 pagetable[numpagesincore-1].diskpage.record_address <<
  279.                 "\n";
  280.             exit(error);
  281.         }
  282.         pagetable[numpagesincore-1].isdirty = false;
  283.         return(pagetable[numpagesincore-1].diskpage);
  284.     }
  285. }
  286.  
  287. // Read in a data record
  288. int PageFile::ReadRecord(DiskRecord& record, char *buffer, int buffsize)
  289. {
  290.     // seek to data offset
  291.     long pos = lseek(fd,record.record_address,SEEK_SET);
  292.     // seek failure?
  293.     if (pos == -1) return(-1);
  294.     // read in data (or at as much as will fit in record
  295.     if (buffsize >= record.record_size) {
  296.         return(read(fd,buffer,record.record_size));
  297.     } else {
  298.         return(read(fd,buffer,buffsize));
  299.     }
  300. }
  301.  
  302. // Write a redord out
  303. DiskRecord PageFile::WriteRecord(char *buffer, int buffsize)
  304. {
  305.     DiskRecord newrec;    // new disk record
  306.     // seek to EOF
  307.     newrec.record_address = lseek(fd,0,SEEK_END);
  308.     // seek failure??
  309.     if (newrec.record_address == -1L) {
  310.         return 0;
  311.     }
  312.     //cerr.form("*** in WriteRecord(): newrec.record_address = 0x%08x\n",
  313.     //     newrec.record_address);
  314.     // write out record
  315.     newrec.record_size = write(fd,buffer,buffsize);
  316.     //cerr.form("*** in WriteRecord(): buffsize = %d, newrec.record_size = %d\n",
  317.     //    buffsize,newrec.record_size);
  318.     return(newrec);
  319. }
  320.  
  321. // update old record or write new one
  322. DiskRecord PageFile::ReWriteRecord(DiskRecord& record, char *buffer, int buffsize)
  323. {
  324.     long pos;
  325.  
  326.     //cerr << "*** PageFile::ReWriteRecord(): record = (:SIZE " << 
  327.     //    record.record_size << " :ADDR " << record.record_address << 
  328.     //    "), buffsize = " << buffsize << "\n";
  329.     // will new record fill in old place?
  330.     if (buffsize > record.record_size) {
  331.         // no, create new record
  332.         return(PageFile::WriteRecord(buffer,buffsize));
  333.     } else {
  334.         // yes, rewrite old record
  335.         pos = lseek(fd,record.record_address,SEEK_SET);
  336.         if (pos == -1) return(0);
  337.         record.record_size = write(fd,buffer,buffsize);    
  338.         return(record);
  339.     }
  340.     
  341. }
  342.  
  343.