©2004 by Marc J. Rochkind. All rights reserved. Portions marked "Open Source" may be copied under license.

 

Main Page   Modules   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

c7/f3.c

Go to the documentation of this file.
00001 /*
00002     File locking (lockf)
00003     AUP2, Sec. 7.11.3
00004 
00005     Copyright 2003 by Marc J. Rochkind. All rights reserved.
00006     May be copied only for purposes and under conditions described
00007     on the Web page www.basepath.com/aup/copyright.htm.
00008 
00009     The Example Files are provided "as is," without any warranty;
00010     without even the implied warranty of merchantability or fitness
00011     for a particular purpose. The author and his publisher are not
00012     responsible for any damages, direct or incidental, resulting
00013     from the use or non-use of these Example Files.
00014 
00015     The Example Files may contain defects, and some contain deliberate
00016     coding mistakes that were included for educational reasons.
00017     You are responsible for determining if and how the Example Files
00018     are to be used.
00019 
00020 */
00021 #include "defs.h"
00022 
00023 /*[rec]*/
00024 struct rec {
00025     int r_data;
00026     off_t r_next;
00027 };
00028 /*[readrec]*/
00029 bool readrec(int dbfd, struct rec *r, off_t off)
00030 {
00031     ssize_t nread;
00032 
00033     if ((nread = pread(dbfd, r, sizeof(struct rec), off)) ==
00034       sizeof(struct rec))
00035         return true;
00036     if (nread != -1)
00037         errno = EIO;
00038     EC_FAIL
00039     return true;
00040 
00041 EC_CLEANUP_BGN
00042     return false;
00043 EC_CLEANUP_END
00044 }
00045 
00046 bool writerec(int dbfd, struct rec *r, off_t off)
00047 {
00048     ssize_t nwrote;
00049 
00050     if ((nwrote = pwrite(dbfd, r, sizeof(struct rec), off)) ==
00051       sizeof(struct rec))
00052         return true;
00053     if (nwrote != -1)
00054         errno = EIO;
00055     EC_FAIL
00056     return true;
00057 
00058 EC_CLEANUP_BGN
00059     return false;
00060 EC_CLEANUP_END
00061 }
00062 
00063 bool store(int dbfd, int data)
00064 {
00065     struct rec r, rnew;
00066     off_t end, prev;
00067 
00068     ec_neg1( end = lseek(dbfd, 0, SEEK_END) )
00069     prev = 0;
00070     ec_false( readrec(dbfd, &r, prev) )
00071     while (r.r_next != 0) {
00072         ec_false( readrec(dbfd, &r, r.r_next) )
00073         if (r.r_data > data)
00074             break;
00075         prev = r.r_next;
00076     }
00077 /*[store]*/
00078     ec_neg1( lseek(dbfd, 0, SEEK_SET) )
00079     ec_neg1( lockf(dbfd, F_LOCK, 0) )
00080     ec_false( readrec(dbfd, &r, prev) )
00081     rnew.r_next = r.r_next;
00082     r.r_next = end;
00083     ec_false( writerec(dbfd, &r, prev) )
00084     rnew.r_data = data;
00085     usleep(1); /* give up CPU */
00086     ec_false( writerec(dbfd, &rnew, end) )
00087     ec_neg1( lseek(dbfd, 0, SEEK_SET) )
00088     ec_neg1( lockf(dbfd, F_ULOCK, 0) )
00089 /*[]*/
00090     return true;
00091 
00092 EC_CLEANUP_BGN
00093     return false;
00094 EC_CLEANUP_END
00095 }
00096 /*[process1]*/
00097 #define DBNAME "termdb"
00098 
00099 static void process1(void)
00100 {
00101     int dbfd, data;
00102     struct rec r;
00103 
00104     ec_neg1( dbfd = open(DBNAME, O_CREAT | O_TRUNC | O_RDWR, PERM_FILE) )
00105     memset(&r, 0, sizeof(r));
00106     ec_false( writerec(dbfd, &r, 0) )
00107     for (data = 100; data >= 0; data--)
00108         ec_false( store(dbfd, data) )
00109     ec_neg1( close(dbfd) )
00110     exit(EXIT_SUCCESS);
00111 
00112 EC_CLEANUP_BGN
00113     exit(EXIT_FAILURE);
00114 EC_CLEANUP_END
00115 }
00116 static void process2(void)
00117 {
00118     int try, dbfd;
00119     struct rec r1, r2;
00120 
00121     for (try = 0; try < 10; try++)
00122         if ((dbfd = open(DBNAME, O_RDWR)) == -1) {
00123             if (errno == ENOENT) {
00124                 continue;
00125             }
00126             else
00127                 EC_FAIL
00128         }
00129     ec_neg1( dbfd )
00130 /*[process2]*/
00131     for (try = 0; try < 100; try++) {
00132         ec_neg1( lseek(dbfd, 0, SEEK_SET) )
00133         ec_neg1( lockf(dbfd, F_LOCK, 0) )
00134         ec_false( readrec(dbfd, &r1, 0) )
00135         while (r1.r_next != 0) {
00136             ec_false( readrec(dbfd, &r2, r1.r_next) )
00137             if (r1.r_data > r2.r_data) {
00138                 printf("Found sorting error (try %d)\n", try);
00139                 break;
00140             }
00141             r1 = r2;
00142         }
00143         ec_neg1( lseek(dbfd, 0, SEEK_SET) )
00144         ec_neg1( lockf(dbfd, F_ULOCK, 0) )
00145     }
00146 /*[]*/
00147     ec_neg1( close(dbfd) )
00148     return;
00149 
00150 EC_CLEANUP_BGN
00151     exit(EXIT_FAILURE);
00152 EC_CLEANUP_END
00153 }
00154 /*[main]*/
00155 int main(void)
00156 {
00157     pid_t pid;
00158 
00159     ec_neg1( pid = fork() )
00160     if (pid == 0)
00161         process1();
00162     else {
00163         process2();
00164         ec_neg1( waitpid(pid, NULL, 0) )
00165     }
00166     exit(EXIT_SUCCESS);
00167 
00168 EC_CLEANUP_BGN
00169     exit(EXIT_FAILURE);
00170 EC_CLEANUP_END
00171 }
00172 /*[]*/

Generated on Fri Apr 23 10:56:58 2004 for AUP2 Example Source by doxygen 1.3.1