813 lines
52 KiB
HTML
813 lines
52 KiB
HTML
|
|
||
|
<!DOCTYPE html>
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
<html lang="en">
|
||
|
<head>
|
||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||
|
|
||
|
<title>7.8. Extended Example: Event Log File — Computer Systems Fundamentals</title>
|
||
|
|
||
|
<link rel="stylesheet" href="_static/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous" />
|
||
|
<link rel="stylesheet" href="_static/css/pygments.css" type="text/css" />
|
||
|
<link rel="stylesheet" href="_static/css/normalize.css" type="text/css" />
|
||
|
<link rel="stylesheet" href="../../../JSAV/css/JSAV.css" type="text/css" />
|
||
|
<link rel="stylesheet" href="../../../lib/odsaMOD-min.css" type="text/css" />
|
||
|
<link rel="stylesheet" href="_static/css/jquery-1.11.4-smoothness-ui.css" type="text/css" />
|
||
|
<link rel="stylesheet" href="../../../lib/odsaStyle-min.css" type="text/css" />
|
||
|
<link rel="stylesheet" href="_static/css/csf.css" type="text/css" />
|
||
|
|
||
|
<style>
|
||
|
.underline { text-decoration: underline; }
|
||
|
</style>
|
||
|
|
||
|
<script type="text/javascript">
|
||
|
var DOCUMENTATION_OPTIONS = {
|
||
|
URL_ROOT: './',
|
||
|
VERSION: '0.4.1',
|
||
|
COLLAPSE_INDEX: false,
|
||
|
FILE_SUFFIX: '.html',
|
||
|
HAS_SOURCE: true
|
||
|
};
|
||
|
</script>
|
||
|
|
||
|
<script type="text/x-mathjax-config">
|
||
|
MathJax.Hub.Config({
|
||
|
tex2jax: {
|
||
|
inlineMath: [['$','$'], ['\\(','\\)']],
|
||
|
displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
|
||
|
processEscapes: true
|
||
|
},
|
||
|
"HTML-CSS": {
|
||
|
scale: "80"
|
||
|
}
|
||
|
});
|
||
|
</script>
|
||
|
<link rel="shortcut icon" href="_static/favicon.ico"/>
|
||
|
<link rel="index" title="Index" href="genindex.html" />
|
||
|
<link rel="search" title="Search" href="search.html" />
|
||
|
<link rel="index" title="Computer Systems Fundamentals" href="index.html" />
|
||
|
<link rel="next" title="1. Synchronization Patterns and Problems" href="SynchProblemsOverview.html" />
|
||
|
<link rel="prev" title="7. Deadlock" href="Deadlock.html" />
|
||
|
|
||
|
</head><body>
|
||
|
|
||
|
<nav class="navbar navbar-expand-md navbar-dark navbar-custom fixed-top">
|
||
|
|
||
|
<a class="navbar-brand py-0" href="index.html"><img src="_static/CSF-Logo-Square-Text.png" alt="OpenCSF Logo" height="40em" class="py-1 px-2 mb-0 align-center rounded-lg bg-white" /></a>
|
||
|
<!-- Show a navbar toggler on mobile -->
|
||
|
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#defaultNavbars" aria-controls="defaultNavbars" aria-expanded="false" aria-label="Toggle navigation">
|
||
|
<span class="navbar-toggler-icon"></span>
|
||
|
</button>
|
||
|
<div class="collapse navbar-collapse" id="defaultNavbars">
|
||
|
<ul class="navbar-nav mr-auto">
|
||
|
<li class="nav-item dropdown">
|
||
|
<a class="nav-link dropdown-toggle jmu-gold rounded" href="Extended7Events.html#" id="navbarDropdownChapters" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Contents</a>
|
||
|
<div class="dropdown-menu scrollable-menu" role="menu" aria-labelledby="navbarDropdownChapters">
|
||
|
<a class="dropdown-item" tabindex="-1" href="Extended7Events.html#"><b>Chapter 1</b></a>
|
||
|
<a class="dropdown-item" href="IntroConcSysOverview.html"> 1.1. Introduction to Concurrent Systems</a>
|
||
|
<a class="dropdown-item" href="SysAndModels.html"> 1.2. Systems and Models</a>
|
||
|
<a class="dropdown-item" href="Themes.html"> 1.3. Themes and Guiding Principles</a>
|
||
|
<a class="dropdown-item" href="Architectures.html"> 1.4. System Architectures</a>
|
||
|
<a class="dropdown-item" href="StateModels.html"> 1.5. State Models in UML</a>
|
||
|
<a class="dropdown-item" href="SequenceModels.html"> 1.6. Sequence Models in UML</a>
|
||
|
<a class="dropdown-item" href="StateModelImplementation.html"> 1.7. Extended Example: State Model Implementation</a>
|
||
|
<div class="dropdown-divider"></div>
|
||
|
<a class="dropdown-item disabled"><b>Chapter 2</b></a>
|
||
|
<a class="dropdown-item" href="ProcessesOverview.html"> 2.1. Processes and OS Basics</a>
|
||
|
<a class="dropdown-item" href="Multiprogramming.html"> 2.2. Processes and Multiprogramming</a>
|
||
|
<a class="dropdown-item" href="KernelMechanics.html"> 2.3. Kernel Mechanics</a>
|
||
|
<a class="dropdown-item" href="Syscall.html"> 2.4. System Call Interface</a>
|
||
|
<a class="dropdown-item" href="ProcessCycle.html"> 2.5. Process Life Cycle</a>
|
||
|
<a class="dropdown-item" href="UnixFile.html"> 2.6. The UNIX File Abstraction</a>
|
||
|
<a class="dropdown-item" href="EventsSignals.html"> 2.7. Events and Signals</a>
|
||
|
<a class="dropdown-item" href="Extended2Processes.html"> 2.8. Extended Example: Listing Files with Processes</a>
|
||
|
<div class="dropdown-divider"></div>
|
||
|
<a class="dropdown-item disabled"><b>Chapter 3</b></a>
|
||
|
<a class="dropdown-item" href="IPCOverview.html"> 3.1. Concurrency with IPC</a>
|
||
|
<a class="dropdown-item" href="IPCModels.html"> 3.2. IPC Models</a>
|
||
|
<a class="dropdown-item" href="Pipes.html"> 3.3. Pipes and FIFOs</a>
|
||
|
<a class="dropdown-item" href="MMap.html"> 3.4. Shared Memory With Memory-mapped Files</a>
|
||
|
<a class="dropdown-item" href="POSIXvSysV.html"> 3.5. POSIX vs. System V IPC</a>
|
||
|
<a class="dropdown-item" href="MQueues.html"> 3.6. Message Passing With Message Queues</a>
|
||
|
<a class="dropdown-item" href="ShMem.html"> 3.7. Shared Memory</a>
|
||
|
<a class="dropdown-item" href="IPCSems.html"> 3.8. Semaphores</a>
|
||
|
<a class="dropdown-item" href="Extended3Bash.html"> 3.9. Extended Example: Bash-lite: A Simple Command-line Shell</a>
|
||
|
<div class="dropdown-divider"></div>
|
||
|
<a class="dropdown-item disabled"><b>Chapter 4</b></a>
|
||
|
<a class="dropdown-item" href="SocketsOverview.html"> 4.1. Networked Concurrency</a>
|
||
|
<a class="dropdown-item" href="FiveLayer.html"> 4.2. The TCP/IP Internet Model</a>
|
||
|
<a class="dropdown-item" href="NetApps.html"> 4.3. Network Applications and Protocols</a>
|
||
|
<a class="dropdown-item" href="Sockets.html"> 4.4. The Socket Interface</a>
|
||
|
<a class="dropdown-item" href="TCPSockets.html"> 4.5. TCP Socket Programming: HTTP</a>
|
||
|
<a class="dropdown-item" href="UDPSockets.html"> 4.6. UDP Socket Programming: DNS</a>
|
||
|
<a class="dropdown-item" href="AppBroadcast.html"> 4.7. Application-Layer Broadcasting: DHCP</a>
|
||
|
<a class="dropdown-item" href="Extended4CGI.html"> 4.8. Extended Example: CGI Web Server</a>
|
||
|
<div class="dropdown-divider"></div>
|
||
|
<a class="dropdown-item disabled"><b>Chapter 5</b></a>
|
||
|
<a class="dropdown-item" href="InternetOverview.html"> 5.1. The Internet and Connectivity</a>
|
||
|
<a class="dropdown-item" href="AppLayer.html"> 5.2. Application Layer: Overlay Networks</a>
|
||
|
<a class="dropdown-item" href="TransLayer.html"> 5.3. Transport Layer</a>
|
||
|
<a class="dropdown-item" href="NetSec.html"> 5.4. Network Security Fundamentals</a>
|
||
|
<a class="dropdown-item" href="NetLayer.html"> 5.5. Network Layer: IP</a>
|
||
|
<a class="dropdown-item" href="LinkLayer.html"> 5.6. Link Layer</a>
|
||
|
<a class="dropdown-item" href="Wireless.html"> 5.7. Wireless Connectivity: Wi-Fi, Bluetooth, and Zigbee</a>
|
||
|
<a class="dropdown-item" href="Extended5DNS.html"> 5.8. Extended Example: DNS client</a>
|
||
|
<div class="dropdown-divider"></div>
|
||
|
<a class="dropdown-item disabled"><b>Chapter 6</b></a>
|
||
|
<a class="dropdown-item" href="ThreadsOverview.html"> 6.1. Concurrency with Multithreading</a>
|
||
|
<a class="dropdown-item" href="ProcVThreads.html"> 6.2. Processes vs. Threads</a>
|
||
|
<a class="dropdown-item" href="RaceConditions.html"> 6.3. Race Conditions and Critical Sections</a>
|
||
|
<a class="dropdown-item" href="POSIXThreads.html"> 6.4. POSIX Thread Library</a>
|
||
|
<a class="dropdown-item" href="ThreadArgs.html"> 6.5. Thread Arguments and Return Values</a>
|
||
|
<a class="dropdown-item" href="ImplicitThreads.html"> 6.6. Implicit Threading and Language-based Threads</a>
|
||
|
<a class="dropdown-item" href="Extended6Input.html"> 6.7. Extended Example: Keyboard Input Listener</a>
|
||
|
<a class="dropdown-item" href="Extended6Primes.html"> 6.8. Extended Example: Concurrent Prime Number Search</a>
|
||
|
<div class="dropdown-divider"></div>
|
||
|
<a class="dropdown-item disabled"><b>Chapter 7</b></a>
|
||
|
<a class="dropdown-item" href="SynchOverview.html"> 7.1. Synchronization Primitives</a>
|
||
|
<a class="dropdown-item" href="CritSect.html"> 7.2. Critical Sections and Peterson's Solution</a>
|
||
|
<a class="dropdown-item" href="Locks.html"> 7.3. Locks</a>
|
||
|
<a class="dropdown-item" href="Semaphores.html"> 7.4. Semaphores</a>
|
||
|
<a class="dropdown-item" href="Barriers.html"> 7.5. Barriers</a>
|
||
|
<a class="dropdown-item" href="Condvars.html"> 7.6. Condition Variables</a>
|
||
|
<a class="dropdown-item" href="Deadlock.html"> 7.7. Deadlock</a>
|
||
|
<a class="dropdown-item" href="Extended7Events.html"> 7.8. Extended Example: Event Log File</a>
|
||
|
<div class="dropdown-divider"></div>
|
||
|
<a class="dropdown-item disabled"><b>Chapter 8</b></a>
|
||
|
<a class="dropdown-item" href="SynchProblemsOverview.html"> 8.1. Synchronization Patterns and Problems</a>
|
||
|
<a class="dropdown-item" href="SynchDesign.html"> 8.2. Basic Synchronization Design Patterns</a>
|
||
|
<a class="dropdown-item" href="ProdCons.html"> 8.3. Producer-Consumer Problem</a>
|
||
|
<a class="dropdown-item" href="ReadWrite.html"> 8.4. Readers-Writers Problem</a>
|
||
|
<a class="dropdown-item" href="DiningPhil.html"> 8.5. Dining Philosophers Problem and Deadlock</a>
|
||
|
<a class="dropdown-item" href="CigSmokers.html"> 8.6. Cigarette Smokers Problem and the Limits of Semaphores and Locks</a>
|
||
|
<a class="dropdown-item" href="Extended8ModExp.html"> 8.7. Extended Example: Parallel Modular Exponentiation</a>
|
||
|
<div class="dropdown-divider"></div>
|
||
|
<a class="dropdown-item disabled"><b>Chapter 9</b></a>
|
||
|
<a class="dropdown-item" href="ParallelDistributedOverview.html"> 9.1. Parallel and Distributed Systems</a>
|
||
|
<a class="dropdown-item" href="ParVConc.html"> 9.2. Parallelism vs. Concurrency</a>
|
||
|
<a class="dropdown-item" href="ParallelDesign.html"> 9.3. Parallel Design Patterns</a>
|
||
|
<a class="dropdown-item" href="Scaling.html"> 9.4. Limits of Parallelism and Scaling</a>
|
||
|
<a class="dropdown-item" href="DistTiming.html"> 9.5. Timing in Distributed Environments</a>
|
||
|
<a class="dropdown-item" href="DistDataStorage.html"> 9.6. Reliable Data Storage and Location</a>
|
||
|
<a class="dropdown-item" href="DistConsensus.html"> 9.7. Consensus in Distributed Systems</a>
|
||
|
<a class="dropdown-item" href="Extended9Blockchain.html"> 9.8. Extended Example: Blockchain Proof-of-Work</a>
|
||
|
<div class="dropdown-divider"></div>
|
||
|
<a class="dropdown-item disabled"><b>Appendix A</b></a>
|
||
|
<a class="dropdown-item" href="CLangOverview.html"> A.1. C Language Reintroduction</a>
|
||
|
<a class="dropdown-item" href="Debugging.html"> A.2. Documentation and Debugging</a>
|
||
|
<a class="dropdown-item" href="BasicTypes.html"> A.3. Basic Types and Pointers</a>
|
||
|
<a class="dropdown-item" href="Arrays.html"> A.4. Arrays, Structs, Enums, and Type Definitions</a>
|
||
|
<a class="dropdown-item" href="Functions.html"> A.5. Functions and Scope</a>
|
||
|
<a class="dropdown-item" href="Pointers.html"> A.6. Pointers and Dynamic Allocation</a>
|
||
|
<a class="dropdown-item" href="Strings.html"> A.7. Strings</a>
|
||
|
<a class="dropdown-item" href="FunctionPointers.html"> A.8. Function Pointers</a>
|
||
|
<a class="dropdown-item" href="Files.html"> A.9. Files</a>
|
||
|
</div>
|
||
|
</li>
|
||
|
|
||
|
|
||
|
|
||
|
</ul>
|
||
|
</div>
|
||
|
|
||
|
<ul class="navbar-nav flex-row ml-md-auto d-none d-md-flex">
|
||
|
<li class="nav-item"><a class="nav-link jmu-gold" href="https://w3.cs.jmu.edu/kirkpams/OpenCSF/Books/csf/source/Extended7Events.rst"
|
||
|
target="_blank" rel="nofollow">Show Source</a></li>
|
||
|
|
||
|
</ul>
|
||
|
</nav>
|
||
|
|
||
|
|
||
|
<div class="container center">
|
||
|
«  <a id="prevmod" href="Deadlock.html">7.7. Deadlock</a>
|
||
|
  ::  
|
||
|
<a class="uplink" href="index.html">Contents</a>
|
||
|
  ::  
|
||
|
<a id="nextmod" href="SynchProblemsOverview.html">8.1. Synchronization Patterns and Problems</a>  »
|
||
|
|
||
|
</div>
|
||
|
<br />
|
||
|
|
||
|
|
||
|
|
||
|
<script type="text/javascript" src="_static/js/jquery-2.1.4.min.js"></script>
|
||
|
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
||
|
<script type="text/javascript" src="_static/js/jquery-1.11.4-ui.min.js"></script>
|
||
|
<script type="text/javascript" src="_static/js/forge-0.7.0.min.js"></script>
|
||
|
<script type="text/javascript" src="../../../JSAV/lib/jquery.transit.js"></script>
|
||
|
<script type="text/javascript" src="../../../JSAV/lib/raphael.js"></script>
|
||
|
<script type="text/javascript" src="../../../JSAV/build/JSAV-min.js"></script>
|
||
|
<script type="text/javascript" src="_static/js/config.js"></script>
|
||
|
<script type="text/javascript" src="../../../lib/odsaUtils-min.js"></script>
|
||
|
<script type="text/javascript" src="../../../lib/odsaMOD-min.js"></script>
|
||
|
<script type="text/javascript" src="_static/js/d3-4.13.0.min.js"></script>
|
||
|
<script type="text/javascript" src="_static/js/d3-selection-multi.v1.min.js"></script>
|
||
|
<script type="text/javascript" src="../../../lib/dataStructures.js"></script>
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
<div class="container">
|
||
|
|
||
|
<script>ODSA.SETTINGS.DISP_MOD_COMP = true;ODSA.SETTINGS.MODULE_NAME = "Extended7Events";ODSA.SETTINGS.MODULE_LONG_NAME = "Extended Example: Event Log File";ODSA.SETTINGS.MODULE_CHAPTER = "Synchronization Primitives"; ODSA.SETTINGS.BUILD_DATE = "2021-06-01 15:31:50"; ODSA.SETTINGS.BUILD_CMAP = false;JSAV_OPTIONS['lang']='en';JSAV_EXERCISE_OPTIONS['code']='java';</script><div class="section" id="extended-example-event-log-file">
|
||
|
<h1>7.8. Extended Example: Event Log File<a class="headerlink" href="Extended7Events.html#extended-example-event-log-file" title="Permalink to this headline">¶</a></h1>
|
||
|
<p>Many concurrent systems use a common log file to store records of key events.
|
||
|
For instance, journaling file systems use a log to keep track of changes that
|
||
|
can be validated in case of a system crash. This Extended Example uses multiple
|
||
|
threads that create random fake events that then get written to the common log
|
||
|
file. Access to the log file is synchronized to ensure that the writes do not
|
||
|
interfere with each other.</p>
|
||
|
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
|
||
|
2
|
||
|
3
|
||
|
4
|
||
|
5
|
||
|
6
|
||
|
7
|
||
|
8
|
||
|
9
|
||
|
10
|
||
|
11
|
||
|
12
|
||
|
13
|
||
|
14
|
||
|
15
|
||
|
16
|
||
|
17
|
||
|
18
|
||
|
19
|
||
|
20
|
||
|
21
|
||
|
22
|
||
|
23
|
||
|
24
|
||
|
25
|
||
|
26
|
||
|
27
|
||
|
28
|
||
|
29
|
||
|
30
|
||
|
31
|
||
|
32
|
||
|
33
|
||
|
34
|
||
|
35
|
||
|
36
|
||
|
37
|
||
|
38
|
||
|
39
|
||
|
40
|
||
|
41
|
||
|
42
|
||
|
43
|
||
|
44
|
||
|
45
|
||
|
46
|
||
|
47
|
||
|
48
|
||
|
49
|
||
|
50
|
||
|
51
|
||
|
52
|
||
|
53
|
||
|
54
|
||
|
55
|
||
|
56
|
||
|
57
|
||
|
58
|
||
|
59
|
||
|
60
|
||
|
61
|
||
|
62
|
||
|
63
|
||
|
64
|
||
|
65
|
||
|
66
|
||
|
67
|
||
|
68
|
||
|
69
|
||
|
70
|
||
|
71
|
||
|
72
|
||
|
73
|
||
|
74
|
||
|
75
|
||
|
76
|
||
|
77
|
||
|
78
|
||
|
79
|
||
|
80
|
||
|
81
|
||
|
82
|
||
|
83
|
||
|
84
|
||
|
85
|
||
|
86
|
||
|
87
|
||
|
88
|
||
|
89
|
||
|
90
|
||
|
91
|
||
|
92
|
||
|
93
|
||
|
94
|
||
|
95
|
||
|
96
|
||
|
97
|
||
|
98
|
||
|
99
|
||
|
100
|
||
|
101
|
||
|
102
|
||
|
103
|
||
|
104
|
||
|
105
|
||
|
106
|
||
|
107
|
||
|
108
|
||
|
109
|
||
|
110
|
||
|
111
|
||
|
112
|
||
|
113
|
||
|
114
|
||
|
115
|
||
|
116
|
||
|
117
|
||
|
118
|
||
|
119
|
||
|
120
|
||
|
121
|
||
|
122
|
||
|
123
|
||
|
124
|
||
|
125
|
||
|
126
|
||
|
127
|
||
|
128
|
||
|
129
|
||
|
130
|
||
|
131
|
||
|
132
|
||
|
133
|
||
|
134
|
||
|
135
|
||
|
136
|
||
|
137
|
||
|
138
|
||
|
139
|
||
|
140
|
||
|
141
|
||
|
142
|
||
|
143
|
||
|
144
|
||
|
145
|
||
|
146
|
||
|
147
|
||
|
148
|
||
|
149
|
||
|
150
|
||
|
151
|
||
|
152
|
||
|
153
|
||
|
154
|
||
|
155
|
||
|
156
|
||
|
157
|
||
|
158
|
||
|
159
|
||
|
160
|
||
|
161
|
||
|
162
|
||
|
163
|
||
|
164
|
||
|
165
|
||
|
166
|
||
|
167
|
||
|
168
|
||
|
169
|
||
|
170
|
||
|
171
|
||
|
172
|
||
|
173
|
||
|
174
|
||
|
175
|
||
|
176
|
||
|
177
|
||
|
178
|
||
|
179
|
||
|
180
|
||
|
181
|
||
|
182
|
||
|
183
|
||
|
184
|
||
|
185
|
||
|
186
|
||
|
187
|
||
|
188
|
||
|
189
|
||
|
190
|
||
|
191
|
||
|
192
|
||
|
193
|
||
|
194
|
||
|
195
|
||
|
196
|
||
|
197
|
||
|
198
|
||
|
199
|
||
|
200
|
||
|
201
|
||
|
202
|
||
|
203
|
||
|
204
|
||
|
205
|
||
|
206
|
||
|
207
|
||
|
208
|
||
|
209
|
||
|
210
|
||
|
211
|
||
|
212
|
||
|
213
|
||
|
214
|
||
|
215
|
||
|
216
|
||
|
217
|
||
|
218
|
||
|
219
|
||
|
220
|
||
|
221
|
||
|
222
|
||
|
223
|
||
|
224
|
||
|
225
|
||
|
226
|
||
|
227
|
||
|
228
|
||
|
229
|
||
|
230
|
||
|
231
|
||
|
232
|
||
|
233
|
||
|
234
|
||
|
235
|
||
|
236
|
||
|
237
|
||
|
238
|
||
|
239
|
||
|
240
|
||
|
241
|
||
|
242
|
||
|
243
|
||
|
244
|
||
|
245
|
||
|
246
|
||
|
247
|
||
|
248
|
||
|
249
|
||
|
250
|
||
|
251
|
||
|
252
|
||
|
253
|
||
|
254
|
||
|
255
|
||
|
256
|
||
|
257
|
||
|
258
|
||
|
259
|
||
|
260
|
||
|
261
|
||
|
262
|
||
|
263
|
||
|
264
|
||
|
265
|
||
|
266
|
||
|
267
|
||
|
268
|
||
|
269
|
||
|
270
|
||
|
271
|
||
|
272
|
||
|
273
|
||
|
274</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cp">#include</span> <span class="cpf"><assert.h></span><span class="cp"></span>
|
||
|
<span class="cp">#include</span> <span class="cpf"><fcntl.h></span><span class="cp"></span>
|
||
|
<span class="cp">#include</span> <span class="cpf"><pthread.h></span><span class="cp"></span>
|
||
|
<span class="cp">#include</span> <span class="cpf"><stdbool.h></span><span class="cp"></span>
|
||
|
<span class="cp">#include</span> <span class="cpf"><stdio.h></span><span class="cp"></span>
|
||
|
<span class="cp">#include</span> <span class="cpf"><stdlib.h></span><span class="cp"></span>
|
||
|
<span class="cp">#include</span> <span class="cpf"><string.h></span><span class="cp"></span>
|
||
|
<span class="cp">#include</span> <span class="cpf"><sys/stat.h></span><span class="cp"></span>
|
||
|
<span class="cp">#include</span> <span class="cpf"><time.h></span><span class="cp"></span>
|
||
|
<span class="cp">#include</span> <span class="cpf"><unistd.h></span><span class="cp"></span>
|
||
|
|
||
|
<span class="cp">#define SHALENGTH 64</span>
|
||
|
<span class="cp">#define LOGFILE "var.log"</span>
|
||
|
|
||
|
<span class="cm">/* Change these to increase the number of threads and events */</span>
|
||
|
<span class="cp">#define NUM_THREADS 5</span>
|
||
|
<span class="cp">#define NUM_ITERATIONS 10</span>
|
||
|
|
||
|
<span class="kt">void</span> <span class="nf">append_log_message</span> <span class="p">(</span><span class="kt">FILE</span> <span class="o">*</span><span class="p">,</span> <span class="kt">size_t</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="p">);</span>
|
||
|
<span class="kt">char</span> <span class="o">*</span> <span class="nf">compute_log_hash</span> <span class="p">(</span><span class="kt">FILE</span> <span class="o">*</span><span class="p">,</span> <span class="kt">size_t</span><span class="p">);</span>
|
||
|
<span class="kt">void</span> <span class="nf">create_initial_log</span> <span class="p">(</span><span class="kt">void</span><span class="p">);</span>
|
||
|
<span class="kt">char</span> <span class="o">*</span> <span class="nf">generate_random_log</span> <span class="p">(</span><span class="kt">int</span><span class="p">);</span>
|
||
|
<span class="kt">bool</span> <span class="nf">verify_log</span> <span class="p">(</span><span class="kt">FILE</span> <span class="o">*</span><span class="p">);</span>
|
||
|
|
||
|
<span class="cm">/* Thread parameter struct */</span>
|
||
|
<span class="k">struct</span> <span class="n">log_params</span> <span class="p">{</span>
|
||
|
<span class="kt">int</span> <span class="n">tid</span><span class="p">;</span> <span class="cm">/* thread ID */</span>
|
||
|
<span class="n">pthread_mutex_t</span> <span class="o">*</span><span class="n">mutex</span><span class="p">;</span> <span class="cm">/* shared mutex */</span>
|
||
|
<span class="kt">size_t</span> <span class="o">*</span><span class="n">log_index</span><span class="p">;</span> <span class="cm">/* shared log index */</span>
|
||
|
<span class="kt">size_t</span> <span class="n">iterations</span><span class="p">;</span> <span class="cm">/* number of events */</span>
|
||
|
<span class="p">};</span>
|
||
|
|
||
|
<span class="cm">/* Event-generating thread. Each copy of this thread will</span>
|
||
|
<span class="cm"> sleep for a random amount of time, then wake up to generate</span>
|
||
|
<span class="cm"> an event. When that happens, the thread acquires the lock</span>
|
||
|
<span class="cm"> for the log file, verifies that the log is still valid,</span>
|
||
|
<span class="cm"> appends a new log message, and closes the file. After a</span>
|
||
|
<span class="cm"> certain number of iterations has occurred, the thread exits */</span>
|
||
|
<span class="kt">void</span> <span class="o">*</span>
|
||
|
<span class="nf">event_thread</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span> <span class="n">_params</span><span class="p">)</span>
|
||
|
<span class="p">{</span>
|
||
|
<span class="k">struct</span> <span class="n">log_params</span> <span class="o">*</span><span class="n">params</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">log_params</span> <span class="o">*</span><span class="p">)</span> <span class="n">_params</span><span class="p">;</span>
|
||
|
<span class="kt">unsigned</span> <span class="n">seed</span> <span class="o">=</span> <span class="p">(</span><span class="kt">unsigned</span><span class="p">)</span> <span class="n">params</span><span class="o">-></span><span class="n">tid</span><span class="p">;</span>
|
||
|
<span class="kt">size_t</span> <span class="n">i</span><span class="p">;</span>
|
||
|
<span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">params</span><span class="o">-></span><span class="n">iterations</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
|
||
|
<span class="p">{</span>
|
||
|
<span class="n">usleep</span> <span class="p">((</span><span class="n">rand_r</span> <span class="p">(</span><span class="o">&</span><span class="n">seed</span><span class="p">)</span> <span class="o">%</span> <span class="mi">500000</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
|
||
|
<span class="n">pthread_mutex_lock</span> <span class="p">(</span><span class="n">params</span><span class="o">-></span><span class="n">mutex</span><span class="p">);</span>
|
||
|
|
||
|
<span class="cm">/* Here begins the critical section */</span>
|
||
|
<span class="kt">FILE</span> <span class="o">*</span><span class="n">fp</span> <span class="o">=</span> <span class="n">fopen</span> <span class="p">(</span><span class="n">LOGFILE</span><span class="p">,</span> <span class="s">"a+"</span><span class="p">);</span>
|
||
|
<span class="k">if</span> <span class="p">(</span><span class="n">fp</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span>
|
||
|
<span class="p">{</span>
|
||
|
<span class="n">pthread_mutex_unlock</span> <span class="p">(</span><span class="n">params</span><span class="o">-></span><span class="n">mutex</span><span class="p">);</span>
|
||
|
<span class="n">pthread_exit</span> <span class="p">(</span><span class="nb">NULL</span><span class="p">);</span>
|
||
|
<span class="p">}</span>
|
||
|
|
||
|
<span class="k">if</span> <span class="p">(</span><span class="o">!</span> <span class="n">verify_log</span> <span class="p">(</span><span class="n">fp</span><span class="p">))</span>
|
||
|
<span class="p">{</span>
|
||
|
<span class="n">perror</span> <span class="p">(</span><span class="s">"Failed to validate log file"</span><span class="p">);</span>
|
||
|
<span class="n">fclose</span> <span class="p">(</span><span class="n">fp</span><span class="p">);</span>
|
||
|
<span class="n">pthread_mutex_unlock</span> <span class="p">(</span><span class="n">params</span><span class="o">-></span><span class="n">mutex</span><span class="p">);</span>
|
||
|
<span class="n">pthread_exit</span> <span class="p">(</span><span class="nb">NULL</span><span class="p">);</span>
|
||
|
<span class="p">}</span>
|
||
|
|
||
|
<span class="cm">/* All previous log messages have hashed correctly. Append</span>
|
||
|
<span class="cm"> a new message, which includes an updated hash value. */</span>
|
||
|
<span class="kt">char</span> <span class="o">*</span><span class="n">log_message</span> <span class="o">=</span> <span class="n">generate_random_log</span> <span class="p">(</span><span class="n">params</span><span class="o">-></span><span class="n">tid</span><span class="p">);</span>
|
||
|
<span class="n">append_log_message</span> <span class="p">(</span><span class="n">fp</span><span class="p">,</span> <span class="o">*</span><span class="n">params</span><span class="o">-></span><span class="n">log_index</span><span class="p">,</span> <span class="n">log_message</span><span class="p">);</span>
|
||
|
<span class="n">free</span> <span class="p">(</span><span class="n">log_message</span><span class="p">);</span>
|
||
|
|
||
|
<span class="cm">/* Increment shared log index number and close the file */</span>
|
||
|
<span class="p">(</span><span class="o">*</span><span class="n">params</span><span class="o">-></span><span class="n">log_index</span><span class="p">)</span><span class="o">++</span><span class="p">;</span>
|
||
|
<span class="n">fclose</span> <span class="p">(</span><span class="n">fp</span><span class="p">);</span>
|
||
|
|
||
|
<span class="cm">/* End of critical section */</span>
|
||
|
<span class="n">pthread_mutex_unlock</span> <span class="p">(</span><span class="n">params</span><span class="o">-></span><span class="n">mutex</span><span class="p">);</span>
|
||
|
<span class="p">}</span>
|
||
|
<span class="n">pthread_exit</span> <span class="p">(</span><span class="nb">NULL</span><span class="p">);</span>
|
||
|
<span class="p">}</span>
|
||
|
|
||
|
<span class="cm">/* Main entry point */</span>
|
||
|
<span class="kt">int</span>
|
||
|
<span class="nf">main</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span>
|
||
|
<span class="p">{</span>
|
||
|
<span class="cm">/* Create a bogus initial log to start with */</span>
|
||
|
<span class="n">create_initial_log</span> <span class="p">();</span>
|
||
|
<span class="kt">size_t</span> <span class="n">log_index</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
|
||
|
|
||
|
<span class="n">pthread_mutex_t</span> <span class="n">mutex</span><span class="p">;</span>
|
||
|
<span class="n">pthread_mutex_init</span> <span class="p">(</span><span class="o">&</span><span class="n">mutex</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>
|
||
|
|
||
|
<span class="cm">/* Create the thread parameters and the threads */</span>
|
||
|
<span class="n">pthread_t</span> <span class="n">threads</span><span class="p">[</span><span class="n">NUM_THREADS</span><span class="p">];</span>
|
||
|
<span class="k">struct</span> <span class="n">log_params</span> <span class="n">params</span><span class="p">[</span><span class="n">NUM_THREADS</span><span class="p">];</span>
|
||
|
<span class="kt">size_t</span> <span class="n">i</span><span class="p">;</span>
|
||
|
<span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">NUM_THREADS</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
|
||
|
<span class="p">{</span>
|
||
|
<span class="n">params</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">tid</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
|
||
|
<span class="n">params</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">mutex</span> <span class="o">=</span> <span class="o">&</span><span class="n">mutex</span><span class="p">;</span>
|
||
|
<span class="n">params</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">log_index</span> <span class="o">=</span> <span class="o">&</span><span class="n">log_index</span><span class="p">;</span>
|
||
|
<span class="n">params</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">iterations</span> <span class="o">=</span> <span class="n">NUM_ITERATIONS</span><span class="p">;</span>
|
||
|
<span class="n">pthread_create</span> <span class="p">(</span><span class="o">&</span><span class="n">threads</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">event_thread</span><span class="p">,</span> <span class="o">&</span><span class="n">params</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
|
||
|
<span class="p">}</span>
|
||
|
|
||
|
<span class="cm">/* Join the threads then destroy the mutex and exit */</span>
|
||
|
<span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">NUM_THREADS</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
|
||
|
<span class="n">pthread_join</span> <span class="p">(</span><span class="n">threads</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="nb">NULL</span><span class="p">);</span>
|
||
|
|
||
|
<span class="n">pthread_mutex_destroy</span> <span class="p">(</span><span class="o">&</span><span class="n">mutex</span><span class="p">);</span>
|
||
|
<span class="n">pthread_exit</span> <span class="p">(</span><span class="nb">NULL</span><span class="p">);</span>
|
||
|
<span class="p">}</span>
|
||
|
|
||
|
<span class="cm">/* Log file verification routine */</span>
|
||
|
<span class="kt">bool</span>
|
||
|
<span class="nf">verify_log</span> <span class="p">(</span><span class="kt">FILE</span> <span class="o">*</span><span class="n">fp</span><span class="p">)</span>
|
||
|
<span class="p">{</span>
|
||
|
<span class="cm">/* Compute the hash value from all lines except the last bytes</span>
|
||
|
<span class="cm"> that contain the final hash */</span>
|
||
|
<span class="kt">char</span> <span class="o">*</span><span class="n">computed</span> <span class="o">=</span> <span class="n">compute_log_hash</span> <span class="p">(</span><span class="n">fp</span><span class="p">,</span> <span class="n">SHALENGTH</span> <span class="o">+</span> <span class="mi">2</span><span class="p">);</span>
|
||
|
|
||
|
<span class="cm">/* Now read the final hash and confirm that it matches */</span>
|
||
|
<span class="kt">char</span> <span class="n">expected</span><span class="p">[</span><span class="n">SHALENGTH</span> <span class="o">+</span> <span class="mi">3</span><span class="p">];</span>
|
||
|
<span class="n">memset</span> <span class="p">(</span><span class="n">expected</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="n">expected</span><span class="p">));</span>
|
||
|
<span class="n">fread</span> <span class="p">(</span><span class="n">expected</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="kt">char</span><span class="p">),</span> <span class="n">SHALENGTH</span> <span class="o">+</span> <span class="mi">2</span><span class="p">,</span> <span class="n">fp</span><span class="p">);</span>
|
||
|
|
||
|
<span class="k">if</span> <span class="p">(</span><span class="n">strncmp</span> <span class="p">(</span><span class="n">computed</span><span class="p">,</span> <span class="n">expected</span><span class="p">,</span> <span class="n">SHALENGTH</span><span class="p">))</span>
|
||
|
<span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
|
||
|
|
||
|
<span class="n">free</span> <span class="p">(</span><span class="n">computed</span><span class="p">);</span>
|
||
|
<span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
|
||
|
<span class="p">}</span>
|
||
|
|
||
|
<span class="cm">/* Append a message to the log file */</span>
|
||
|
<span class="kt">void</span>
|
||
|
<span class="nf">append_log_message</span> <span class="p">(</span><span class="kt">FILE</span> <span class="o">*</span><span class="n">fp</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">index</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">message</span><span class="p">)</span>
|
||
|
<span class="p">{</span>
|
||
|
<span class="cm">/* Add the message at the end of the file and flush the data</span>
|
||
|
<span class="cm"> to ensure it gets written to disk */</span>
|
||
|
<span class="n">fseek</span> <span class="p">(</span><span class="n">fp</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">SEEK_END</span><span class="p">);</span>
|
||
|
<span class="n">fprintf</span> <span class="p">(</span><span class="n">fp</span><span class="p">,</span> <span class="s">"%zd: %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">index</span><span class="p">,</span> <span class="n">message</span><span class="p">);</span>
|
||
|
<span class="n">fflush</span> <span class="p">(</span><span class="n">fp</span><span class="p">);</span>
|
||
|
|
||
|
<span class="cm">/* Re-compute the hash with the new message and append it to</span>
|
||
|
<span class="cm"> the end of the file */</span>
|
||
|
<span class="kt">char</span> <span class="o">*</span><span class="n">computed</span> <span class="o">=</span> <span class="n">compute_log_hash</span> <span class="p">(</span><span class="n">fp</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
|
||
|
<span class="n">fseek</span> <span class="p">(</span><span class="n">fp</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">SEEK_END</span><span class="p">);</span>
|
||
|
<span class="n">fprintf</span> <span class="p">(</span><span class="n">fp</span><span class="p">,</span> <span class="s">"%s</span><span class="se">\n\n</span><span class="s">"</span><span class="p">,</span> <span class="n">computed</span><span class="p">);</span>
|
||
|
<span class="n">free</span> <span class="p">(</span><span class="n">computed</span><span class="p">);</span>
|
||
|
<span class="p">}</span>
|
||
|
|
||
|
<span class="cm">/* For a given file, compute the SHA-256 hash sum of the contents.</span>
|
||
|
<span class="cm"> The trailing parameter indicates the number of bytes at the</span>
|
||
|
<span class="cm"> end of the file to omit from the computation. Returns a</span>
|
||
|
<span class="cm"> dynamically allocated string that must be freed. */</span>
|
||
|
<span class="kt">char</span> <span class="o">*</span>
|
||
|
<span class="nf">compute_log_hash</span> <span class="p">(</span><span class="kt">FILE</span> <span class="o">*</span><span class="n">fp</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">trailing</span><span class="p">)</span>
|
||
|
<span class="p">{</span>
|
||
|
<span class="cm">/* Allocate pipes for parent-to-child communication and create</span>
|
||
|
<span class="cm"> a child process */</span>
|
||
|
<span class="kt">int</span> <span class="n">p2c_pipe</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">c2p_pipe</span><span class="p">[</span><span class="mi">2</span><span class="p">];</span>
|
||
|
<span class="n">pipe</span> <span class="p">(</span><span class="n">p2c_pipe</span><span class="p">);</span>
|
||
|
<span class="n">pipe</span> <span class="p">(</span><span class="n">c2p_pipe</span><span class="p">);</span>
|
||
|
<span class="kt">pid_t</span> <span class="n">child_pid</span> <span class="o">=</span> <span class="n">fork</span> <span class="p">();</span>
|
||
|
<span class="n">assert</span> <span class="p">(</span><span class="n">child_pid</span> <span class="o">>=</span> <span class="mi">0</span><span class="p">);</span>
|
||
|
|
||
|
<span class="cm">/* Child process will read data from the pipe, redirecting this</span>
|
||
|
<span class="cm"> data as stdin to the shasum program. The stdout will be</span>
|
||
|
<span class="cm"> redirected through the pipe back to the parent. */</span>
|
||
|
<span class="k">if</span> <span class="p">(</span><span class="n">child_pid</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
|
||
|
<span class="p">{</span>
|
||
|
<span class="n">close</span> <span class="p">(</span><span class="n">p2c_pipe</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
|
||
|
<span class="n">close</span> <span class="p">(</span><span class="n">c2p_pipe</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
|
||
|
<span class="n">dup2</span> <span class="p">(</span><span class="n">p2c_pipe</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">STDIN_FILENO</span><span class="p">);</span>
|
||
|
<span class="n">dup2</span> <span class="p">(</span><span class="n">c2p_pipe</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">STDOUT_FILENO</span><span class="p">);</span>
|
||
|
<span class="n">execlp</span> <span class="p">(</span><span class="s">"shasum"</span><span class="p">,</span> <span class="s">"shasum"</span><span class="p">,</span> <span class="s">"-a"</span><span class="p">,</span> <span class="s">"256"</span><span class="p">,</span> <span class="s">"-"</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>
|
||
|
<span class="p">}</span>
|
||
|
|
||
|
<span class="cm">/* Parent resumes from here by closing the unused pipe ends */</span>
|
||
|
<span class="n">close</span> <span class="p">(</span><span class="n">p2c_pipe</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
|
||
|
<span class="n">close</span> <span class="p">(</span><span class="n">c2p_pipe</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
|
||
|
|
||
|
<span class="cm">/* Determine the size of the file without the last two lines</span>
|
||
|
<span class="cm"> (containing a shasum and a blank line) */</span>
|
||
|
<span class="k">struct</span> <span class="n">stat</span> <span class="n">file_info</span><span class="p">;</span>
|
||
|
<span class="n">assert</span> <span class="p">(</span><span class="n">stat</span> <span class="p">(</span><span class="n">LOGFILE</span><span class="p">,</span> <span class="o">&</span><span class="n">file_info</span><span class="p">)</span> <span class="o">>=</span> <span class="mi">0</span><span class="p">);</span>
|
||
|
<span class="kt">size_t</span> <span class="n">remaining</span> <span class="o">=</span> <span class="n">file_info</span><span class="p">.</span><span class="n">st_size</span> <span class="o">-</span> <span class="n">trailing</span><span class="p">;</span>
|
||
|
<span class="n">fseek</span> <span class="p">(</span><span class="n">fp</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">SEEK_SET</span><span class="p">);</span>
|
||
|
|
||
|
<span class="cm">/* Instead of reading the entire file contents (which could be</span>
|
||
|
<span class="cm"> large), read a chunk at a time and write the contents into</span>
|
||
|
<span class="cm"> the pipe for the child to access */</span>
|
||
|
<span class="kt">size_t</span> <span class="n">size</span> <span class="o">=</span> <span class="mi">1024</span><span class="p">;</span>
|
||
|
<span class="kt">char</span> <span class="n">buffer</span><span class="p">[</span><span class="n">size</span> <span class="o">+</span> <span class="mi">1</span><span class="p">];</span>
|
||
|
<span class="k">while</span> <span class="p">(</span><span class="n">remaining</span> <span class="o">></span> <span class="n">size</span><span class="p">)</span>
|
||
|
<span class="p">{</span>
|
||
|
<span class="n">memset</span> <span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="n">buffer</span><span class="p">));</span>
|
||
|
<span class="n">fread</span> <span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="kt">char</span><span class="p">),</span> <span class="n">size</span><span class="p">,</span> <span class="n">fp</span><span class="p">);</span>
|
||
|
<span class="n">write</span> <span class="p">(</span><span class="n">p2c_pipe</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">buffer</span><span class="p">,</span> <span class="n">size</span><span class="p">);</span>
|
||
|
<span class="n">remaining</span> <span class="o">-=</span> <span class="n">size</span><span class="p">;</span>
|
||
|
<span class="p">}</span>
|
||
|
|
||
|
<span class="cm">/* If there is any left over, read those bytes and send them to</span>
|
||
|
<span class="cm"> the child */</span>
|
||
|
<span class="k">if</span> <span class="p">(</span><span class="n">remaining</span> <span class="o">></span> <span class="mi">0</span><span class="p">)</span>
|
||
|
<span class="p">{</span>
|
||
|
<span class="n">memset</span> <span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="n">buffer</span><span class="p">));</span>
|
||
|
<span class="n">fread</span> <span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="kt">char</span><span class="p">),</span> <span class="n">remaining</span><span class="p">,</span> <span class="n">fp</span><span class="p">);</span>
|
||
|
<span class="n">write</span> <span class="p">(</span><span class="n">p2c_pipe</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">buffer</span><span class="p">,</span> <span class="n">remaining</span><span class="p">);</span>
|
||
|
<span class="p">}</span>
|
||
|
|
||
|
<span class="cm">/* All data have been written, so close the pipe so the child</span>
|
||
|
<span class="cm"> can finalize its calculation */</span>
|
||
|
<span class="n">close</span> <span class="p">(</span><span class="n">p2c_pipe</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
|
||
|
|
||
|
<span class="cm">/* Read the computed shasum back and compare it with the last</span>
|
||
|
<span class="cm"> shasum in the file */</span>
|
||
|
<span class="kt">char</span> <span class="n">shabuf</span><span class="p">[</span><span class="n">SHALENGTH</span> <span class="o">+</span> <span class="mi">1</span><span class="p">];</span>
|
||
|
<span class="n">memset</span> <span class="p">(</span><span class="n">shabuf</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="n">shabuf</span><span class="p">));</span>
|
||
|
<span class="n">read</span> <span class="p">(</span><span class="n">c2p_pipe</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">shabuf</span><span class="p">,</span> <span class="n">SHALENGTH</span><span class="p">);</span>
|
||
|
<span class="n">close</span> <span class="p">(</span><span class="n">c2p_pipe</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
|
||
|
|
||
|
<span class="k">return</span> <span class="n">strdup</span> <span class="p">(</span><span class="n">shabuf</span><span class="p">);</span>
|
||
|
<span class="p">}</span>
|
||
|
|
||
|
<span class="cm">/* asctime_r returns 24 characters plus \n and \0 */</span>
|
||
|
<span class="cp">#define ASCTIME_BUFSIZE 26</span>
|
||
|
|
||
|
<span class="kt">char</span> <span class="o">*</span>
|
||
|
<span class="nf">generate_random_log</span> <span class="p">(</span><span class="kt">int</span> <span class="n">tid</span><span class="p">)</span>
|
||
|
<span class="p">{</span>
|
||
|
<span class="cm">/* Determine the current local time and convert it to an</span>
|
||
|
<span class="cm"> ASCII-printable format */</span>
|
||
|
<span class="kt">char</span> <span class="n">timebuf</span><span class="p">[</span><span class="n">ASCTIME_BUFSIZE</span><span class="p">];</span>
|
||
|
<span class="n">memset</span> <span class="p">(</span><span class="n">timebuf</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="n">timebuf</span><span class="p">));</span>
|
||
|
<span class="k">struct</span> <span class="n">tm</span> <span class="n">localbuf</span><span class="p">;</span>
|
||
|
<span class="n">memset</span> <span class="p">(</span><span class="o">&</span><span class="n">localbuf</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="n">localbuf</span><span class="p">));</span>
|
||
|
|
||
|
<span class="kt">time_t</span> <span class="n">current</span> <span class="o">=</span> <span class="n">time</span> <span class="p">(</span><span class="nb">NULL</span><span class="p">);</span>
|
||
|
<span class="k">struct</span> <span class="n">tm</span> <span class="o">*</span><span class="n">local</span> <span class="o">=</span> <span class="n">localtime_r</span> <span class="p">(</span><span class="o">&</span><span class="n">current</span><span class="p">,</span> <span class="o">&</span><span class="n">localbuf</span><span class="p">);</span>
|
||
|
<span class="kt">char</span> <span class="o">*</span><span class="n">timemsg</span> <span class="o">=</span> <span class="n">asctime_r</span> <span class="p">(</span><span class="n">local</span><span class="p">,</span> <span class="n">timebuf</span><span class="p">);</span>
|
||
|
|
||
|
<span class="kt">char</span> <span class="o">*</span><span class="n">message</span> <span class="o">=</span> <span class="n">calloc</span> <span class="p">(</span><span class="mi">100</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="kt">char</span><span class="p">));</span>
|
||
|
<span class="n">assert</span> <span class="p">(</span><span class="n">message</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">);</span>
|
||
|
|
||
|
<span class="cm">/* Use the ASCII-formatted time to create a log message like:</span>
|
||
|
<span class="cm"> [Wed Jun 26 10:32:15 1996] Event from thread 5</span>
|
||
|
<span class="cm"> */</span>
|
||
|
<span class="n">message</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'['</span><span class="p">;</span>
|
||
|
<span class="n">strncpy</span> <span class="p">(</span><span class="o">&</span><span class="n">message</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">timemsg</span><span class="p">,</span> <span class="n">ASCTIME_BUFSIZE</span> <span class="o">-</span> <span class="mi">2</span><span class="p">);</span>
|
||
|
<span class="n">strncat</span> <span class="p">(</span><span class="n">message</span><span class="p">,</span> <span class="s">"] Event from thread "</span><span class="p">,</span> <span class="mi">100</span> <span class="o">-</span> <span class="n">ASCTIME_BUFSIZE</span><span class="p">);</span>
|
||
|
<span class="n">snprintf</span> <span class="p">(</span><span class="o">&</span><span class="n">message</span><span class="p">[</span><span class="n">ASCTIME_BUFSIZE</span> <span class="o">+</span> <span class="mi">19</span><span class="p">],</span> <span class="mi">100</span> <span class="o">-</span> <span class="n">strlen</span> <span class="p">(</span><span class="n">message</span><span class="p">),</span> <span class="s">"%d"</span><span class="p">,</span> <span class="n">tid</span><span class="p">);</span>
|
||
|
|
||
|
<span class="cm">/* Return a heap-allocated copy of the string */</span>
|
||
|
<span class="k">return</span> <span class="n">strdup</span> <span class="p">(</span><span class="n">message</span><span class="p">);</span>
|
||
|
<span class="p">}</span>
|
||
|
|
||
|
<span class="cm">/* Create bogus initial commit message to have a starting point */</span>
|
||
|
<span class="kt">void</span>
|
||
|
<span class="nf">create_initial_log</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span>
|
||
|
<span class="p">{</span>
|
||
|
<span class="n">unlink</span> <span class="p">(</span><span class="n">LOGFILE</span><span class="p">);</span>
|
||
|
<span class="k">struct</span> <span class="n">stat</span> <span class="n">file_info</span><span class="p">;</span>
|
||
|
<span class="n">stat</span> <span class="p">(</span><span class="n">LOGFILE</span><span class="p">,</span> <span class="o">&</span><span class="n">file_info</span><span class="p">);</span>
|
||
|
|
||
|
<span class="kt">int</span> <span class="n">file</span> <span class="o">=</span> <span class="n">open</span> <span class="p">(</span><span class="n">LOGFILE</span><span class="p">,</span> <span class="n">O_RDWR</span> <span class="o">|</span> <span class="n">O_CREAT</span><span class="p">);</span>
|
||
|
<span class="n">assert</span> <span class="p">(</span><span class="n">file</span> <span class="o">>=</span> <span class="mi">0</span><span class="p">);</span>
|
||
|
|
||
|
<span class="n">fchmod</span> <span class="p">(</span><span class="n">file</span><span class="p">,</span> <span class="mo">0644</span><span class="p">);</span>
|
||
|
<span class="n">write</span> <span class="p">(</span><span class="n">file</span><span class="p">,</span> <span class="s">"0: [Tue Jun 25 22:09:41 2019] Initial commit</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="mi">45</span><span class="p">);</span>
|
||
|
<span class="n">write</span> <span class="p">(</span><span class="n">file</span><span class="p">,</span> <span class="s">"6231aaee038b4ab9b3fd50e5bf604f26"</span>
|
||
|
<span class="s">"97af98b5c126f4f86f5aaca809439c65</span><span class="se">\n\n</span><span class="s">"</span><span class="p">,</span> <span class="n">SHALENGTH</span> <span class="o">+</span> <span class="mi">2</span><span class="p">);</span>
|
||
|
<span class="n">close</span> <span class="p">(</span><span class="n">file</span><span class="p">);</span>
|
||
|
<span class="p">}</span>
|
||
|
</pre></div>
|
||
|
</td></tr></table></div>
|
||
|
</div>
|
||
|
|
||
|
|
||
|
</div>
|
||
|
|
||
|
|
||
|
|
||
|
<div class="container">
|
||
|
|
||
|
<div class="mt-4 container center">
|
||
|
«  <a id="prevmod1" href="Deadlock.html">7.7. Deadlock</a>
|
||
|
  ::  
|
||
|
<a class="uplink" href="index.html">Contents</a>
|
||
|
  ::  
|
||
|
<a id="nextmod1" href="SynchProblemsOverview.html">8.1. Synchronization Patterns and Problems</a>  »
|
||
|
</div>
|
||
|
|
||
|
|
||
|
</div>
|
||
|
|
||
|
<br />
|
||
|
|
||
|
<div class="row jmu-dark-purple-bg">
|
||
|
<div class="col-md-12">
|
||
|
<center>
|
||
|
<a id="contact_us" class="btn button-link-no-blue jmu-gold" rel="nofollow" href="mailto:webmaster@opencsf.org" role="button">Contact Us</a>
|
||
|
<a id="license" class="btn button-link-no-blue jmu-gold" rel="nofollow" href="https://w3.cs.jmu.edu/kirkpams/OpenCSF/lib/license.html" target="_blank">License</a>
|
||
|
</center>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
<script src="_static/js/popper.js-1.14.7-min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
|
||
|
<script src="_static/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
|
||
|
</body>
|
||
|
</html>
|