לדלג לתוכן

פתרון זיכרון משותף והתאוששות עמית

הכתובת הווירטואלית של view שייכת לתהליך. לכן שדה שמכיל pointer מתהליך אחד אינו כתובת שימושית בתהליך השני. שדה offset מתפרש ביחס לבסיס המקומי, לאחר בדיקת גבולות.

בדיקת טווח נכונה נראית כך:

bool valid_range(std::uint64_t mapping_size,
                 std::uint64_t offset, std::uint64_t length) {
    return offset <= mapping_size && length <= mapping_size - offset;
}

אם הטבלה מכילה count רשומות בגודל record_size, בודקים קודם ש־count אינו גדול מן הגבול המותר וש־record_size אינו אפס. כדי למנוע overflow, אפשר לבדוק count קטן או שווה ל־remaining חלקי record_size לפני הכפל. רק לאחר מכן ממירים ל־size_t של התהליך.

נטישה והמשך

תהליך שמקבל WAIT_ABANDONED כבר מחזיק את ה־mutex. לכן גם מסלול השגיאה שלו צריך לשחרר בעלות. הנתונים יכולים להיות תקינים או חלקיים, והקוד אינו יודע זאת רק מתוך תוצאת ההמתנה.

ניסוי מבוקר מוסיף נקודת עצירה מפורשת לאחר רכישה. תהליך אחר מחכה, ואז תהליך הבדיקה הראשון מסתיים. התוצאה הצפויה היא דיווח על נטישה והימנעות מעדכון נוסף. הדוח צריך לציין בדיוק באיזה שלב הופסק הבעלים.

דורות ומקור אמת

ב־recovery אפשר ליצור מיפוי חדש עם מספר דור חדש ולשחזר אליו רק עסקאות מאושרות מן היומן. תהליכים שמצטרפים מקבלים את הדור הנוכחי דרך מנגנון בקרה מהימן. כל פעולה בודקת שה־session שלה עדיין שייך לדור הפעיל לפי הפרוטוקול.

אין די בשדה generation בתוך מיפוי ישן אם תהליך ישן ממשיך לכתוב אליו בלי להתייעץ עם מנגנון הבקרה. צריך למנוע ממנו לפרסם תוצאה או לשתף פעולה עם השרת החדש, למשל באמצעות מזהה session ומסלול בקשות שמאמת אותו. השארת view ישן בחיים יכולה להיות מותרת עבור קורא מבודד, אבל אינה מעניקה לו סמכות לשנות את הדור החדש.

היומן העמיד מחזיק את המידע שאסור לאבד, והמיפוי הוא תצוגה שאפשר לבנות מחדש. ההפרדה מצמצמת את מספר התרחישים שבהם צריך לתקן מבנה משותף שנשאר באמצע שינוי.