Чтение онлайн

на главную

Жанры

Linux программирование в примерах

Роббинс Арнольд

Шрифт:

Нам был нужен способ воспроизведения проблемы на своей машине разработки, система с неудачей находилась в стороне за девять часовых поясов, а интерактивный запуск GDB через Атлантический океан мучителен. Мы воспроизвели проблему, заставив

optimal_bufsize
проверять значение специальной переменной окружения
AWKBUFSIZE
. Когда ее значение равно
"exact"
,
optimal_bufsize
всегда возвращает размер файла, каким бы он ни был. Если значением
AWKBUFSIZE
является какое-нибудь целое число, функция возвращает это число. В противном
случае, функция возвращается к прежнему алгоритму. Это дает нам возможность запускать тесты, не требуя постоянной перекомпиляции
gawk
. Например,

$ AWKBUFSIZE=42 make check

Это запускает тестовый набор

gawk
с использованием размера буфера в 42 байта. (Тестовый набор проходит.) Вот модифицированная версия
optimal_bufsize
:

1 /* optimal_bufsize --- определение оптимального размера буфера */

2

3 /*

4 * В целях отладки усовершенствуйте это следующим образом:

5 *

6 * Всегда используйте stat для файла, буфер stat используется кодом

7 * более высокого уровня.

8 * if (AWKBUFSIZE == "exact")

9 * return the file size

10 * else if (AWKBUFSIZE == число)

11 * всегда возвращать это число

12 * else

13 * if размер < default_blocksize

14 * return размер

15 * else

16 * return default_blocksize

17 * end if

18 * end if

19 *

20 * Приходится повозиться, чтобы иметь дело с AWKBUFSIZE лишь

21 * однажды, при первом вызове этой процедуры, а не при каждом

22 * ее вызове. Производительность, знаете ли.

23 */

24

25 size_t

26 optimal_bufsize(fd, stb)

27 int fd;

28 struct stat *stb;

29 {

30 char *val;

31 static size_t env_val = 0;

32 static short first = TRUE;

33 static short exact = FALSE;

34

35 /* обнулить все члены, на случай, если ОС их не использует. */

36 memset(stb, '\0', sizeof(struct stat));

37

38 /* всегда использовать stat на случай, если stb используется кодом более высокого уровня */

39 if (fstat(fd, stb) == -1)

40 fatal("can't stat fd %d (%s)", fd, strerror(errno));

41

42 if (first) {

43 first = FALSE;

44

45 if ((val = getenv("AWKBUFSIZE")) != NULL) {

46 if (strcmp(val, "exact") == 0)

47 exact = TRUE;

48 else if (ISDIGIT(*val)) {

49 for (; *val && ISDIGIT(*val); val++)

50 env_val = (env_val * 10) + *val - '0';

51

52 return env_val;

53 }

54 }

55 } else if (!exact && env_val > 0)

56 return env_val;

57 /* else

58
обрабатывать дальше */

59

60 /*

61 * System V.n, n < 4, не имеет в структуре stat размера системного

62 * блока файла. Поэтому нам нужно осуществить разумную догадку.

63 * Мы используем BUFSIZ из stdio, поскольку именно это имелось

64 * в виду прежде всего.

65 */

66 #ifdef HAVE_ST_BLKSIZE

67 #define DEFBLKSIZE (stb->st_blksize > 0 ? stb->st_blksize : BUFSIZ)

68 #else

69 #define DEFBLKSIZE BUFSIZ

70 #endif

71

72 if (S_ISREG(stb->st_mode) /* обычный файл */

73 && 0 < stb->st_size /* ненулевой размер */

74 && (stb->st_size < DEFBLKSIZE /* маленький файл */

75 || exact)) /* или отладка */

76 return stb->st_size; /* использовать размер файла*/

77

78 return DEFBLKSIZE;

79 }

Комментарий в строках 3–23 объясняет алгоритм. Поскольку поиск переменных окружения может быть затратным и его нужно осуществить лишь однажды, функция использует для сбора соответствующих сведений в первый раз несколько статических переменных.

Строки 42–54 выполняются лишь при первом вызове функции. Строка 43 обеспечивает это условие, устанавливая в

first
значение
false
. Строки 45–54 обрабатывают переменную окружения, разыскивая либо строку
"exact"
, либо число. В последнем случае оно преобразуется из строкового значения в десятичное, сохраняясь в
env_val
. (Возможно, нам следовало бы использовать здесь
strtoul
; в свое время это не пришло нам на ум.)

Строка 55 выполняется каждый раз, кроме первого. Если было представлено числовое значение, условие будет истинным, и возвращается это значение (строка 56). В противном случае, исполнение переходит к оставшейся части функции.

Поделиться:
Популярные книги

Sos! Мой босс кровосос!

Юнина Наталья
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Sos! Мой босс кровосос!

Черный Маг Императора 7 (CИ)

Герда Александр
7. Черный маг императора
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Черный Маг Императора 7 (CИ)

Я – Орк

Лисицин Евгений
1. Я — Орк
Фантастика:
юмористическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Я – Орк

Купеческая дочь замуж не желает

Шах Ольга
Фантастика:
фэнтези
6.89
рейтинг книги
Купеческая дочь замуж не желает

Возвышение Меркурия. Книга 4

Кронос Александр
4. Меркурий
Фантастика:
героическая фантастика
боевая фантастика
попаданцы
5.00
рейтинг книги
Возвышение Меркурия. Книга 4

Газлайтер. Том 6

Володин Григорий
6. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Газлайтер. Том 6

Наследник и новый Новосиб

Тарс Элиан
7. Десять Принцев Российской Империи
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Наследник и новый Новосиб

Законы Рода. Том 4

Flow Ascold
4. Граф Берестьев
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Законы Рода. Том 4

Промышленникъ

Кулаков Алексей Иванович
3. Александр Агренев
Приключения:
исторические приключения
9.13
рейтинг книги
Промышленникъ

Адъютант

Демиров Леонид
2. Мания крафта
Фантастика:
фэнтези
6.43
рейтинг книги
Адъютант

Зауряд-врач

Дроздов Анатолий Федорович
1. Зауряд-врач
Фантастика:
альтернативная история
8.64
рейтинг книги
Зауряд-врач

Измена. Не прощу

Леманн Анастасия
1. Измены
Любовные романы:
современные любовные романы
4.00
рейтинг книги
Измена. Не прощу

Я еще не князь. Книга XIV

Дрейк Сириус
14. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я еще не князь. Книга XIV

Тринадцатый

NikL
1. Видящий смерть
Фантастика:
фэнтези
попаданцы
аниме
6.80
рейтинг книги
Тринадцатый