Skip to content

Commit

Permalink
[DOC] add phar.cache_list, a PATH_SEPARATOR-separated list of full pa…
Browse files Browse the repository at this point in the history
…ths to phar archives to cache

at startup.  This caches the manifest, so that on first access to a phar archive, no file manifest parsing occurs.

This could use further tweaking.  For instance, the full copy of the manifest into the current process may be unnecessary if refcounting could be external
to the manifest.  This would be another significant gain.  With APC, I measure a slight perf increase to 19 req/sec up from 16 req/sec, without it approaches
regular PHP at 3.8 req/sec (regular is 4 req/sec).  This is benching phpMyAdmin
  • Loading branch information
Greg Beaver committed Jun 12, 2008
1 parent 84eb9cc commit 98f2dc2
Show file tree
Hide file tree
Showing 9 changed files with 389 additions and 87 deletions.
325 changes: 293 additions & 32 deletions ext/phar/phar.c

Large diffs are not rendered by default.

Binary file modified ext/phar/phar.phar
Binary file not shown.
9 changes: 9 additions & 0 deletions ext/phar/phar_internal.h
Expand Up @@ -137,6 +137,9 @@ ZEND_BEGIN_MODULE_GLOBALS(phar)
HashTable phar_alias_map;
HashTable phar_SERVER_mung_list;
int readonly;
char* cache_list;
int manifest_cached;
int persist;
int has_zlib;
int has_bz2;
zend_bool readonly_orig;
Expand Down Expand Up @@ -228,6 +231,7 @@ typedef struct _phar_entry_info {
/* when changing compression, save old flags in case fp is NULL */
php_uint32 old_flags;
zval *metadata;
int metadata_len; /* only used for cached manifests */
php_uint32 filename_len;
char *filename;
enum phar_fp_type fp_type;
Expand Down Expand Up @@ -258,6 +262,8 @@ typedef struct _phar_entry_info {
char tar_type;
/* zip-based phar file stuff */
int is_zip:1;
/* for cached phar entries */
int is_persistent:1;
} phar_entry_info;

/* information about a phar file (the archive itself) */
Expand Down Expand Up @@ -286,6 +292,7 @@ struct _phar_archive_data {
int sig_len;
char *signature;
zval *metadata;
int metadata_len; /* only used for cached manifests */
/* if 1, then this alias was manually specified by the user and is not a permanent alias */
int is_temporary_alias:1;
int is_modified:1;
Expand All @@ -299,6 +306,8 @@ struct _phar_archive_data {
int is_tar:1;
/* PharData variables */
int is_data:1;
/* for cached phar manifests */
int is_persistent:1;
};

#define PHAR_MIME_PHP '\0'
Expand Down
42 changes: 22 additions & 20 deletions ext/phar/tar.c
Expand Up @@ -214,11 +214,12 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
hdr = (tar_header*)buf;
old = (memcmp(hdr->magic, "ustar", sizeof("ustar")-1) != 0);

myphar = (phar_archive_data *) ecalloc(1, sizeof(phar_archive_data));
myphar = (phar_archive_data *) pecalloc(1, sizeof(phar_archive_data), PHAR_G(persist));
myphar->is_persistent = PHAR_G(persist);
zend_hash_init(&myphar->manifest, sizeof(phar_entry_info),
zend_get_hash_value, destroy_phar_manifest_entry, 0);
zend_get_hash_value, destroy_phar_manifest_entry, myphar->is_persistent);
zend_hash_init(&myphar->mounted_dirs, sizeof(char *),
zend_get_hash_value, NULL, 0);
zend_get_hash_value, NULL, myphar->is_persistent);
myphar->is_tar = 1;
/* remember whether this entire phar was compressed with gz/bzip2 */
myphar->flags = compression;
Expand Down Expand Up @@ -257,9 +258,9 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
/* some tar programs store directories with trailing slash */
entry.filename_len--;
}
entry.filename = estrndup(name, entry.filename_len);
entry.filename = pestrndup(name, entry.filename_len, myphar->is_persistent);
} else {
entry.filename = estrdup(hdr->name);
entry.filename = pestrdup(hdr->name, myphar->is_persistent);
entry.filename_len = strlen(entry.filename);
if (entry.filename[entry.filename_len - 1] == '/') {
/* some tar programs store directories with trailing slash */
Expand All @@ -271,13 +272,13 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
if (error) {
spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (checksum mismatch of file \"%s\")", fname, entry.filename);
}
efree(entry.filename);
pefree(entry.filename, myphar->is_persistent);
php_stream_close(fp);
zend_hash_destroy(&myphar->manifest);
myphar->manifest.arBuckets = 0;
zend_hash_destroy(&myphar->mounted_dirs);
myphar->mounted_dirs.arBuckets = 0;
efree(myphar);
pefree(myphar, myphar->is_persistent);
return FAILURE;
}

Expand All @@ -286,6 +287,7 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
entry.fp_type = PHAR_FP;
entry.flags = phar_tar_number(hdr->mode, sizeof(hdr->mode)) & PHAR_ENT_PERM_MASK;
entry.timestamp = phar_tar_number(hdr->mtime, sizeof(hdr->mtime));
entry.is_persistent = myphar->is_persistent;

#ifndef S_ISDIR
#define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)
Expand All @@ -305,13 +307,13 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
if (error) {
spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file - hard link to non-existent file \"%s\"", fname, hdr->linkname);
}
efree(entry.filename);
pefree(entry.filename, entry.is_persistent);
php_stream_close(fp);
zend_hash_destroy(&myphar->manifest);
myphar->manifest.arBuckets = 0;
zend_hash_destroy(&myphar->mounted_dirs);
myphar->mounted_dirs.arBuckets = 0;
efree(myphar);
pefree(myphar, entry.is_persistent);
return FAILURE;
}
entry.link = estrdup(hdr->linkname);
Expand All @@ -329,7 +331,7 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
myphar->manifest.arBuckets = 0;
zend_hash_destroy(&myphar->mounted_dirs);
myphar->mounted_dirs.arBuckets = 0;
efree(myphar);
pefree(myphar, myphar->is_persistent);
return FAILURE;
}
}
Expand All @@ -345,7 +347,7 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
myphar->manifest.arBuckets = 0;
zend_hash_destroy(&myphar->mounted_dirs);
myphar->mounted_dirs.arBuckets = 0;
efree(myphar);
pefree(myphar, myphar->is_persistent);
return FAILURE;
}
read = php_stream_read(fp, buf, size);
Expand All @@ -366,10 +368,10 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
myphar->manifest.arBuckets = 0;
zend_hash_destroy(&myphar->mounted_dirs);
myphar->mounted_dirs.arBuckets = 0;
efree(myphar);
pefree(myphar, myphar->is_persistent);
return FAILURE;
}
actual_alias = estrndup(buf, size);
actual_alias = pestrndup(buf, size, myphar->is_persistent);
myphar->alias = actual_alias;
myphar->alias_len = size;
php_stream_seek(fp, pos, SEEK_SET);
Expand All @@ -382,7 +384,7 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
myphar->manifest.arBuckets = 0;
zend_hash_destroy(&myphar->mounted_dirs);
myphar->mounted_dirs.arBuckets = 0;
efree(myphar);
pefree(myphar, myphar->is_persistent);
return FAILURE;
}
}
Expand All @@ -399,7 +401,7 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
myphar->manifest.arBuckets = 0;
zend_hash_destroy(&myphar->mounted_dirs);
myphar->mounted_dirs.arBuckets = 0;
efree(myphar);
pefree(myphar, myphar->is_persistent);
return FAILURE;
}
}
Expand All @@ -413,11 +415,11 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
myphar->manifest.arBuckets = 0;
zend_hash_destroy(&myphar->mounted_dirs);
myphar->mounted_dirs.arBuckets = 0;
efree(myphar);
pefree(myphar, myphar->is_persistent);
return FAILURE;
}
} while (read != 0);
myphar->fname = estrndup(fname, fname_len);
myphar->fname = pestrndup(fname, fname_len, myphar->is_persistent);
#ifdef PHP_WIN32
phar_unixify_path_separators(myphar->fname, fname_len);
#endif
Expand Down Expand Up @@ -449,7 +451,7 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
myphar->manifest.arBuckets = 0;
zend_hash_destroy(&myphar->mounted_dirs);
myphar->mounted_dirs.arBuckets = 0;
efree(myphar);
pefree(myphar, myphar->is_persistent);
return FAILURE;
}
myphar = *actual;
Expand Down Expand Up @@ -481,10 +483,10 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
}
}
zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), actual_alias, myphar->alias_len, (void*)&myphar, sizeof(phar_archive_data*), NULL);
myphar->alias = estrndup(alias, alias_len);
myphar->alias = pestrndup(alias, alias_len, myphar->is_persistent);
myphar->alias_len = alias_len;
} else {
myphar->alias = estrndup(myphar->fname, fname_len);
myphar->alias = pestrndup(myphar->fname, fname_len, myphar->is_persistent);
myphar->alias_len = fname_len;
}
myphar->is_temporary_alias = 1;
Expand Down
3 changes: 3 additions & 0 deletions ext/phar/tests/phpinfo_001.phpt
Expand Up @@ -7,6 +7,7 @@ Phar: phpinfo display 1
--INI--
phar.readonly=0
phar.require_hash=0
phar.cache_list=
--FILE--
<?php
phpinfo(INFO_MODULES);
Expand All @@ -33,6 +34,7 @@ Phar based on pear/PHP_Archive, original concept by Davey Shafik.
Phar fully realized by Gregory Beaver and Marcus Boerger.
Portions of tar implementation Copyright (c) 2003-2007 Tim Kientzle.
Directive => Local Value => Master Value
phar.cache_list => no value => no value
phar.readonly => Off => Off
phar.require_hash => Off => Off
%a
Expand All @@ -53,6 +55,7 @@ Phar based on pear/PHP_Archive, original concept by Davey Shafik.
Phar fully realized by Gregory Beaver and Marcus Boerger.
Portions of tar implementation Copyright (c) 2003-2007 Tim Kientzle.
Directive => Local Value => Master Value
phar.cache_list => no value => no value
phar.readonly => On => Off
phar.require_hash => On => Off
%a
Expand Down
2 changes: 2 additions & 0 deletions ext/phar/tests/phpinfo_002.phpt
Expand Up @@ -7,6 +7,7 @@ Phar: phpinfo display 2
--INI--
phar.readonly=1
phar.require_hash=1
phar.cache_list=
--FILE--
<?php
phpinfo(INFO_MODULES);
Expand All @@ -31,6 +32,7 @@ Phar based on pear/PHP_Archive, original concept by Davey Shafik.
Phar fully realized by Gregory Beaver and Marcus Boerger.
Portions of tar implementation Copyright (c) 2003-2007 Tim Kientzle.
Directive => Local Value => Master Value
phar.cache_list => no value => no value
phar.readonly => On => On
phar.require_hash => On => On
%a
Expand Down
2 changes: 2 additions & 0 deletions ext/phar/tests/phpinfo_003.phpt
Expand Up @@ -7,6 +7,7 @@ Phar: phpinfo display 3
--INI--
phar.readonly=1
phar.require_hash=1
phar.cache_list=
--FILE--
<?php
phpinfo(INFO_MODULES);
Expand All @@ -31,6 +32,7 @@ Phar based on pear/PHP_Archive, original concept by Davey Shafik.
Phar fully realized by Gregory Beaver and Marcus Boerger.
Portions of tar implementation Copyright (c) 2003-2007 Tim Kientzle.
Directive => Local Value => Master Value
phar.cache_list => no value => no value
phar.readonly => On => On
phar.require_hash => On => On
%a
Expand Down
3 changes: 3 additions & 0 deletions ext/phar/tests/phpinfo_004.phpt
Expand Up @@ -7,6 +7,7 @@ Phar: phpinfo display 4
--INI--
phar.readonly=0
phar.require_hash=0
phar.cache_list=
--POST--
a=b
--FILE--
Expand Down Expand Up @@ -37,6 +38,7 @@ Phar based on pear/PHP_Archive, original concept by Davey Shafik.<br />Phar full
</table><br />
<table border="0" cellpadding="3" width="600">
<tr class="h"><th>Directive</th><th>Local Value</th><th>Master Value</th></tr>
<tr><td class="e">phar.cache_list</td><td class="v"><i>no value</i></td><td class="v"><i>no value</i></td></tr>
<tr><td class="e">phar.readonly</td><td class="v">Off</td><td class="v">Off</td></tr>
<tr><td class="e">phar.require_hash</td><td class="v">Off</td><td class="v">Off</td></tr>
</table><br />
Expand All @@ -59,6 +61,7 @@ Phar based on pear/PHP_Archive, original concept by Davey Shafik.<br />Phar full
</table><br />
<table border="0" cellpadding="3" width="600">
<tr class="h"><th>Directive</th><th>Local Value</th><th>Master Value</th></tr>
<tr><td class="e">phar.cache_list</td><td class="v"><i>no value</i></td><td class="v"><i>no value</i></td></tr>
<tr><td class="e">phar.readonly</td><td class="v">On</td><td class="v">Off</td></tr>
<tr><td class="e">phar.require_hash</td><td class="v">On</td><td class="v">Off</td></tr>
</table><br />
Expand Down

0 comments on commit 98f2dc2

Please sign in to comment.