זיהוי פתיחה וסגירה של קבצים מיותרים ב-COBOL

כיצד לזהות פתיחה וסגירה של קבצים מיותרים ב-COBOL: גישת ניתוח סטטי

טיפול בקבצים ב-COBOL הוא פשוט באופן מטעה על פני השטח. אתה מכריז על קובץ ב-ENVIRONMENT DIVISION, מתאר את פריסת הרשומה שלו ב-DATA DIVISION, ומשתמש ב-OPEN, READ או WRITE, ו-CLOSE ב-PRODUCTION DIVISION. ארבעה פעלים, מחזור חיים אחד. הבעיה היא שתוכניות COBOL כמעט ולא נשארות פשוטות, הן צוברות לוגיקה, נתיבי חריגים, ענפים מותנים וקריאות PERFORM במשך עשרות שנים של תחזוקה. מה שמתחיל כתבנית נקייה של פתיחה אחת וסגירה אחת, הופך בשקט למשהו מורכב יותר: קבצים שנפתחים פעמיים בנתיב ביצוע יחיד, פקודות CLOSE שפועלות כאשר אין קובץ פתוח, שגיאה יוצאת לחלוטין מהענף הזה מעבר ל-CLOSE.

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

גילוי דליפות בכל שפה

SMART TS XL ממפה שרשראות ייחוס ארוכות טווח ומבני נתונים בלתי מוגבלים על פני בסיס הקוד המלא שלך.

מידע נוסף

ארבעת פגמי מצב הקובץ שכדאי למצוא

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

פגםמה קורה בזמן ריצהחומרה
פתוח כפולפתיחה על קובץ שכבר פתוח → סטטוס קובץ 41 או ביטולגָבוֹהַ
סגירה ללא פתיחה מוקדמתסגור על קובץ שמעולם לא נפתח → סטטוס קובץ 42 או סגורגָבוֹהַ
חסר סגירה ביציאה רגילהקובץ שנותר פתוח ב-STOP RUN → מערכת ההפעלה סוגרת אותו, אך מאגרים שלא נמחקו מסתכנים באובדן נתוניםבינוני
חסר סגירה ביציאה משגיאההתוכנית נסגרת עם קובץ פתוח → פגיעה אפשרית ברשומות בקבצי VSAMגָבוֹהַ
פתיחה/סגירה מיותרת בלולאהקובץ נפתח ונסגר בכל איטרציה → תקרת קלט/פלט חמורהבינוני גבוה

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

מה מקשה על מציאת זה ידנית

האתגר הוא לא לזהות את התבנית. כל מפתח יודע שאסור לפתוח קובץ פעמיים. האתגר הוא שזרימת הבקרה של COBOL אינה לינארית באופן שהופך את המעקב הידני ללא אמין.

נבחן תוכנית עם מבנה כזה:

קובול

       PROCEDURE DIVISION.
       MAIN-LOGIC.
           PERFORM INITIALIZATION
           PERFORM PROCESS-RECORDS
           PERFORM TERMINATION
           STOP RUN.

       INITIALIZATION.
           OPEN INPUT CUSTOMER-FILE
           OPEN OUTPUT REPORT-FILE
           MOVE 0 TO WS-ERROR-FLAG.

       PROCESS-RECORDS.
           READ CUSTOMER-FILE INTO WS-CUSTOMER-REC
               AT END MOVE 1 TO WS-EOF-FLAG
           END-READ
           IF WS-ERROR-FLAG = 1
               PERFORM ERROR-EXIT
           END-IF
           PERFORM UNTIL WS-EOF-FLAG = 1
               PERFORM PROCESS-ONE-RECORD
               READ CUSTOMER-FILE INTO WS-CUSTOMER-REC
                   AT END MOVE 1 TO WS-EOF-FLAG
               END-EXEC
           END-PERFORM.

       ERROR-EXIT.
           DISPLAY 'Error in processing'
           CLOSE CUSTOMER-FILE    *> CLOSE here...
           STOP RUN.

       TERMINATION.
           CLOSE CUSTOMER-FILE    *> ...and CLOSE here too
           CLOSE REPORT-FILE
           STOP RUN.

האם ניתן לאתר את הפגם מבלי לעקוב אחר כל נתיב ביצוע? WS-ERROR-FLAG מוגדר ל-1 בפנים PROCESS-ONE-RECORD (אולי על ידי תת-תוכנית שנקראה), הבקרה זורמת אל ERROR-EXIT, אשר סוגר את הקובץ ועוצר. זה נכון. אבל אם WS-ERROR-FLAG is לֹא מוגדר, הלולאה הושלמה, PROCESS-RECORDS החזרות, ו TERMINATION ריצות, אשר גם נסגרות CUSTOMER-FILEשתי סגירות, פתיחה אחת. סטטוס קובץ בזמן ריצה 42.

זוהי תוכנית פשוטה בת שלושה חלקים. לתוכניות אמיתיות יש עשרים חלקים, קריאות PERFORM מותנות, פקודות GO TO בקוד מדור קודם, ושגרות טיפול בחריגים שקוראות בעצמן לרוטינות אחרות. מעקב ידני אינו רק מועד לשגיאות, הוא אינו ניתן לניהול.


כיצד ניתוח סטטי מדמה את מצב הקובץ

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

הניתוח מקצה לכל קובץ משתנה מצב עם שלושה ערכים אפשריים:

  • CLOSED, הקובץ לא נפתח, או נסגר בהצלחה
  • OPENהקובץ נפתח ועדיין לא נסגר
  • UNKNOWN, לא ניתן לקבוע את המצב באופן סטטי (למשל, פתיחה מותנית בענף שלא נותח במלואו)

בכל פקודה OPEN, הניתוח בודק: האם קובץ זה כבר במצב OPENאם כן → פגם פתוח כפול.

בכל משפט CLOSE: האם קובץ זה במצב CLOSED or UNKNOWNאם סגור → סגור ללא פגם פתוח.

בכל נתיב ל-STOP RUN או EXIT PROGRAM: האם קובץ כלשהו עדיין במצבו? OPENאם כן → פגם סגור חסר.

עבור לולאות, הניתוח בודק האם פקודה OPEN או CLOSE נשלטת על ידי כותרת לולאה, כלומר היא מבצעת כל איטרציה.

היזהר: המקרים הקשים ביותר עבור כל מנתח הם קריאות PERFORM לתוך שגרות משותפות. אם ERROR-HANDLER נקרא משנים עשר מקומות שונים בתוכנית, מצב הקובץ בנקודת הקריאה של PERFORM קובע האם סגירה בתוך ERROR-HANDLER נכון או שגוי. מנתח שאינו מפיץ מצב דרך שרשראות PERFORM יפיק תוצאות שליליות שגויות (חסרי פגמים אמיתיים) או תוצאות חיוביות שגויות (סימון קוד נכון).


פתיחה/סגירה ברמת הלולאה: פגם ביצועים ללא קוד שגיאה

תבנית זו אינה מייצרת שגיאות זמן ריצה ואינה אנומליה ב-FILE STATUS. היא פשוט פועלת לאט, אולי אפילו סדרי גודל איטיים יותר מהנדרש.

קובול

      *> PROBLEMATIC: file opened and closed on every iteration
       PROCESS-ALL-REGIONS.
           PERFORM VARYING WS-REGION-ID FROM 1 BY 1
               UNTIL WS-REGION-ID > 10
               OPEN INPUT CUSTOMER-FILE
               PERFORM PROCESS-REGION-RECORDS
               CLOSE CUSTOMER-FILE
           END-PERFORM.

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

כל פתיחה (OPEN) בקובץ VSAM כרוכה בחיפוש קטלוג, אתחול ACB והקצאת מאגר מאגרים. כל סגירה (CLOSE) מרוקנת את המאגרים, מעדכנת את הקטלוג ומשחררת את ה-ACB. עבור קובץ עם עשרה אזורים, זה קורה עשר פעמים במקום פעם אחת. עבור קובץ עם 10,000 רשומות ואלף אזורים, החישוב הופך לכואב.

קובול

      *> CORRECT: open once, filter inside the loop
       PROCESS-ALL-REGIONS.
           OPEN INPUT CUSTOMER-FILE
           PERFORM VARYING WS-REGION-ID FROM 1 BY 1
               UNTIL WS-REGION-ID > 10
               PERFORM PROCESS-REGION-RECORDS
           END-PERFORM
           CLOSE CUSTOMER-FILE.

ניתוח סטטי מזהה זאת על ידי זיהוי פקודות OPEN ו-CLOSE הנשלטות על ידי לולאה, כלומר, כל ביצוע של גוף הלולאה מבצע את ה-OPEN או CLOSE. הזיהוי דורש שגרף זרימת הבקרה ייצג את מבנה הלולאה, ולא רק את רצף הפקודות.


סטטוס קובץ: אות מצב הקובץ של התוכנית שלך, אם תבדוק אותו

כל פעולת קובץ COBOL מגדירה את השדה FILE STATUS המוגדר בערך FILE-CONTROL. תוכנית שבודקת את FILE STATUS לאחר כל OPEN, READ, WRITE ו-CLOSE יכולה לזהות ולהגיב לכל אנומליה במצב קובץ בזמן ריצה. תוכנית שמתעלמת מ-FILE STATUS טסה בעיוורון.

רשימת בדיקה: קודי סטטוס קובץ שכל מפתח COBOL צריך להכיר

  • 00, השלמה מוצלחת
  • 10, סוף קובץ (קריאה: אין עוד רשומות)
  • 35, קובץ לא נמצא (פתח קלט: קובץ לא קיים)
  • 41הקובץ כבר פתוח (OPEN על קובץ במצב OPEN)
  • 42, הקובץ לא נפתח (סגור או קריאה עבור קובץ במצב סגור)
  • 47ניסיון קריאה בקובץ שלא נפתח, קלט או קלט/פלט
  • 48ניסיון כתיבה על קובץ שלא נפתח: OUTPUT, IO או EXTEND
  • 97, הקובץ נפתח בהצלחה (ספציפי ל-IBM, סביבות מסוימות)

קובול

       FILE-CONTROL.
           SELECT CUSTOMER-FILE
               ASSIGN TO CUSTFILE
               FILE STATUS IS WS-CUST-FILE-STATUS.

       WORKING-STORAGE SECTION.
       01 WS-CUST-FILE-STATUS   PIC XX.

       PROCEDURE DIVISION.
           OPEN INPUT CUSTOMER-FILE
           IF WS-CUST-FILE-STATUS NOT = '00'
               DISPLAY 'OPEN failed: ' WS-CUST-FILE-STATUS
               PERFORM ABEND-ROUTINE
           END-IF.

היזהר: שגיאת תחזוקה נפוצה היא הצהרת FILE STATUS בערך FILE-CONTROL אך לעולם לא הפניה אליו WS-CUST-FILE-STATUS ב-PROCEDURE DIVISION. השדה מאוכלס לאחר כל פעולת קובץ, אך אם אף קוד לא בודק אותו, התוכנית תרוץ על פני שגיאות בשקט. ניתוח סטטי יכול לסמן דפוס זה: FILE STATUS הוצהר אך מעולם לא הופנה אליו בלוגיקה מותנית.


שלוש תבניות COBOL מהעולם האמיתי שגורמות לפגמים

תבנית 1: בעיית השגיאה-יציאה המשותפת

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

קובול

       VALIDATE-RECORDS.
           READ CUSTOMER-FILE INTO WS-REC
               AT END MOVE 1 TO WS-EOF
           END-READ
           IF WS-CUST-FILE-STATUS NOT = '00' AND '10'
               CLOSE CUSTOMER-FILE    *> closes here on read error
               PERFORM WRITE-ERROR-LOG
               GO TO TERMINATION      *> skips to close in TERMINATION?
           END-IF.

       TERMINATION.
           CLOSE CUSTOMER-FILE        *> double close if GO TO reached here
           CLOSE REPORT-FILE
           STOP RUN.

השמיים GO TO TERMINATION מעביר שליטה ישירות אל TERMINATION, אשר מבצעת את עצמה CLOSE CUSTOMER-FILEסטטוס קובץ 42.

תיקון: השתמשו בשגרת סגירה מרכזית אחת. כל נתיב יציאה קורא לאותה שגרה, שבודקת האם הקובץ פתוח לפני הסגירה.

תבנית 2: הפתיחה המותנית

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

קובול

       INITIALIZATION.
           IF WS-PROCESSING-MODE = 'FULL'
               OPEN OUTPUT AUDIT-FILE   *> only opened in FULL mode
           END-IF.

       TERMINATION.
           CLOSE AUDIT-FILE    *> ALWAYS closes -- FILE STATUS 42 in PARTIAL mode
           STOP RUN.

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

תבנית 3: ביצוע על פני יחידות קומפילציה

בתוכניות המשתמשות ב-CALL כדי להפעיל תת-תוכניות, קובץ שנפתח בתוכנית הראשית עשוי להיות מועבר לתת-תוכנית שסוגרת אותו, ואז התוכנית הראשית סוגרת אותו שוב.

קובול

      *> Main program
       CALL 'SUBPROG1' USING CUSTOMER-FILE-STATUS
       *> SUBPROG1 closes CUSTOMER-FILE internally
       CLOSE CUSTOMER-FILE    *> double close

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


מה מנתח סטטי צריך כדי לעשות זאת היטב

לא כל כלי הניתוח הסטטי מטפלים בניתוח מצב קבצי COBOL באותה עומק. הנה רשימת בדיקה להערכת יכולות:

האם הכלי מטפל בשרשראות PERFORM? תוכניות COBOL משתמשות ב-PERFORM כדי לקרוא לפסקאות וסעיפים בעלי שם. פעולות קבצים בתוך יעד PERFORM חייבות להיות גלויות למעקב המצב של הקורא.

האם הכלי מטפל ב-inline PERFORM VARYING (לולאות)? זיהוי לולאות נדרש כדי לזהות פעולות OPEN/CLOSE הנשלטות על ידי לולאה.

האם זה עוקב אחר מצב לאורך GO TO? תוכניות COBOL מדור קודם משתמשות ב-GO TO בהרחבה. מנתח שאינו יכול לעקוב אחר קצוות GO TO בגרף זרימת הבקרה יפספס מחלקות שלמות של פגמים.

האם הוא מטפל ב-COPY וב-REPLACE? קוד לטיפול בקבצים נמצא לרוב באיברי COPY. מנתח שאינו מרחיב איברי COPY לפני הניתוח יחמיץ פעולות המוגדרות בקוד הכלול.

האם זה בודק את השימוש ב-FILE STATUS? ניתוח מלא בודק לא רק האם FILE STATUS מוצהר, אלא האם הוא אכן נבדק לאחר כל פעולה.

האם הוא מבצע ניתוח בין-פרוצדורלי? תת-תוכניות שנקראו ומבצעות פעולות קבצים יוצרות תלויות מצב בין-תוכניות. כיסוי אמיתי דורש ביצוע שרשראות CALL.

מסקנה חשובה: כלי שבודק רק פסקה או מקטע בודד יחמיץ את רוב הפגמים בעולם האמיתי. הפגמים החשובים בייצור, אלה שלקח שנים להופיע ושעות לאבחון, הם אלה שמשתרעים על פני מקטעים מרובים, ענפים מותנים, ו"רוטינות".


מה לעשות עם התוצאות: מסגרת קביעת סדרי עדיפויות

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

תקן מיד (לפני ריצת האצווה הבאה):

  • פתיחה כפולה בכל נתיב ביצוע שבו FILE STATUS 41 יגרום לשגיאה
  • סגירה ללא פתיחה בנתיבים שמבוצעים בסביבת ייצור
  • חסר סגירה בנתיבי יציאה משגיאות עבור קבצי VSAM (סיכון שלמות כתיבה)

לוח זמנים לספרינט הבא:

  • פתיחה/סגירה הנשלטת על ידי לולאה עם השפעה מדידה של חלון אצווה
  • בדיקות סטטוס קובץ חסרות בקבצים קריטיים (ביקורת, עסקה, דוח)
  • פתיחה מותנית עם סגירה ללא תנאי בתוכניות מרובות מצבים

מעקב וכתובת במהלך מעבר המודרניזציה הבא:

  • הצהרות סטטוס קובץ חסרות
  • סגור רק בנתיבי יציאה רגילים (מערכת ההפעלה מטפלת בזה, אבל זה נוהג גרוע)
  • פגמים בין-פרוצדוריים שבהם התיקון דורש תיאום שינויים בין תוכניות מרובות

איך SMART TS XL מנתח את מצב קובץ ה-COBOL

SMART TS XL"S ניתוח קוד סטטי בונה מודל זרימת בקרה של כל תוכנית COBOL בסביבה, מרחיב איברי COPY, עוקב אחר שרשראות PERFORM, עוקב אחר קצוות GO TO ומפיץ את מצב הקובץ דרך כל ענף של כל תנאי. זה לא סריקת התאמת תבניות; זהו מודל מבני של מה שהתוכנית עושה בפועל בכל נקודה נגישה בביצועה.

יכולת מיפוי התלות של היישומים מרחיבה זאת למימד הבין-פרוצדורלי: כאשר תוכנית COBOL קוראת לתת-תוכנית שמבצעת פעולות קבצים, מפת התלות מייצגת את הקשר הזה, ומאפשרת ניתוח שחוצה גבולות יחידות קומפילציה. פגמי OPEN כפולים המשתרעים על פני תוכנית ראשית ותת-תוכנית שנקראה גלויים במודל המבני באופן שבו הם אינם גלויים בשום ניתוח תוך-תוכניתי.

יכולת החיפוש הארגוני הופכת את התוצאות לפעולה בקנה מידה גדול: מצאו כל תוכנית בתיק העבודות שפותחת מערך נתונים ספציפי, כל חבר COPY המכיל משפט CLOSE, כל תוכנית שיש לה יעד PERFORM המכיל OPEN, על פני מיליוני שורות COBOL תוך שניות. עבור צוות מודרניזציה שמתכונן להעביר עומס עבודה של אצווה לענן, יכולת חיפוש זו הופכת ביקורת ידנית בת שבועות לשאילתה ממוקדת.

יכולת ההרחבה של JCL מוסיפה את ההקשר התפעולי: אילו שלבי משימת JCL מפעילים כל תוכנית, לאילו מערכי נתונים כל משפט DD מפנה, וכיצד טיפול הקבצים בקוד COBOL מתחבר למערכי הנתונים הפיזיים המוגדרים ב-JCL. פגם CLOSE בקובץ ש-JCL מגדיר כמערך נתונים קריטי הוא בעל עדיפות גבוהה יותר מאותו פגם בקובץ עבודה זמני, ותעדוף זה דורש הכרת ההקשר JCL של כל תוכנית COBOL.


הלקח הרחב יותר: מצב קובץ הוא רק מימד אחד

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

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

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