Dust and Stars - 1992 | Chapter 151 | State and Rollback | English
Morning light slanted through the high exhaust window of the machine room, cutting across the keyboard. Dust drifted slowly in the
Chapter 151: State and Rollback
Morning light slanted through the high exhaust window of the machine room, cutting across the keyboard. Dust drifted slowly in the beam like some mute timer. Lin Chen stared at checkpoint_manager.c, the cursor resting on line 47. He needed to define a struct to record the current parsing offset, the file handle of the temporary file already written, and the hash value from the most recent successful validation. The heart of crash recovery was not blind retries, but rolling back precisely to the last safe state.
He typed typedef struct { off_t offset; int fd; char md5[33]; } checkpoint_t;. The memory alignment had to be handled properly to keep false sharing on cache lines from slowing down reads. Then came the write logic: after every hundred thousand lines processed, flush the struct to disk. He could not flush too often or I/O would drag down the main thread; he could not wait too long either, because a crash would become too costly. He set up a double safeguard: a memory threshold trigger plus a timed heartbeat. fsync would force the data to disk. The cost was higher single-request latency, but the data would survive.
His left leg started twitching again under the desk. He stopped typing and shoved the chair back half an inch, letting his heel hang in the air. There was only a little Yunnan Baiyao left in the drawer; what came out was a thin mist carrying the sharp smell of alcohol. He rubbed his calf. The muscle was hard as stone, and when he pressed down with his fingertips he could feel the fascia sticking. The time read 06:10. Fifty-six hours remained until Wednesday at two in the afternoon. He could not sleep. Sleep would break his flow, and once he stayed still the injury in his foot would stiffen even more. He got up and went to the washroom, splashing cold water on his face. The water from the tap was icy enough to make him shiver. He was awake again.
Back at his seat, he kept writing the rollback logic for exceptions. When the parser encountered a corrupted block, it could not simply crash; it had to skip the block, record the offset, and trigger a rollback to the previous checkpoint. He introduced a ring buffer for the error log and used atomic operations to keep multithreaded writes from colliding. Compile. On the first run, the terminal spat out Segmentation fault. The core dump showed that when the consumer thread read a corrupted block, a pointer went out of bounds and touched an uninitialized buffer. He added boundary checks and compiled again. On the second run, there was a memory leak. valgrind reported that every time a rollback was triggered, the temporary file descriptor was not being closed properly. He added close(fd) and put another state lock into the cleanup function. The third compile passed.
He imported five hundred thousand lines of test data, with ten percent intentionally seeded with garbled text and truncated rows. The terminal output began to scroll. The memory curve held steady at 38MB. Time: 4.1s. He kept his eyes on the log file. The checkpoint records were intact, corrupted blocks were skipped with precision, and the rollback offsets were correct. It met the mark. But he knew this was only local validation. File-lock contention during concurrent writes across three million lines would decide whether he lived or died at Wednesday's acceptance test. He pulled up the mmap region and wrote the checkpoint metadata directly into shared memory, bypassing system calls. The C extension on the Python side would have to be wrapped again to expose two functions: init_checkpoint and rollback_to.
The door to the machine room opened, and Old Chen the security guard came in carrying a thermos. His footsteps echoed down the empty hallway. When he saw Lin Chen, he paused. "Kid, you pulled another all-nighter?" Lin Chen nodded without speaking. Old Chen set the thermos down at the duty desk and sighed. "You computer people burn your lives up on electricity. Have you eaten breakfast yet?" Lin Chen shook his head. Old Chen fished two plastic bags out of his pocket. Inside were still-warm tea eggs and steamed buns. "Just out of the cafeteria. Picked them up on the way. Don't try to brute-force everything. Machines can reboot. People can't." Lin Chen took them and murmured a thank-you. The warmth of the plastic seeped into his fingertips. It felt solid, real. He peeled an egg and took a bite. Protein and starch landed in his stomach, and the hollow ache in his abdomen finally settled. The 810.4 yuan in his online banking account could not be touched; that was the cushion for Xiaoman's medicine changes. But the calories in front of him were enough to carry him through the afternoon.
After eating, he kept going. Wrapping the C extension meant dealing with Python's GIL. In version 2.4, the GIL had to be released before C threads could truly run in parallel. He added the Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS macros. The codebase swelled again. He had to make sure that while the GIL was released, no Python object would be accidentally reclaimed by garbage collection. Increment the reference count, decrement it, one step at a time, no mistakes allowed. He opened his notebook and sketched the life cycle of the reference counts. The arrows pointed to explicit release points. There was no gray area.
By nine in the morning, sunlight had completely spread across the desk. More and more people trickled into the machine room, keyboard clatter rising and falling around him. Lin Chen put on noise-canceling headphones. The world narrowed to the hum of the fans and the tapping of code. His left foot was so swollen that it no longer fit in his usual sneakers, so he changed into a loose pair of slippers. Every forty minutes of sitting, he had to stand and hobble a lap along the wall. The dull ache in his knee had become a steady burn, as if fine needles were scraping at the periosteum. He did not care. The progress bar was moving forward. That felt more real than pain.
At one in the afternoon, the full three-million-line test began. The memory curve started to climb. 30MB, 42MB, 48MB... then it stopped at 49.7MB. Latency: 13.4s. That worked out to about 44 milliseconds per ten thousand lines, far below the red line of 300 milliseconds. Corrupted blocks were handled normally, checkpoint rollback succeeded. He stared at the screen, fingers hovering over the keyboard, and did not celebrate at once. It was too quiet. He pulled up system monitoring and found the disk I/O wait time unusually high. Memory had not exploded, but the random writes on the hard drive were already close to the limit. If the acceptance environment on Wednesday used a faster SSD array, this logic would hold. But if they used an old mechanical disk, concurrent writes could trigger I/O stalls and send the latency soaring.
He needed a fallback plan. At the configuration layer, he would add an I/O scheduling strategy to detect the disk type and automatically switch between synchronous and asynchronous write modes. But that meant adding another layer of system-call probing, and the code complexity would jump again. Less than thirty hours remained. He created a new file and named it io_scheduler.c. His phone vibrated on the desk. A message from Engineer Li: "Wednesday's acceptance test: the deputy director of technical affairs and an outside expert will both be there. The demo environment is locked down. No last-minute config changes allowed. Bring the final build. If it doesn't run, you're out."
Lin Chen stared at the screen. No configuration changes allowed. That meant he had to hard-code the adaptive logic, or figure out the hardware parameters of the acceptance machine in advance. He checked the asset sheet for the training camp's machine room: Zone B, Machine 3, hard drive model Seagate ST3500418AS, 5400 RPM, SATA II. A mechanical disk. The I/O bottleneck was inevitable. He could not gamble. At the parser layer, he had to turn random writes into sequential writes through pre-buffering. That meant refactoring the consumer thread's write queue and introducing a double-buffer mechanism.
He took a deep breath, slipped his left foot out of the slipper, and rested it on an ice-cold bottle of mineral water. The chill climbed from the sole upward and pressed down the burning pain. He typed the first line of comment: // Goal: replace random writes with sequential writes; decouple I/O from parsing through double buffering.
The clouds outside broke apart, and the sunlight turned harsh. The air conditioner in the machine room kicked on again, blowing out dry air. His fingers came down on the keys. The rhythm was slow, but steady. In the bottom-right corner of the screen, the clock ticked soundlessly toward 13:45.
More from WayDigital
Continue through other published articles from the same publisher.
Comments
0 public responses
All visitors can read comments. Sign in to join the discussion.
Log in to comment