זוהי הפקודה rxgen שניתן להפעיל בספק האירוח החינמי של OnWorks באמצעות אחת מתחנות העבודה המקוונות המרובות שלנו, כגון Ubuntu Online, Fedora Online, אמולטור מקוון של Windows או אמולטור מקוון של MAC OS
תָכְנִית:
שֵׁם
rxgen - מחולל בדל עבור חבילת הקריאה להליך מרחוק Rx
תַקצִיר
rxgen [-h | -c | -C | -S | -r] [-dkpR]
[-I dir] [-P קידומת] [-o אוסף] [בקובץ]
rxgen -s להעביר [-o אוסף] [בקובץ]
rxgen -l [-o אוסף] [בקובץ]
rxgen -m [-o אוסף] [בקובץ]
תיאור
rxgen הוא כלי שיוצר קוד C ליישום פרוטוקול Rx RPC; זה לוקח כקלט
תיאור של ממשק אפליקציה דומה ל-C ומייצר מספר שרתים
ו/או שגרות בדל לקוח לקישור עם תוכניות מבוססות RPC. בלמים אלו מאפשרים
תוכניות להפעיל נהלים מרוחקים באמצעות קריאות פרוצדורות מקומיות. rxgen הוא הרחבה
של סאן rpcgen (גרסה 3.9) ושומר על מלא rpcgen פונקציונליות (לפחות נכון לעכשיו
גִרְסָה). בבקשה התייחס ל rpcgen(1) לפרטים נוספים על הדגלים הספציפיים של ה-RPC של השמש, וכן
למדריך התכנות RPC לגבי שפת RPC יחד עם דוגמאות שימושיות.
אפשרויות
rxgen פועל במספר מצבים שונים. ניתן להפיק את קבצי הפלט שנוצרו
בנפרד (באמצעות אחד מ -h, -c, -C, או -S) או ביחד. כל קבצי הפלט הם
נוצר כאשר נעשה שימוש ברירת המחדל (כלומר, ללא אפשרויות), או שהפלט מוגבל ל-
בדלי שרת (-C ו -S) כאשר -r נעשה שימוש בדגל. להלן מתארים את סוגי
קבצי פלט שנוצרו (למען הפשטות, שם הקובץ מתייחס לשם קובץ הפלט הראשי):
-h צור הגדרות נתוני C (קובץ כותרת) מהגדרות RPCL סטנדרטיות (ברירת מחדל
סיומת: שם הקובץ.h).
-c הרכיב את שגרות ה-XDR הנדרשות להסדרת הפרוטוקול המתואר על ידי RPCL.
צור שגרות XDR עבור כל ההצהרות (סיומת ברירת המחדל: שם הקובץ.xdr.c).
-C צור את כל שגרות הסטאב בצד הלקוח (סיומת ברירת המחדל: שם הקובץ.cs.c).
קריאה לשגרה בקובץ זה תגרום לארוזים ולשלוח דרך
Rx (או R).
-S צור את כל שגרות ה-Stub בצד השרת (סיומת ברירת המחדל: שם הקובץ.ss.c).
טיעונים פורקים, ושגרת השרת המתאימה נקראת.
-r צור את שני קובצי ההרחבות המוגדרים כברירת מחדל המיוצרים על ידי -C ו -S אפשרויות.
ניתן להשתמש באפשרויות הבאות על כל שילוב של rxgen שיחות:
-R צור קוד עבור פרוטוקול \R הישן יותר, בניגוד ל-Rx, שהוא ברירת המחדל.
-k יש לציין כאשר הקוד שנוצר מיועד לשמש את הליבה;
מיוחד "כולל" ופרטים נוספים מופקים כאשר פלט היעד הוא עבור
גַרעִין.
-p דגל שילוב חבילות: כאשר מספר חבילות כלולות בתוך חבילה אחת
קובץ המפרט, שגרת ביצוע בקשות בודדת תשמש עבור כולן בתור א
התוצאה של הדגל הזה. ברירת המחדל היא ליצור בדלי בקשת ביצוע בודדים עבור
כל חבילה.
-I dir
בדומה ל -I דגל במהדר C (cc). דגל זה מועבר לקדם-
מעבד (cpp) כך שהספרייה הזו dir הוא מחפש לפני רשימת החיפוש הרגילה
#include קבצים. כצפוי, מרובה -I ניתן להשתמש בדגלים בו זמנית.
-P קידומת
השמיים קידומת מחרוזת הבאה למתג זה מוצמדת לכל קבצי הפלט שנוצרו;
שימושי כאשר ריצות מרובות רוצות לייצר גרסאות שונות של אותו ממשק
(נניח, גרסאות ליבה ולא גרסאות ליבה).
-d מצב איתור באגים; צריך רק מתי rxgen יש לנפות באגים (נגיד, via dbx).
-o אוסף
ציין את השם של קובץ הפלט. אם לא צוין, הפלט הסטנדרטי הוא
בשימוש (-c, -h, -C, ו -S מצבים בלבד). שים לב שאם קובץ פלט מצוין ב-a
אפשרות קובץ ריבוי פלט (כגון ברירת המחדל, או עם אפשרות -r), אז ה אוסף
מחליף את השם שנוצר כברירת מחדל (המבוסס על התצורה הראשית של התצורה
שם קובץ).
השמיים -s, -l, ו -m אפשרויות קיימות רק עבור rpcgen תמיכה. לִרְאוֹת rpcgen(1) עבור
מידע על השימוש בהם.
rxgen תחביר סיכום
קובץ מפרט:
|
|
|
|
|
:
"חֲבִילָה"
:
"תחילית"
:
"startingopcode"
:
"תחילית מפוצלת" ";"
:
"IN =" "|"
"OUT =" "|"
:
["פרוק"] [ ] [ ]
["פיצול" | "רַב"]
["=" ] ";"
:
"(" ")"
:
["<" ">" | "[" "]"] | ריק
:
"," | ריק
:
"IN" | "OUT" | "INOUT" | ריק
:
| ריק
:
:
:
:
:
:
:
:
:
:
:
תחביר שפת ה-RPCL של Sun (ראה rpcgen(1))
rxgen פקודות
תגובות ו עיבוד מוקדם
ממשק הקלט עשוי להכיל הנחיות קדם-מעבד המועברות דרך ה-C
מעבד קדם (כלומר "cpp"). מכיוון שהמעבד המקדים פועל על כל קבצי הקלט לפני שהם
למעשה מתפרש על ידי rxgen, כל cpp הנחיות (#include, #ifdefs, #defines וכו') הן
חוקי ומתקבל בברכה בתוך rxgen קובץ קלט. כמובן, אף אחד מהקדם-מעבד האלה
הנחיות ייכללו בכל אחד מהקבצים שנוצרו. כדי להקל על הבחנות
בין הסוגים השונים של קבצי פלט, rxgen מגדיר מיוחד מסוים cpp סמלים עבור
שימוש על ידי ה rxgen מְתַכנֵת. אלה הם RPC_HDR (מוגדרים בעת הידור לכותרת,
שם הקובץ.h, קבצים), RPC_XDR (מוגדר בעת קומפילציה לתוך xdr, שם הקובץ.xdr.c, קבצים),
RPC_CLIENT (מוגדר בעת קומפילציה לתוך קבצי לקוח, שם הקובץ.cs.c, קבצים), ו
RPC_SERVER (מוגדר בעת קומפילציה לתוך קטעי שרת, שם הקובץ.ss.c, קבצים).
בנוסף, rxgen עושה עיבוד מוקדם משל עצמו. כל שורה שמתחילה ב-% היא
הועבר ישירות לקובץ הפלט, ללא פירוש על ידי rxgen. להמוני יותר כבדים
השלכת קוד לא מפורש, מומלץ לכלול את כל הקוד הזה ב-an
קובץ "#include" והעבירו אותו לפניו "%". ממשק הקלט עשוי להכיל גם כל
הערות בסגנון C שמתעלמים מהן, כמובן. הפרשנות היא מבוססת אסימונים, לפיכך
אין צורך בכיוון קו מיוחד של הצהרות נפרדות. rxgen גם מספק
סט עשיר ומועיל למדי של דוחות שגיאות, המזהים אותם לפי מיקום קו מדויק ו
סוג שגיאה. גַם, rxgen ייצור אוטומטית שורות #include עבור include רגיל
קבצים, כגון rx/xdr.h ו rx/rx.h, יחד עם קובץ הכותרת שנוצר מזה
מִמְשָׁק.
קידומת בדל נהלים
השמיים חבילה הצהרה מספרת rxgen שם חבילת הממשק. הוא משמש עבור
הקדמת שמות של כל שגרות הסטאב שנוצרו והליך הבקשה לביצוע.
לדוגמה:
חבילה AFS_
גורם להליך ביצוע הבקשה לקבל את השם AFS_ExecuteRequest (אזהרה: בגרסה הישנה יותר
גרסה "_" נוסף צורפה אחרי שם החבילה לשם ExecuteRequest;
לכן ודא שאין לך שגרת ממשק ExecuteRequest) ו-Stub נתון
שגרה, נניח אחזור, שתקרא למעשה AFS_Fetch. הצהרות חבילות מרובות (נוכחי
גודל מקסימלי הוא 10) לכל תצורה מותרים והם שימושיים כאשר מספר קבוצות של
ממשקים מיושמים (ראה את הדוגמה בסוף). שימו לב שבמקרים כאלה, שימוש ב
מה היא -p הדגל מביא ליצירת הליך ExecuteRequest אחד בלבד אשר
מזהה את הממשקים המרובים ושהשם שלהם מופיע בחבילה הראשונה
הַצהָרָה. במקרה ברירת המחדל, יווצרו נהלי ExecuteRequest עצמאיים עבור
כל קבוצה ארוזה של שיחות נוהל מרחוק.
השמיים קידומת ההצהרה מספקת שם לראשון לכל הקריאות לשמות פרוצדורות מרוחקות בהן
שגרת ה-ExecuteRequest stub. זה שימושי כאשר השרת מבצע קריאות RPC לאחרים
שרתים (נניח, למטרות ניפוי באגים). לדוגמה:
קידומת S
גורם לכך שהשם "S" יוצב לפני השם של כל השגרות שנקראות מהשרת
בדלונים. לאחר מכן, השרת יכול לקרוא לשם המקורי ולקבל את תווי הלקוח.
rxgen הליך הכרזה
השמיים proc הצהרה היא הנפוצה (והמשמעותית) ביותר ב- rxgen מִמְשָׁק. התחביר שלו
התיאור הוא:
[פרוק] [ ] [ ] ( , ..., )
[פיצול | רב] [= ] ;
שם:
· "proc" היא קידומת אופציונלית של הצהרת הפרוצדורה. זה רק פריט סגנוני
ולא תוחם נוהל נדרש.
· הוא שם ההליך. שימו לב שאפילו שם ההליך הוא
אופציונאלי. זה הגיוני רק כאשר השם של ההליך הנתון זהה לזה
שמו של האחרון חבילה הצהרה (כלומר, "חבילת RCallBack" וההצהרה של
הליך "RCallBack").
· , אם קיים, גורם להליך ExecuteRequest לקרוא לסטאב הזה במקום זאת
של הסטאב שנוצר אוטומטית כאשר שיחה עם קוד זה מפוענחת.
· הוא קבוע או סמל שהוא ה-opcode עבור הליך זה. אפשר להשתמש
תכונות הפרה-מעבד (כלומר, #define), ה- const תכונה בשפת RPC, או הישן
קבועים טובים כאופקודים. נעשה הערכה/עיבוד נוספת של קודים.
במיוחד, מתבצעות בדיקות לאיתור קודים כפולים ולא קיימים, יחד עם
בודק "חורים" (כלומר, פערים בקודים עוקבים) ברצפי ה-opcode. ל
לדוגמה, אנו משתמשים בעובדה שכאשר קיימים "חורים" בקודים, ה-ExecuteRequest
ההליך משתמש ב מקרה הצהרה במקום המהירה יותר (והקטנה יותר, מבחינת קוד) באינדקס
שיטת מערך.
אז, rxgen מגדיר (כלומר, מוסיף לקובץ הכותרת) שלוש פקודות מאקרו יקרות ערך עבור כל אחת מהן
קבוצת חבילות: LOWEST_OPCODE, HIGHEST_OPCODE, ו
NUMBER_OPCODES. אלה עשויים להיות שימושיים עבור rxgen מְתַכנֵת. גַם,
שימו לב כי ה opcode הצהרה היא תכונה אופציונלית, וניתן להשמיט אותה. בכזה
במקרים, מספרי אופקוד אוטומטיים נוצרים ברצף, החל מ-0.
אפשר לשנות את מספר האופקוד הראשוני באמצעות ה startopcode (בהיעדר א
שם טוב יותר) rxgen פקודה. התחביר שלו הוא:
startopcode
איפה חייב להיות הגיוני! שימו לב שאי אפשר לערבב נהלים, חלקם עם
opcodes וחלקם ללא, ולא לאפשר opcodes לאחר המפרט של
startopcode הצהרה. rxgen יתלונן בכל המקרים הללו.
· טענה הכניסה מייצגת פרמטר נתון של ההליך. התחביר שלו הוא:
[IN | INOUT | OUT | ]
[ |<>|[מקסימום]|[]]
אם הטיפוס הוא טיפוס עקיף (כלומר, אחריו *), ההנחה היא שהמצביע
יש לעקוב אחר רמה אחת ולהעביר את הנתונים שעליהם הצביעו. זה אמור
בדרך כלל משמש עבור כל המבנים/מערכים ופרמטרים החוצה. חריג בולט
הוא כאשר ניתן גודל מרבי של מערך/מבנה מפורש; מכיוון שאין מערך מצביע
הצהרות מותרות יש להשתמש ב-typedefs כדי להשיג את האפקט הדומה. ה
פרמטרים יכולים להיות פרמטרי קלט (שלפניהם IN), פרמטרי פלט (שלפניהם
OUT), או פרמטרי קלט/פלט (שלפניהם INOUT). אם לא צוין, אז ה
נעשה שימוש בכיוון של הפרמטר הקודם בהליך. (הערה: הראשון
יש להקדים את הפרמטר על ידי הפרימיטיבי הכיווני!)
· "פיצול" הוא פריצה להתמודדות עם שגרות בדל שעושות דברים כמו העברות קבצים או כל דבר אחר
פעולה אחרת שצריכה להחליף מידע (למשל, אורך קובץ) לפני ה-
call מחזירה את פרמטרי הפלט שלו. בגלל לחיצת היד המסוימת כלומר
המעורבים בעת העברת קבצים מרחוק, כרגע אנו מפרקים את כל השיחות הללו לשניים
שגרות בדל בצד הלקוח. הראשון (עם קידומת ברירת המחדל של "התחלה") משמש ל
להעביר את כל הפרמטרים IN ו-INOUT לצד השרת. השני (עם ברירת המחדל
הקידומת של "End") משמשת להחזרת הפרמטרים INOUT ו-OUT מהשרת.
בין שתי השיחות, המשתמש אמור לבצע את הקריאות המתאימות לקובץ
לְהַעֲבִיר. לדוגמה, הצהרת הפרוצדורה הבאה בחבילה AFS_
Fetch (IN a, b,INOUT c, OUT d) פיצול = FETCHOPCODE;
ייצור בערך את שתי שגרות הסטאב העצמאיות של הלקוח:
BeginAFS_Fetch (IN a, b, c)
ו
EndAFS_Fetch(OUT c,d)
השמיים תחילית מפוצלת המשפט משמש לשינוי שמות קידומת ברירת המחדל המשמשים את השניים
שגרות שנוצרו על ידי בדל בצד הלקוח בעת התמודדות עם הליך הקשור להעברת קבצים
שיחות. לדוגמה:
splitprefix IN=לפני_ OUT=אחרי_
יגרום למתן שמות של שני קבצי הלקוח לשגרה הקשורה להעברת קבצים, למשל
לְהָבִיא(), להיות Before_AFS_Fetch() ו After_AFS_Fetch(), בהתאמה.
· אפשרות ה"רב" כמעט זהה לתכונת ה"פיצול" שתוארה לעיל. היחיד
הבדל משמעותי גלוי הוא שיחד עם שני בדלי הלקוח, הסטנדרט
נוצר גם בדל לקוח. מכיוון שהכוונה היא לטפל בשיחות מולטי-Rx, אנחנו
צריך את כל הפרוצדורה הסטנדרטית במקרים שבהם אין קריאת ריבוי Rx של
ההליך מתבצע. תופעת לוואי של אפשרות ה"רב" היא יצירת א
מאקרו מיוחד (כלומר, "multi_ "אשר מחזיר כטיעונים את ה"התחלה"
ו-"End" stubs בקובץ הפלט של הכותרת. מאקרו זה משמש ישירות על ידי קוד Rx
כאשר מבוצעת קריאת ריבוי Rx של הליך זה.
אובסולייט rxgen מאפיינים
למרות שפקודות ה-rxgen הבאות עדיין בתוקף, הן יוסרו בקרוב מאז
יש חלופות טובות יותר. אל תשתמש בהם!
השמיים מיוחד statement הוא פריצה זמנית המשמשת לטיפול בחוסר יעילות מסוימות של
שגרות xdr סטנדרטיות לטיפול בכמה הצהרות מותאמות אישית למשתמש. בפרט, זה
חל על מצביע מחרוזת שצוין כחלק מהצהרה. לדוגמה,
מבנה מיוחד BBS SeqBody;
אומר rxgen שהערך "SeqBody" בשגרת BBS xdr המוגדרת על ידי המשתמש הוא מחרוזת (שים לב
שיותר ממחרוזת אחת יכולה להיות "מיוחדת" לכל מבנה -- מרובים מופרדים על ידי
פסיקים); לפיכך הוא יקצה ותבטל את ההקצאה של שטח כראוי בשרת שנוצר
stubs המכילים מבנה זה כפרמטר IN או INOUT.
אלטרנטיבה טובה יותר ל מיוחד האם ה אישית הצהרה, שהיא פשוט ה
אסימון "מותאם אישית" ואחריו ההכרזה הרגילה של מבנה המבוסס על RPCL
כללים. במקרה זה, ההצהרה תיכלל בקובץ הכותרות שנוצר (-h
option) אך לא תיווצר שגרת xdr עבור המבנה הזה -- המשתמש יספק
זֶה. כל כניסות המצביעים במבנה זה ייזכרו כך כאשר המבנה יהיה
משמש כ-IN או כ-INOUT בסטאב השרת, לא תתרחש דליפות ליבה. לדוגמה,
לשקול
מבנה מותאם אישית CBS {
ארוך Seqlen;
char *SeqBody;
}
שגרת "xdr_CBS" תסופק על ידי המשתמש כאשר במהלך ה-DECODE xdr opcode,
מוקצה מקום מתאים למחרוזת "SeqBody". באופן דומה, החלל הזה מתפנה
במהלך קוד ה-xdr החינמי.
הערה: "מפרט פרמטרי מערך" בסגנון ישן אינם נתמכים יותר.
דוגמאות
במקרה שיש דרישות מסוימות שאינן זמינות בשפת ה-RPC הנוכחית, אפשר
התאם אישית כמה שגרות XDR על ידי השארת סוגי נתונים אלה לא מוגדרים. לכל סוג נתונים
שאינו מוגדר, ההנחה היא שקיימת שגרה עם השם "xdr_".
אליו. סט נבחר של rxgen תכונות מוצגות להלן, אך למידע מקיף יותר
אחד (איגודים, דוגמאות מורכבות וכו') אנא עיין ב rpcgen תכנות להדריך ו
חיצוני נתונים יִצוּג: שמש טכני הערות.
טיפוסיות
הצהרת RPC typedef זהה ל-C typedef (כלומר "typedef ").
כברירת מחדל, רוב הצהרות המשתמש (כלומר מבנים, איגודים וכו') הן אוטומטיות
מודפס על ידי rxgen. מכיוון שהוא הופך את הניתוח לפשוט יותר, השימוש בו מומלץ על ידי rxgen
תסריטים.
מחרוזות
מוסכמות המחרוזות "char *" של C היא די מעורפלת, מכיוון שהיא נועדה בדרך כלל
מתכוון למחרוזת תווים עם סיומת אפס, אבל זה יכול גם לייצג מצביע ל-a
תו בודד, מצביע למערך של תווים וכו'. בשפת RPC, ערך null-
מחרוזת שהסתיימה נקראת באופן חד משמעי "מחרוזת". דוגמאות,
מחרוזת bigname<>;
שם מחרוזת ;
typedef מחרוזת volname ;
שים לב שהגודל המרבי של המחרוזת יכול להיות שרירותי (כמו "שם גדול" למעלה) או,
רצוי, או מצוין בסוגריים של זווית (כלומר "שם" ו-"volname" למעלה). ב
תרגול, יש להשתמש תמיד רק במחרוזות מוגבלות בממשקים. פרוק שיחות לדוגמה
השימוש בהצהרות לעיל יהיה:
GetEntryByName (שם ווליום,
OUT struct vldbentry *כניסה) = VL_GETENTRYBYNAME;
או, כמובן,
GetEntryByName (IN מחרוזת volname ,
OUT struct vldbentry *כניסה) = VL_GETENTRYBYNAME;
חשוב מאוד שהמשתמש יבין מתי צריכים להיות פרמטרי המחרוזת
מוקצה ו/או משוחרר על ידי תוכניות הלקוח ו/או השרת שלו. ניתוח קצר על
טיפול בפרמטרים של מחרוזת מופיע בהמשך (שים לב ששיטה דומה משמשת לטיפול ב
מערכי אורך משתנה כפי שיוצגו בהמשך):
· בצד הלקוח: פרמטרי מחרוזת IN ו-INOUT הם באחריות המתכנת
ויש להקצות (סטטי או דרך malloc) לפני קריאת ה-rpc ולשחרר אותו (אם
נעשה שימוש ב-malloc) לאחר החזרת ה-rpc בתוכנת הלקוח של המשתמש; כמובן, עבור
INOUT פרמטרים, המחרוזת המוחזרת לא יכולה להיות גדולה יותר ממחרוזת הקלט המשובחת.
פרמטרי מחרוזת OUT מוחלפים באופן אוטומטי (בהתבסס על אורך הקובץ המוחזר
מחרוזת ולא ה-maxsize) לפי ה rxgen תלושי לקוח (ב שם הקובץ.cs.c) וחייב להיות
משוחרר על ידי תוכנית הלקוח; יש להודות, זה יכול להיות קצת מבלבל מאז המשתמש
צריך לשחרר משהו שהוא/היא לא הקצה.}
· בצד השרת: פרמטרי מחרוזת IN ו-INOUT מוחלפים באופן אוטומטי (בהתבסס על
בגודל של מחרוזות נכנסות) על ידי זרעי שרת rxgen (ב שם הקובץ.ss.c) לפניהם
מועברים לנוהל השרת של המשתמש; שהחלל מתפנה אוטומטית ממש לפני
בדל השרת של rxgen חוזר; לכן המשתמש לא צריך לעשות שום דבר מיוחד עבור IN
ופרמטרי מחרוזת INOUT.
פרמטרי מחרוזת OUT חייבים להיות מקובעים על ידי נוהל השרת של המשתמש (כלומר מצביע null
מועבר אליו על ידי שרת rxgen stub) והוא משוחרר אוטומטית בסוף
מה היא rxgen בדל שרת. כמו בצד הלקוח, הפרמטרים של OUT הם במידת מה
לא שגרתי (כלומר, שגרת השרת חייבת למלא מחרוזת מבלי לשחרר אותה בעצמה;
זה נעשה על ידי rxgen בדל שרת).
שימו לב שלפרמטרי מחרוזת INOUT ו-OUT, הן בצד הלקוח והן בצד השרת שלהם
הארגומנטים חייבים להיות char של מצביעים (כלומר char **).
מצביעים
הצהרות מצביע ב-RPC הן גם בדיוק כפי שהן ב-C (כלומר "struct
single_vldbentry *vldblist;"). כמובן, אי אפשר לשלוח מצביעים דרך הרשת, אבל
אפשר להשתמש במצביעי XDR לשליחת סוגי נתונים רקורסיביים כגון רשימות ועצים (an
דוגמה לרשימה מקושרת תוצג בקרוב).
מערכים
מערכים קבועים הם בדיוק כמו הצהרות סטנדרטיות של מערך C (כלומר "struct UpdateEntry
ערכים[20]") ללא בעיות של תופעות לוואי ב rxgen. מאז יש למערכים באורך משתנה
אין תחביר מפורש ב-C, סוגריים זווית משמשים עבורו והצהרות המערך הן
הידור למעשה לתוך "מבנה". לדוגמה, הצהרות כגון:
const MAXBULKSIZE = 10000;
const MAXENTRIES = 100;
בתפזורת אטומה ; /* לכל היותר 10000 פריטים */
int hosts<>; /* כל מספר פריטים */
typedef vldbentry blkentries<100>; /* עדיף מערך decl */
מורכבים למבנים הבאים:
struct {
u_int bulk_len; /* מספר פריטים */
char *bulk_val; /* מצביע למערך */
} בתפזורת;
עבור מערך ה-"bulk", ובדומה למערך "blkentries<100>",
struct {
u_int blkentries_len; /* מספר פריטים במערך */
vldbentry *blkentries_val; /* מצביע למערך */
} blkentries;
לכן המשתמש צריך להיות מודע לערכי המבנה שנוצרו "באופן קסם" כגון
מספר הפריטים במערך ( _len) והמצביע למערך
( _val) מכיוון שחלק מהערכים יצטרכו להיות מילוי מה-
תוכניות לקוח/שרת. תהליך לדוגמה יהיה:
typedef vldbentry blkentries ;
proc GetBlk (OUT blkentries *vlentries) = VL_GETBLK;
או, באופן ישיר יותר,
GetBlk(OUT vldbentry vlentries ) = VL_GETBLK;
שימו לב שלמרות שהשיטה העדכנית עדיפה מכיוון שלא חייבים להשתמש לראשונה
את הצהרת typedef (ואם להודות, מתכנתים מעדיפים להימנע מ-typedefs), צריך
תביני את זה rxgen האם הרחבת המבנה ויצירת xdr באופן מרומז; לָכֵן
המשתמש צריך להיות מודע לשדות "vldbentries_val" ו-"vldbentries_len" כמו קודם
(ראה דוגמאות הבאות).
מערך דוגמה I (הכי פחות רצוי)
הצהרת נוהל בתצורת הממשק:
proc ListAttributes (IN vldblistbyattributes *attributes,
INOUT blkentries *vldbentries) = VL_LISTATTRIBUTES;
קוד לקוח לדוגמה:
ערכים של blkentries, *pnt;
entries.blkentries_len = 10; /* מקסימום # ערכים שהוחזרו */
entries.blkentries_val = (vldbentry *)malloc(LEN);
/* זה חייב להיות מוגדר */
code = VL_ListAttributes(&attributes, &entries);
if (!code) {
pnt = entries.blkentries_val;
עבור (i=0; i < entries.blkentries_len; i++, pnt++)
display_vldbentry(pnt);
/* ודא שאתה מפנה את השטח המוקצה */
free((char *)entries.blkentries_val);
}
קוד SERVER לדוגמה:
VL_ListAttributes(מאפיינים, ערכים)
{
vldbentry *singleentry = entries->blkentries_val;
entries->blkentries_len = 0;
while (copy_to_vldbentry(&vlentry, singleentry))
singleentry++, vldbentries->entries_len++;
}
למרות ששיטה זו עבור מערכים בגדלים משתנה עובדת מצוין, יש כמה חסרונות עיקריים.
יש להכריז על פרמטר המערך (כלומר vldbentries למעלה) כ-INOUT מכיוון שאנו צריכים
להעביר את האורך המרבי של המערך המוחזר הצפוי; חשוב מכך, גדול (תלוי
הערך של "_len") גוש קוד זבל יועבר לשרת כתוצאה מכך
של תופעת הלוואי IN(out) של המערך. זוהי שיטה קלה ונוחה אם
ניתן לחזות את גודל המערך המוחזר מההתחלה ומתי הגודל די גבוה. זֶה
השיטה כלולה כדוגמה לשימוש שגוי (ושימוש לרעה) ב rxgen ולא צריך להיות
מְשׁוּמָשׁ.
מערך דוגמה II (רצוי שיטה)
הצהרת נוהל בתצורת הממשק (באמצעות דוגמה I לעיל):
proc ListAttributes (IN vldblistbyattributes *attributes,
OUT blkentries *vldbentries) = VL_LISTATTRIBUTES;
קוד לקוח לדוגמה:
ערכים של blkentries, *pnt;
code = VL_ListAttributes(&attributes, &entries);
if (!code) {
pnt = entries.blkentries_val;
עבור (i=0; i < entries.blkentries_len; i++, pnt++)
display_vldbentry(pnt);
/* ודא שאתה מפנה את השטח המוקצה (על ידי rxgen) */
free((char *)entries.blkentries_val);
}
קוד SERVER לדוגמה:
VL_ListAttributes(מאפיינים, ערכים)
{
vldbentry *סינגלנטרי;
entries->blkentries_len = 0;
singleentry = entries->blkentries_val
= (vldbentry *)malloc(MAXENTRIES * sizeof(vldbentry));
while (copy_to_vldbentry(&vlentry, singleentry))
singleentry++, vldbentries->entries_len++;
}
זוהי הדרך הטובה ביותר (והפשוטה ביותר) להשתמש במערכים בגודל משתנה כפרמטר פלט.
באחריותו של הבדל בצד השרת malloc () המרחב המתאים שהוא
משוחרר אוטומטית על ידי rxgen בָּדָל; צד הלקוח צריך לפנות את השטח שהוקצה על ידי
מה היא rxgen-בדל קורא.
מערך דוגמה ג (צָמוּד רשימות)
בהתחשב ב-3 ההצהרות הבאות (יכול היה להחיל כמה אופטימיזציות) ב-
קובץ תצורה:
typedef struct single_vldbentry *vldblist;
struct single_vldbentry {
vldbentry vlentry;
vldblist next_vldb;
};
struct vldb_list {
צומת vldblist;
};
והצהרת נוהל rxgen:
LinkedList (IN vldblistbyattributes *attributes,
OUT vldb_list *linkedentries) = VL_LINKEDLIST;
קוד לקוח לדוגמה:
vldb_list linkedvldbs;
vldblist vllist, vllist1;
bzero(&linkedvldbs, sizeof(vldb_list));
code = VL_LinkedList(&attributes, &entries, &linkedvldbs);
if (!code) {
printf("קיבלנו %d ערכים vldb\n", nentries);
for (vllist = linkedvldbs.node; vllist; vllist = vllist1) {
vllist1 = vllist->next_vldb;
display_entry(&vllist->vlentry);
free((char *)vllist);
}
}
קוד SERVER לדוגמה:
VL_LinkedList(rxcall, attributes, nentries, linkedvldbs);
{
vldblist vllist, *vllistptr = &linkedvldbs->node;
בזמן (...) {
vllist = *vllistptr
= (single_vldbentry *)malloc (sizeof (single_vldbentry));
copy_to_vldbentry(&tentry, &vllist->vlentry);
ערכים++;
vllistptr = &vllist->next_vldb;
};
*vllistptr = NULL;
}
שימוש ברשימה מקושרת מציע יתרונות רבים: שום דבר לא מועבר לשרת (הפרמטר
הוא OUT), אין תקורה נוספת מעורבת, והמתקשר לא חייב במפורש
להתכונן לגודל החזר שרירותי. החיסרון הוא שלמתקשר יש את
אחריות של malloc () (בשרת) ובחינם (בלקוח) של כל כניסה (ל
למנוע דליפות ליבה לא רצויות). חיסרון נוסף הוא שמכיוון שמדובר בשיחה רקורסיבית, ה-C
מחסנית תגדל באופן ליניארי ביחס למספר הצמתים ברשימה (אז זה חכם לעשות
הגדל את מחסנית Rx LWP אם צפויות חזרה כמויות אדירות של נתונים -- גודל מחסנית ברירת המחדל
הוא 4K). היתרונות כאן צריכים לעלות על החסרונות.
חשוב לשים לב להערות של שלוש דוגמאות המערך לעיל
במיוחד כאשר הם מתייחסים למועד שבו המשתמש צריך להקצות/לפנות מקום עבור
מערכי אורך משתנה. המנגנון דומה מאוד לטיפול בחוטים ובכך אתה
ייתכן שיהיה צורך לעיין בסעיף המחרוזות שלמעלה; שים לב שהרשימות המקושרות מטופלות
קצת אחרת...
שונות דוגמאות
להלן גרסה מקוצרת של קובץ ממשק אקראי המציגה חלק מהדברים הנפוצים
במקרים.
/* הצהרת כל המבנים המשמשים את ממשק הסקריפט R.xg */
struct AFSFid {
כרך ארוך לא חתום;
Vnode ארוך לא חתום;
לא חתום ארוך ייחודי;
};
typedef long ViceDataType;
/* שימו לב ש-TEST יהיה שווה ערך ל-"HEADER" רק במהלך
עיבוד של הכותרת, *.h, קובץ */
#ifdef RPC_HDR
#define TEST "HEADER"
#else
#define TEST "REST"
#endif
/* זהו קובץ המפרט הסטנדרטי *.xg */
חבילה AFS_
splitprefix IN=BEFORE_ OUT=AFTER_;
בדיקת קידומת
proc Remove(IN struct AFSFid *Did, IN string volname<64>,
מבנה OUT AFSStatus *Status) = AFS_REMOVE;
DisconnectFS AUX_disconnectFS() = AFS_DISCONNECTFS;
proc GetVolumeInfo(מחרוזת IN Vid,
OUT struct VolumeInfo *Info) = AFS_GETVOLUMEINFO;
/* יכול להיות לך יותר מממשק לכל תצורה */
חבילה VOTE_
/* שימוש בתכונה "רב"; לפיכך ניתן לקרוא ל-VOTE_Beacon בתור an
שיחת מולטי-Rx או כשיחה רגילה */
Beacon (במצב ארוך, הצבעה ארוכה התחל,
net_version *version, net_tid *tid)
multi = VOTE_BEACON;
חבילה DISK_
/* שימוש בתכונת "פיצול" */
SendFile (קובץ ארוך IN, היסט ארוך,
long length, net_version *version)
פיצול = DISK_SENDFILE;
תְפוּקָה of an ממשי ממשק תצורה
נדגים חלק מהפלט בפועל שנוצר על ידי rxgen על ידי ביצוע מקוצר
תצורת הממשק בפועל.
תְצוּרָה פילה
תוכן קובץ תצורת הממשק (vldbint.xg):
חבילה VL_
#include "vl_opcodes.h" /* הקודים כלולים כאן */
%#include "vl_opcodes.h" /* ישירות למקומות אחרים */
/* מגבלות נוכחיות על פרמטרים המשפיעים על חבילות אחרות
(כלומר נפח) */
const MAXNAMELEN = 65;
const MAXNSERVERS = 8;
const MAXTYPES = 3;
/* ייצוג חיצוני (גלוי) של ערך vldb בודד */
struct vldbentry {
שם char[MAXNAMELEN];
long volumeType;
שרתים ארוכים;
long serverNumber[MAXNSERVERS];
מחיצת שרת ארוכה[MAXNSERVERS];
long serverFlags[MAXNSERVERS];
u_long volumeId[MAXTYPES];
דגלים ארוכים;
};
typedef struct single_vldbentry *vldblist;
struct single_vldbentry {
vldbentry VldbEntry;
vldblist next_vldb;
};
struct vldb_list {
צומת vldblist;
};
/* שיחות ממשק vldb */
CreateEntry (IN long Volid,
vldbentry *newentry) = VLCREATEENTRY;
GetEntryByName (שם נפח מחרוזת IN ,
OUT vldbentry *כניסה) = VLGETENTRYBYNAME;
GetNewVolumeId (בספירת חבילות ארוכה,
OUT long *newvolumid) = VLGETNEWVOLUMEID;
ReplaceEntry (IN long Volid,
סוג וול ארוך,
vldbentry *newentry,
long ReleaseType) multi = VLREPLACEENTRY;
ListAttributes (IN VldbListByAttributes *attributes,
OUT ארוך *כניסות,
OUT vldbentry bulkentries )
= VLLISTATTRIBUTES;
LinkedList (IN VldbListByAttributes *attributes,
OUT ארוך *כניסות,
OUT vldb_list *linkedentries) = VLLINKEDLIST;
נתרכז רק בקוד שנוצר Rx מאז הקוד שנוצר R (-R אוֹפְּצִיָה)
בקרוב יהיה מיושן. לתיאור מפורט על השיחות הקשורות ל-Rx בתוך
בדל שנוצר (כלומר, rx_NewCall(), rx_EndCall()), יחד עם פרטים על מה שקורה
בתוך שיחות מסוימות (כמו xdrrx_create()) אנא עיין בתיעוד Rx. הקלדה
"rxgen vldbint.xg" יביא ליצירת ארבעה קבצים: vldbint.h, vldbint.xdr.c,
vldbint.cs.c ו vldbint.ss.c. להלן מבט מקרוב על קבצים אלה.
כותרת פילה (vldbint.h)
/* קובץ שנוצר על ידי מכונה -- אל תערוך */
#include "vl_opcodes.h" /* ישירות למקומות אחרים */
#define MAXNAMELEN 65
#define MAXNSERVERS 8
#define MAXTYPES 3
struct vldbentry {
שם char[MAXNAMELEN];
long volumeType;
שרתים ארוכים;
long serverNumber[MAXNSERVERS];
מחיצת שרת ארוכה[MAXNSERVERS];
long serverFlags[MAXNSERVERS];
u_long volumeId[MAXTYPES];
דגלים ארוכים;
};
typedef struct vldbentry vldbentry;
bool_t xdr_vldbentry();
typedef struct single_vldbentry *vldblist;
bool_t xdr_vldblist();
struct single_vldbentry {
vldbentry VldbEntry;
vldblist next_vldb;
};
typedef struct single_vldbentry single_vldbentry;
bool_t xdr_single_vldbentry();
struct vldb_list {
צומת vldblist;
};
typedef struct vldb_list vldb_list;
bool_t xdr_vldb_list();
#לִכלוֹל
#define multi_VL_ReplaceEntry(Volid, voltype, newentry, ReleaseType) \
multi_Body(StartVL_ReplaceEntry(multi_call, Volid, voltype,
newentry, ReleaseType), EndVL_ReplaceEntry(ריבוי_שיחות))
typedef struct bulkentries {
u_int bulkentries_len;
vldbentry *bulkentries_val;
} נפחים;
bool_t xdr_bulkentries();
/* נתונים סטטיסטיים שימושיים הקשורים ל-Opcode עבור חבילה: VL_ */
#define VL_LOWEST_OPCODE 501
#define VL_HIGHEST_OPCODE 506
#define VL_NUMBER_OPCODES 6
שימו לב שכל המבנים מוגדרים אוטומטית וכל ה"קונסט" מומרים ל
"#define"s. מבני נתונים מסוימים, כגון נפחים, לקוחים מפרמטרים של נהלים
(מתוך ListAttributes proc). לפיכך, יש לזכור זאת בעת יצירת בולים
חתיכה עם rxgen (כלומר, באמצעות -c, -h, -C, או -S דגלים). כמו כן, אחד מהצדדים
ההשפעות של האפשרות "רב" (בפרוק "החלף כניסה") היא היצירה של
"multi_VL_ReplaceEntry" למעלה.
XDR שגרות ל מבנים (vldbint.xdr.c)
/* קובץ שנוצר על ידי מכונה -- אל תערוך */
#לִכלוֹל
#include "vldbint.h"
#include "vl_opcodes.h" /* ישירות למקומות אחרים */
bool_t
xdr_vldbentry(xdrs, objp)
XDR *xdrs;
vldbentry *objp;
{
if (!xdr_vector(xdrs, (char *)objp->name, MAXNAMELEN,
sizeof(char), xdr_char))
החזרה (FALSE);
if (!xdr_long(xdrs, &objp->volumeType))
החזרה (FALSE);
if (!xdr_long(xdrs, &objp->nServers))
החזרה (FALSE);
if (!xdr_vector(xdrs, (char *)objp->serverNumber, MAXNSERVERS,
sizeof(long), xdr_long))
החזרה (FALSE);
if (!xdr_vector(xdrs, (char *)objp->serverPartition,
MAXNSERVERS, sizeof(long), xdr_long))
החזרה (FALSE);
if (!xdr_vector(xdrs, (char *)objp->serverFlags, MAXNSERVERS,
sizeof(long), xdr_long))
החזרה (FALSE);
if (!xdr_vector(xdrs, (char *)objp->volumeId, MAXTYPES,
sizeof(u_long), xdr_u_long))
החזרה (FALSE);
if (!xdr_long(xdrs, &objp->flags))
החזרה (FALSE);
החזרה (TRUE);
}
bool_t
xdr_vldblist(xdrs, objp)
XDR *xdrs;
vldblist *objp;
{
if (!xdr_pointer(xdrs, (char **)objp,
sizeof(struct single_vldbentry),
xdr_single_vldbentry))
החזרה (FALSE);
החזרה (TRUE);
}
bool_t
xdr_single_vldbentry(xdrs, objp)
XDR *xdrs;
single_vldbentry *objp;
{
if (!xdr_vldbentry(xdrs, &objp->VldbEntry))
החזרה (FALSE);
if (!xdr_vldblist(xdrs, &objp->next_vldb))
החזרה (FALSE);
החזרה (TRUE);
}
bool_t
xdr_vldb_list(xdrs, objp)
XDR *xdrs;
vldb_list *objp;
{
if (!xdr_vldblist(xdrs, &objp->node))
החזרה (FALSE);
החזרה (TRUE);
}
bool_t
xdr_bulkentries(xdrs, objp)
XDR *xdrs;
נפחים *objp;
{
if (!xdr_array(xdrs, (char **)&objp->bulkentries_val,
(u_int *)&objp->bulkentries_len, MAXVLDBLEN,
sizeof(vldbentry), xdr_vldbentry))
החזרה (FALSE);
החזרה (TRUE);
}
שים לב כי xdr_bulkentries() נוצר באופן אוטומטי כתופעת לוואי של הליך
הצהרת פרמטר. לפיכך, אם נעשה שימוש בהצהרות פרמטרים זהות של מספר סוגים,
אז ייווצרו סטאבים xdr_* המוגדרים בכפל! הרגשנו שזו אלטרנטיבה טובה יותר
שיש את rxgen מתכנת עוסק בסוגים כגון bulkentries_1, bulkentries_2...
צד הלקוח בדל שגרות (vldbint.cs.c)
/* קובץ שנוצר על ידי מכונה -- אל תערוך */
#לִכלוֹל
#לִכלוֹל
#לִכלוֹל
#include "vldbint.h"
#include "vl_opcodes.h" /* ישירות למקומות אחרים */
int VL_CreateEntry(z_conn, Volid, newentry)
רשום struct rx_connection *z_conn;
ארוך Volid;
vldbentry * newentry;
{
struct rx_call *z_call = rx_NewCall(z_conn);
static int z_op = 501;
int z_result;
XDR z_xdrs;
xdrrx_create(&z_xdrs, z_call, XDR_ENCODE);
/* מרשל הטיעונים */
if ((!xdr_int(&z_xdrs, &z_op))
|| (!xdr_long(&z_xdrs, &Volid))
|| (!xdr_vldbentry(&z_xdrs, newentry))) {
z_result = RXGEN_CC_MARSHAL;
צריך להיכשל;
}
z_result = RXGEN_SUCCESS;
לְהִכָּשֵׁל:
return rx_EndCall(z_call, z_result);
}
int VL_GetEntryByName(z_conn, volumename, entry)
רשום struct rx_connection *z_conn;
char * שם נפח;
vldbentry * כניסה;
{
struct rx_call *z_call = rx_NewCall(z_conn);
static int z_op = 504;
int z_result;
XDR z_xdrs;
xdrrx_create(&z_xdrs, z_call, XDR_ENCODE);
/* מרשל הטיעונים */
if ((!xdr_int(&z_xdrs, &z_op))
|| (!xdr_string(&z_xdrs, &volumename, 65))) {
z_result = RXGEN_CC_MARSHAL;
צריך להיכשל;
}
/* בטל מרשל את טיעוני התשובה */
z_xdrs.x_op = XDR_DECODE;
if ((!xdr_vldbentry(&z_xdrs, entry))) {
z_result = RXGEN_CC_UNMARSHAL;
צריך להיכשל;
}
z_result = RXGEN_SUCCESS;
לְהִכָּשֵׁל:
return rx_EndCall(z_call, z_result);
}
int VL_GetNewVolumeId(z_conn, bumpcount, newvolumid)
רשום struct rx_connection *z_conn;
ספירת מהמורות ארוכה;
ארוך * newvolumid;
{
struct rx_call *z_call = rx_NewCall(z_conn);
static int z_op = 505;
int z_result;
XDR z_xdrs;
xdrrx_create(&z_xdrs, z_call, XDR_ENCODE);
/* מרשל הטיעונים */
if ((!xdr_int(&z_xdrs, &z_op))
|| (!xdr_long(&z_xdrs, &bumpcount))) {
z_result = RXGEN_CC_MARSHAL;
צריך להיכשל;
}
/* בטל מרשל את טיעוני התשובה */
z_xdrs.x_op = XDR_DECODE;
if ((!xdr_long(&z_xdrs, newvolumid))) {
z_result = RXGEN_CC_UNMARSHAL;
צריך להיכשל;
}
z_result = RXGEN_SUCCESS;
לְהִכָּשֵׁל:
return rx_EndCall(z_call, z_result);
}
int VL_ReplaceEntry(z_conn, Volid, voltype, newentry, ReleaseType)
רשום struct rx_connection *z_conn;
long Volid, voltype, ReleaseType;
vldbentry * newentry;
{
struct rx_call *z_call = rx_NewCall(z_conn);
static int z_op = 506;
int z_result;
XDR z_xdrs;
xdrrx_create(&z_xdrs, z_call, XDR_ENCODE);
/* מרשל הטיעונים */
if ((!xdr_int(&z_xdrs, &z_op))
|| (!xdr_long(&z_xdrs, &Volid))
|| (!xdr_long(&z_xdrs, &voltype))
|| (!xdr_vldbentry(&z_xdrs, newentry))
|| (!xdr_long(&z_xdrs, &ReleaseType))) {
z_result = RXGEN_CC_MARSHAL;
צריך להיכשל;
}
z_result = RXGEN_SUCCESS;
לְהִכָּשֵׁל:
return rx_EndCall(z_call, z_result);
}
int StartVL_ReplaceEntry(z_call, Volid, voltype, newentry, ReleaseType)
רשום struct rx_call *z_call;
long Volid, voltype, ReleaseType;
vldbentry * newentry;
{
static int z_op = 506;
int z_result;
XDR z_xdrs;
xdrrx_create(&z_xdrs, z_call, XDR_ENCODE);
/* מרשל הטיעונים */
if ((!xdr_int(&z_xdrs, &z_op))
|| (!xdr_long(&z_xdrs, &Volid))
|| (!xdr_long(&z_xdrs, &voltype))
|| (!xdr_vldbentry(&z_xdrs, newentry))
|| (!xdr_long(&z_xdrs, &ReleaseType))) {
z_result = RXGEN_CC_MARSHAL;
צריך להיכשל;
}
z_result = RXGEN_SUCCESS;
לְהִכָּשֵׁל:
החזר z_result;
}
int EndVL_ReplaceEntry(z_call)
רשום struct rx_call *z_call;
{
int z_result;
XDR z_xdrs;
z_result = RXGEN_SUCCESS;
לְהִכָּשֵׁל:
החזר z_result;
}
int VL_ListAttributes(z_conn, attributes, nentries, bulkentries_1)
רשום struct rx_connection *z_conn;
VldbListByAttributes * תכונות;
ערכים * ארוכים;
bulkentries * bulkentries_1;
{
struct rx_call *z_call = rx_NewCall(z_conn);
static int z_op = 511;
int z_result;
XDR z_xdrs;
xdrrx_create(&z_xdrs, z_call, XDR_ENCODE);
/* מרשל הטיעונים */
if ((!xdr_int(&z_xdrs, &z_op))
|| (!xdr_VldbListByAttributes(&z_xdrs, attributes))) {
z_result = RXGEN_CC_MARSHAL;
צריך להיכשל;
}
/* בטל מרשל את טיעוני התשובה */
z_xdrs.x_op = XDR_DECODE;
if ((!xdr_long(&z_xdrs, nentries))
|| (!xdr_bulkentries(&z_xdrs, bulkentries_1))) {
z_result = RXGEN_CC_UNMARSHAL;
צריך להיכשל;
}
z_result = RXGEN_SUCCESS;
לְהִכָּשֵׁל:
return rx_EndCall(z_call, z_result);
}
int VL_LinkedList(z_conn, attributes, nentries, linkedentries)
רשום struct rx_connection *z_conn;
VldbListByAttributes * תכונות;
ערכים * ארוכים;
vldb_list * ערכים מקושרים;
{
struct rx_call *z_call = rx_NewCall(z_conn);
static int z_op = 512;
int z_result;
XDR z_xdrs;
xdrrx_create(&z_xdrs, z_call, XDR_ENCODE);
/* מרשל הטיעונים */
if ((!xdr_int(&z_xdrs, &z_op))
|| (!xdr_VldbListByAttributes(&z_xdrs, attributes))) {
z_result = RXGEN_CC_MARSHAL;
צריך להיכשל;
}
/* בטל מרשל את טיעוני התשובה */
z_xdrs.x_op = XDR_DECODE;
if ((!xdr_long(&z_xdrs, nentries))
|| (!xdr_vldb_list(&z_xdrs, linkedentries))) {
z_result = RXGEN_CC_UNMARSHAL;
צריך להיכשל;
}
z_result = RXGEN_SUCCESS;
לְהִכָּשֵׁל:
return rx_EndCall(z_call, z_result);
}
שימו לב לתופעת הלוואי של תכונת ה"רב" (שלושה מודולים שונים עבור "החלף כניסה"
פרוק).
בצד השרת בדל שגרות (vldbint.ss.c)
/* קובץ שנוצר על ידי מכונה -- אל תערוך */
#לִכלוֹל
#לִכלוֹל
#לִכלוֹל
#include "vldbint.h"
#include "vl_opcodes.h" /* ישירות למקומות אחרים */
long _VL_CreateEntry(z_call, z_xdrs)
struct rx_call *z_call;
XDR *z_xdrs;
{
long z_result;
ארוך Volid;
vldbentry newentry;
if ((!xdr_long(z_xdrs, &Volid))
|| (!xdr_vldbentry(z_xdrs, &newentry))) {
z_result = RXGEN_SS_UNMARSHAL;
צריך להיכשל;
}
z_result = VL_CreateEntry(z_call, Volid, &newentry);
לְהִכָּשֵׁל:
החזר z_result;
}
long _VL_GetEntryByName(z_call, z_xdrs)
struct rx_call *z_call;
XDR *z_xdrs;
{
long z_result;
char *volumename = (char *)0;
ערך vldbentry;
if ((!xdr_string(z_xdrs, &volumename, 65))) {
z_result = RXGEN_SS_UNMARSHAL;
צריך להיכשל;
}
z_result = VL_GetEntryByName(z_call, &volumename, &entry);
z_xdrs->x_op = XDR_ENCODE;
if ((!xdr_vldbentry(z_xdrs, &entry)))
z_result = RXGEN_SS_MARSHAL;
לְהִכָּשֵׁל:
z_xdrs->x_op = XDR_FREE;
if (!xdr_string(z_xdrs, &volumename, 65)) צריך להיכשל1;
החזר z_result;
נכשל1:
החזר RXGEN_SS_XDRFREE;
}
long _VL_GetNewVolumeId(z_call, z_xdrs)
struct rx_call *z_call;
XDR *z_xdrs;
{
long z_result;
ספירת מהמורות ארוכה;
ארוך newvolumid;
if ((!xdr_long(z_xdrs, &bumpcount))) {
z_result = RXGEN_SS_UNMARSHAL;
צריך להיכשל;
}
z_result = VL_GetNewVolumeId(z_call, bumpcount, &newvolumid);
z_xdrs->x_op = XDR_ENCODE;
if ((!xdr_long(z_xdrs, &newvolumid)))
z_result = RXGEN_SS_MARSHAL;
לְהִכָּשֵׁל:
החזר z_result;
}
long _VL_ReplaceEntry(z_call, z_xdrs)
struct rx_call *z_call;
XDR *z_xdrs;
{
long z_result;
long Volid, voltype, ReleaseType;
vldbentry newentry;
if ((!xdr_long(z_xdrs, &Volid))
|| (!xdr_long(z_xdrs, &voltype))
|| (!xdr_vldbentry(z_xdrs, &newentry))
|| (!xdr_long(z_xdrs, &ReleaseType))) {
z_result = RXGEN_SS_UNMARSHAL;
צריך להיכשל;
}
z_result = VL_ReplaceEntry(z_call, Volid, voltype, &newentry,
ReleaseType);
לְהִכָּשֵׁל:
החזר z_result;
}
long _VL_ListAttributes(z_call, z_xdrs)
struct rx_call *z_call;
XDR *z_xdrs;
{
long z_result;
תכונות VldbListByAttributes;
ערכים ארוכים;
bulkentries bulkentries_1;
if ((!xdr_VldbListByAttributes(z_xdrs, &attributes))) {
z_result = RXGEN_SS_UNMARSHAL;
צריך להיכשל;
}
z_result = VL_ListAttributes(z_call, &attributes, &entries,
&bulkentries_1);
z_xdrs->x_op = XDR_ENCODE;
if ((!xdr_long(z_xdrs, &entries))
|| (!xdr_bulkentries(z_xdrs, &bulkentries_1)))
z_result = RXGEN_SS_MARSHAL;
לְהִכָּשֵׁל:
z_xdrs->x_op = XDR_FREE;
if (!xdr_bulkentries(z_xdrs, &bulkentries_1)) צריך להיכשל1;
החזר z_result;
נכשל1:
החזר RXGEN_SS_XDRFREE;
}
long _VL_LinkedList(z_call, z_xdrs)
struct rx_call *z_call;
XDR *z_xdrs;
{
long z_result;
תכונות VldbListByAttributes;
ערכים ארוכים;
vldb_list linkedentries;
if ((!xdr_VldbListByAttributes(z_xdrs, &attributes))) {
z_result = RXGEN_SS_UNMARSHAL;
צריך להיכשל;
}
z_result = VL_LinkedList(z_call, &attributes, &entries,
&linkedentries);
z_xdrs->x_op = XDR_ENCODE;
if ((!xdr_long(z_xdrs, &entries))
|| (!xdr_vldb_list(z_xdrs, &linkedentries)))
z_result = RXGEN_SS_MARSHAL;
לְהִכָּשֵׁל:
החזר z_result;
}
long _VL_CreateEntry();
long _VL_GetEntryByName();
long _VL_GetNewVolumeId();
long _VL_ReplaceEntry();
long _VL_ListAttributes();
long _VL_LinkedList();
static long (*StubProcsArray0[])() = {_VL_CreateEntry,
_VL_GetEntryByName, _VL_GetNewVolumeId, _VL_ReplaceEntry,
_VL_ListAttributes, _VL_LinkedList};
VL_ExecuteRequest(z_call)
רשום struct rx_call *z_call;
{
int op;
XDR z_xdrs;
long z_result;
xdrrx_create(&z_xdrs, z_call, XDR_DECODE);
if (!xdr_int(&z_xdrs, &op))
z_result = RXGEN_DECODE;
else if (op < VL_LOWEST_OPCODE || op > VL_HIGHEST_OPCODE)
z_result = RXGEN_OPCODE;
אחר
z_result = (*StubProcsArray0[op - VL_LOWEST_OPCODE])
(z_call, &z_xdrs);
החזר z_result;
}
אם היו פערים ברצף opcode של הנהלים, הקוד עבור VL_ExecuteRequest()
השגרה הייתה שונה באופן דרסטי (זו הייתה הצהרת מקרה עבור
כל הליך).
אורים
rxgen מיושם מ-Sun's rpcgen תוֹעֶלֶת. הכל לפי התקן rpcgen's
הפונקציונליות נשמרת במלואה. שימו לב שחלקם פעילים rpcgen אפשרויות שאינן חלות
ל rxgenהמטרה של לא מוזכרת כאן (כלומר, -s, -l, -m אפשרויות) והמתעניינים
הקורא צריך להתייחס אליו rpcgen(1) לפרטים.
כאשר "%#include תכונה בשימוש ודא שאין לך כאלה
rxgen תכונות שפה (כלומר %#defines) מכיוון שתקבל שגיאות תחביר במהלך
קומפילציות..
מכיוון שמדובר בפרויקט מתמשך, רבים מהדברים לעיל עלולים להשתנות/להיעלם ללא עיקרי
אזהרה.
השתמש ב-rxgen באינטרנט באמצעות שירותי onworks.net