Анимация
JavaScript


Главная  Библионтека 

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 [ 162 ] 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242

14.4. Объединение DBM-файлов 503

dbmopen позволяет работать лишь с одним форматом баз данных и поэтому считается устаревшим.

Копирование хэшей простым присваиванием (%new = %old) работает и для DBM-файлов, однако сначала все данные загружаются в память в виде списка. Для малых хэшей это несушественно, но для больших DBM-файлов затраты могут стать непозволительно большими. Для хэшей баз данных лучше использовать перебор с помощью функции each.

[> Смотри также-

Документация по стандартным модулям GDBM File, NDBMFile, SDBMFile, DB File; рецепт 14.1.

14.4. Объединение DBM-файлов

Проблема

Требуется объединить два DBM-файла в один с сохранением исходных пар «ключ/значение».

Решение

Либо объедините базы данных, интерпретируя их хэши как списки:

%OUTPUT = (%INPUT1, %INPUT2); либо (более разумный вариант) организуйте перебор пар «ключ/значение»:

%OUTPUT =0;

foreach $href ( \%INPUT1, \%INPUT2 ) {

while (my($key, Svalue) = each(%Shref)) { If (exists $OUTPUT{Skey}) {

# Выбрать используемое значение tt и при необходимости присвоить SOUTPUT{Skey} } else {

$OUTPUT{$key) = Svalue;

Комментарий

Прямолинейный подход из рецепта 5.10 обладает тем же недостатком. Объединение хэшей посредством списковой интерпретации требует, чтобы хэши были предварительно загружены в память, что может привести к созданию огромных временных списков. Если вы работаете с большими хэшами и/или не располагаете достаточной виртуальной памятью, организуйте перебор ключей в цикле each - это позволит сэкономить память.

Между этими двумя способами объединения есть еще одно отличие - в том, как они поступают с ключами, присутствующими в обоих базах. Присваивание



пустого списка просто заменяет первое значение вторым. Итеративный перебор позволяет принять решение, как поступить с дубликатом. Возможные варианты - выдача предупреждения или ошибки, сохранение первого экземпляра, замена первого экземпляра вторым, конкатенация обоих экземпляров. Используя модуль MLDBM, можно даже сохранить оба экземпляра в виде ссылки на массив из двух элементов.

1> Смотри также-

Рецепты 5.10; 14.8.

14.5. Блокировка DBM-файлов

Проблема

Необходимо обеспечить одновременный доступ к DBM-файлу со стороны нескольких параллельно работающих программ.

Решение

Воспользуйтесь реализацией механизма блокировки DBM, если он имеется, и заблокируйте файл функцией flock либо обратитесь к нестандартной схеме блокировки из рецепта 7.21.

Комментарий

SDBM и GDBM не обладают возможностью блокировки базы данных. Вам придется изобретать нестандартную схему блокировки с применением дополнительного файла.

В GDBM используется концепция доступа для чтения или записи; файл GDBM в любой момент времени может быть открыт либо многими читающими процессами, либо одним записывающим. Тип доступа (чтение или запись) выбирается при открытии файла. Иногда это раздражает.

Версия 1 Berkeley DB предоставляет доступ к файловому дескриптору открытой базы данных, позволяя заблокировать его с помощью flock. Блокировка относится к базе в целом, а не к отдельным записям. Версия 2 реализует собственную полноценную систему транзакций с блокировкой.

В примере 14.3 приведен пример блокировки базы данных с применением Berkeley DB. Попробуйте многократно запустить программу в фоновом режиме, чтобы убедиться в правильном порядгсе предоставления блокировок.

Пример 14.3. dblockdemo

#!/usr/bin/perl

# dblockdemo - демонстрация блокировки базы данных dbm use DB File; use strict;

sub LOCK SH { 1 } # Ha случай, если у вас нет



14.5. Блокировка DBM-файлов 505

sub LOCK EX { 2 > tt стандартного модуля Fcntl.

sub LOCK NB { 4 } Й Конечно, такое встречается редко,

sub LOCK UN { 8 } # но в жизни всякое бывает.

myCSolclval, $fd, $db, %db, Svalue, $key);

Skey = shift default; Svalue = shift magic; Svalue .= " $$";

$db = tie(%db, DB.File, /tmp/foo.db, 0 CREAT0 RDWR, 0666)

or die "dbcreat /tmp/foo.db S!"; Sfd = Sdb->fd; tt Необходимо для блокировки

print "S$: db fd is $fd\n"; open(DB FH, •+<&=$fd")

or die "dup $!";

unless (flock (DB FH, L0CK SH ] L0CK NB)) {

print "SS: CONTENTION; cant read during write update!

Waiting for read lock (S!) ";

unless (flock (DB FH, LOCK SH)) { die "flock: $!" >

print "S$: Read lock granted\n";

Soldval = Sdb{$key};

print "S$: Old value was Soldval\n";

flock(DB FH, LOCK UN);

unless (flock (DB FH, LOCK EX LOCK NB)) {

print "SS: CONTENTION; must have exclusive lock!

Waiting for write lock ($!) ...."; unless (flock (DB FH, LOCK.EX)) { die "flock: $!" }

print "$$: Write lock granted\n"; Sdb{$key} = Svalue; Sdb->sync; jt to flush sleep 10;

flock(DB FH, LOCK UN); undef $db; untie %db; close(DB FH);

print "$$: Updated db to $key=$value\n";

I> Смотри также-

Документация по стандартному модулю DB File; рецепты 7.11; 16.12.



0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 [ 162 ] 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242