קלט/פלט · מחלקות ותכנות מונחה־עצמים

dbmopen#

קושר קובץ DBM בדיסק להאש כך שקריאות וכתיבות להאש הופכות לחיפושים ולאחסונים במסד הנתונים.

dbmopen הוא הדרך הישנה לקשור האש לקובץ dbm, ndbm, sdbm, gdbm, או Berkeley DB. הוא הוחלף ברובו על־ידי tie עם מודול backend מפורש של DBM (DB_File, GDBM_File, SDBM_File, NDBM_File, AnyDBM_File), שנותן שליטה על המימוש שבו משתמשים ועל אפשרויות לכל־backend. יש להושיט יד ל־dbmopen בקריאת קוד מורשת או כאשר תמציתיות ה־one-liner חשובה יותר מבחירת ה־backend.

בניגוד ל־open, הארגומנט הראשון אינו מטפל קובץ - הוא ההאש שיקושר. HASH נכתב עם ה־sigil של %.

תקציר#

dbmopen %HASH, $DBNAME, $MASK
dbmopen(%HASH, $DBNAME, 0)       # open existing only; never create
dbmclose %HASH                   # or: untie %HASH

מה מקבלים בחזרה#

ערך אמת בהצלחה, ערך שקרי בכישלון. בכישלון, $! נקבע לשגיאת המערכת שמנעה את הקישור. מקרי הכישלון הנפוצים הם ״מסד הנתונים אינו קיים ו־MASK הוא 0״ ושגיאות הרשאה על קבצי הגיבוי.

dbmopen(%cache, $path, 0)
    or die "cache $path missing or unreadable: $!";

לאחר קריאה מוצלחת, %HASH מתנהג כמו כל האש אחר: $HASH{key} = $value כותב למסד הנתונים, $HASH{key} קורא ממנו, delete מסיר רשומה, exists בודק חברות, ו־each / keys / values עוברים על הרשומות. הנתונים חיים בדיסק; ההאש הוא רק מבט.

ארגומנטים#

  • HASH - משתנה ההאש לקשירה. חייב להיכתב עם %. כל תוכן קיים מושלך. ההאש נשאר קשור עד שנקראים עליו dbmclose או untie, או עד שהוא יוצא מהתחום.

  • DBNAME - נתיב מסד הנתונים ללא סיומת הקובץ של ה־backend. אחסוני dbm / sdbm מסורתיים משתמשים בשני קבצים בשם `DBNAME.dir` ו־`DBNAME.pag`; gdbm ו־Berkeley DB משתמשים בקובץ יחיד. העברת "/var/lib/app/cache" פותחת את /var/lib/app/cache.dir + /var/lib/app/cache.pag תחת sdbm, או את /var/lib/app/cache תחת gdbm.

  • MASK - מצב יצירה לכל קבצים שצריכים להיווצר, באותה צורה כמו הארגומנט השלישי של chmod (בדרך כלל ליטרל אוקטלי כמו 0666 או 0644). ה־umask הפעיל מוחל על MASK, ולכן ההרשאות האמיתיות בדיסק הן MASK & ~umask. MASK של 0 מדכא יצירה: אם מסד הנתונים אינו קיים כבר, dbmopen מחזיר שקרי ו־$! נקבע.

מצב גלובלי שהוא נוגע בו#

  • $! - נקבע בכישלון (מסד הנתונים חסר, הרשאה נדחתה, אחסון הגיבוי פגום).

  • ה־umask הפעיל - ממסך את MASK כאשר קבצי גיבוי חדשים נוצרים.

דוגמאות#

פתיחת מסד נתוני היסטוריה, מעבר עם each, ולאחר מכן סגירה:

dbmopen(%HIST, '/usr/lib/news/history', 0666)
    or die "open history: $!";
while (my ($key, $val) = each %HIST) {
    print $key, ' = ', unpack('L', $val), "\n";
}
dbmclose %HIST;

פתיחה לקריאה־בלבד, סירוב ליצור את מסד הנתונים:

dbmopen(%cache, "$ENV{HOME}/.app/cache", 0)
    or die "no cache at $ENV{HOME}/.app/cache: $!";
my $hit = $cache{$key};
dbmclose %cache;

בחירת backend ספציפי על־ידי טעינת המודול שלו לפני קריאה ל־dbmopen. AnyDBM_File מתייעץ עם @AnyDBM_File::ISA כדי להחליט באיזה מימוש dbmopen משתמש:

use DB_File;
dbmopen(%NS_Hist, "$ENV{HOME}/.netscape/history.db", 0644)
    or die "open netscape history: $!";

מסד נתונים מוגן־כתיבה - השמה נכשלת בשקט (או croak בהתאם ל־backend); יש להגן עם eval כאשר צריך לבחון:

dbmopen(%db, $path, 0) or die $!;
my $writable = eval { $db{__probe__} = 1; delete $db{__probe__}; 1 };
warn "read-only\n" unless $writable;

מסד נתונים גדול - יש להימנע מ־keys / values, שמממשים את הרשימה כולה בזיכרון. יש להשתמש ב־each במקום:

dbmopen(%big, $path, 0) or die $!;
while (my ($k, $v) = each %big) {
    process($k, $v);
}
dbmclose %big;

מקרי קצה#

  • ה־sigil של ההאש נדרש. dbmopen %h, $name, 0666 - כתיבת $h או \%h לא עובדת. החריץ הראשון הוא שם ההאש כהאש, לא כהפניה.

  • MASK = 0 הוא המטבע של ״פתיחת קיים בלבד״. 0666 נראה־סביר יוצר בשקט מסד נתונים ריק רענן אם הקובץ חסר, מה שכמעט אף פעם אינו מה שקורא רוצה בנתיב חיפוש של מטמון.

  • הסיומות מנוהלות על־ידי ה־backend. אין להעביר "cache.dir" או "cache.pag" - יש להעביר "cache". sdbm מצרף .dir / .pag; gdbm כותב לשם החשוף.

  • פתיחה אחת לכל תהליך עבור DBM ישן יותר. אם ה־backend הוא ספריית dbm(3) המסורתית (נדיר כיום), לתהליך יכולה להיות רק פתיחת DBM אחת בכל זמן נתון. ל־sdbm ול־gdbm אין מגבלה זו.

  • מגבלות גודל ערך. sdbm תוחם מפתחות + ערכים בערך 1008 בתים לכל רשומה; כתיבות חורגות בגודל נקטעות או נדחות. ל־gdbm ול־Berkeley DB יש מגבלות גבוהות בהרבה. במקרה של ספק, יש להשתמש ב־tie עם DB_File ולבדוק את המגבלות של ה־backend עצמו.

  • ערכים מספריים הם בתים בדיסק. אחסון $h{k} = 42 כותב את המחרוזת "42", לא מספר שלם. יש לבצע pack במפורש עם pack / unpack כאשר השדה זקוק לפריסה בינארית קבועה (כמו בדוגמת news-history לעיל).

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

  • קישור מחדש של האש שכבר קשור. קריאה ל־dbmopen על האש שכבר קשור סוגרת קודם את הקישור הקודם.

הבדלים מ־upstream#

תואם מלא ל־upstream Perl 5.42.

ראו גם#

  • dbmclose - שחרור קישור dbmopen ו־flush של כתיבות ממתינות

  • tie - התחליף המודרני; יש לשלב עם DB_File, GDBM_File, SDBM_File, או AnyDBM_File כדי לבחור backend במפורש

  • untie - שחרור קישור שנעשה עם dbmopen או tie

  • each - שידור רשומות בלי לממש את מסד הנתונים כולו בזיכרון

  • umask - ממסך את הארגומנט MASK כאשר קבצי גיבוי נוצרים

  • open - ה־built-in הרגיל לפתיחת קובץ, שלוקח מטפל קובץ ולא האש