Hans Leidekker : wbemprox: Optimize a common Win32_Directory query.
Alexandre Julliard
julliard at winehq.org
Tue Jun 4 15:48:35 CDT 2013
Module: wine
Branch: master
Commit: 8e1aa4358a7eeef906a9255594f27f9e5910eb6c
URL: http://source.winehq.org/git/wine.git/?a=commit;h=8e1aa4358a7eeef906a9255594f27f9e5910eb6c
Author: Hans Leidekker <hans at codeweavers.com>
Date: Tue Jun 4 13:26:32 2013 +0200
wbemprox: Optimize a common Win32_Directory query.
---
dlls/wbemprox/builtin.c | 176 +++++++++++++++++++++++++++++++++++++----------
1 files changed, 139 insertions(+), 37 deletions(-)
diff --git a/dlls/wbemprox/builtin.c b/dlls/wbemprox/builtin.c
index fc77419..91bcb9e 100644
--- a/dlls/wbemprox/builtin.c
+++ b/dlls/wbemprox/builtin.c
@@ -839,37 +839,6 @@ static enum fill_status fill_compsys( struct table *table, const struct expr *co
return status;
}
-static WCHAR *get_filesystem( const WCHAR *root )
-{
- static const WCHAR ntfsW[] = {'N','T','F','S',0};
- WCHAR buffer[MAX_PATH + 1];
-
- if (GetVolumeInformationW( root, NULL, 0, NULL, NULL, NULL, buffer, MAX_PATH + 1 ))
- return heap_strdupW( buffer );
- return heap_strdupW( ntfsW );
-}
-
-static UINT64 get_freespace( const WCHAR *dir, UINT64 *disksize )
-{
- WCHAR root[] = {'\\','\\','.','\\','A',':',0};
- ULARGE_INTEGER free;
- DISK_GEOMETRY_EX info;
- HANDLE handle;
-
- free.QuadPart = 512 * 1024 * 1024;
- GetDiskFreeSpaceExW( dir, NULL, NULL, &free );
-
- root[4] = dir[0];
- handle = CreateFileW( root, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
- if (handle != INVALID_HANDLE_VALUE)
- {
- if (DeviceIoControl( handle, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, &info, sizeof(info), NULL, NULL ))
- *disksize = info.DiskSize.QuadPart;
- CloseHandle( handle );
- }
- return free.QuadPart;
-}
-
struct dirstack
{
WCHAR **dirs;
@@ -899,10 +868,16 @@ static struct dirstack *alloc_dirstack( UINT size )
return dirstack;
}
-static void free_dirstack( struct dirstack *dirstack )
+static void clear_dirstack( struct dirstack *dirstack )
{
UINT i;
for (i = 0; i < dirstack->num_dirs; i++) heap_free( dirstack->dirs[i] );
+ dirstack->num_dirs = 0;
+}
+
+static void free_dirstack( struct dirstack *dirstack )
+{
+ clear_dirstack( dirstack );
heap_free( dirstack->dirs );
heap_free( dirstack->len_dirs );
heap_free( dirstack );
@@ -912,6 +887,8 @@ static BOOL push_dir( struct dirstack *dirstack, WCHAR *dir, UINT len )
{
UINT size, i = dirstack->num_dirs;
+ if (!dir) return FALSE;
+
if (i == dirstack->num_allocated)
{
WCHAR **tmp;
@@ -957,7 +934,7 @@ static WCHAR *build_glob( WCHAR drive, const WCHAR *path, UINT len )
ret[i++] = drive;
ret[i++] = ':';
ret[i++] = '\\';
- if (path)
+ if (path && len)
{
memcpy( ret + i, path, len * sizeof(WCHAR) );
i += len;
@@ -968,7 +945,7 @@ static WCHAR *build_glob( WCHAR drive, const WCHAR *path, UINT len )
return ret;
}
-static WCHAR *build_dirname( WCHAR drive, const WCHAR *path )
+static WCHAR *build_name( WCHAR drive, const WCHAR *path )
{
UINT i = 0, len = 0;
const WCHAR *p;
@@ -997,6 +974,90 @@ static WCHAR *build_dirname( WCHAR drive, const WCHAR *path )
return ret;
}
+static WCHAR *build_dirname( const WCHAR *path, UINT *ret_len )
+{
+ const WCHAR *p = path, *start;
+ UINT len, i;
+ WCHAR *ret;
+
+ if (!isalphaW( p[0] ) || p[1] != ':' || p[2] != '\\' || p[3] != '\\' || !p[4]) return NULL;
+ start = path + 4;
+ len = strlenW( start );
+ p = start + len - 1;
+ if (*p == '\\') return NULL;
+
+ while (p >= start && *p != '\\') { len--; p--; };
+ while (p >= start && *p == '\\') { len--; p--; };
+
+ if (!(ret = heap_alloc( (len + 1) * sizeof(WCHAR) ))) return NULL;
+ for (i = 0, p = start; p < start + len; p++)
+ {
+ if (p[0] == '\\' && p[1] == '\\')
+ {
+ ret[i++] = '\\';
+ p++;
+ }
+ else ret[i++] = *p;
+ }
+ ret[i] = 0;
+ *ret_len = i;
+ return ret;
+}
+
+static BOOL seen_dir( struct dirstack *dirstack, const WCHAR *path )
+{
+ UINT i;
+ for (i = 0; i < dirstack->num_dirs; i++) if (!strcmpW( dirstack->dirs[i], path )) return TRUE;
+ return FALSE;
+}
+
+/* optimize queries of the form WHERE Name='...' [OR Name='...']* */
+static UINT seed_dirs( struct dirstack *dirstack, const struct expr *cond, WCHAR root, UINT *count )
+{
+ const struct expr *left = cond->u.expr.left, *right = cond->u.expr.right;
+
+ if (cond->type != EXPR_COMPLEX) return *count = 0;
+ if (cond->u.expr.op == OP_EQ)
+ {
+ UINT len;
+ WCHAR *path;
+ const WCHAR *str = NULL;
+
+ if (left->type == EXPR_PROPVAL && right->type == EXPR_SVAL &&
+ !strcmpW( left->u.propval->name, prop_nameW ) &&
+ toupperW( right->u.sval[0] ) == toupperW( root ))
+ {
+ str = right->u.sval;
+ }
+ else if (left->type == EXPR_SVAL && right->type == EXPR_PROPVAL &&
+ !strcmpW( right->u.propval->name, prop_nameW ) &&
+ toupperW( left->u.sval[0] ) == toupperW( root ))
+ {
+ str = left->u.sval;
+ }
+ if (str && (path = build_dirname( str, &len )))
+ {
+ if (seen_dir( dirstack, path ))
+ {
+ heap_free( path );
+ return ++*count;
+ }
+ else if (push_dir( dirstack, path, len )) return ++*count;
+ heap_free( path );
+ return *count = 0;
+ }
+ }
+ else if (cond->u.expr.op == OP_OR)
+ {
+ UINT left_count = 0, right_count = 0;
+
+ if (!(seed_dirs( dirstack, left, root, &left_count ))) return *count = 0;
+ if (!(seed_dirs( dirstack, right, root, &right_count ))) return *count = 0;
+ return *count += left_count + right_count;
+ }
+ return *count = 0;
+}
+
static WCHAR *append_path( const WCHAR *path, const WCHAR *segment, UINT *len )
{
UINT len_path = 0, len_segment = strlenW( segment );
@@ -1005,7 +1066,7 @@ static WCHAR *append_path( const WCHAR *path, const WCHAR *segment, UINT *len )
*len = 0;
if (path) len_path = strlenW( path );
if (!(ret = heap_alloc( (len_path + len_segment + 2) * sizeof(WCHAR) ))) return NULL;
- if (path)
+ if (path && len_path)
{
memcpy( ret, path, len_path * sizeof(WCHAR) );
ret[len_path] = '\\';
@@ -1021,7 +1082,7 @@ static enum fill_status fill_directory( struct table *table, const struct expr *
{
static const WCHAR dotW[] = {'.',0}, dotdotW[] = {'.','.',0};
struct record_directory *rec;
- UINT i, len, row = 0, offset = 0, count = 4;
+ UINT i, len, row = 0, offset = 0, count = 4, num_expected_rows;
WCHAR *glob = NULL, *path = NULL, *new_path, root[] = {'A',':','\\',0};
DWORD drives = GetLogicalDrives();
WIN32_FIND_DATAW data;
@@ -1038,6 +1099,9 @@ static enum fill_status fill_directory( struct table *table, const struct expr *
root[0] = 'A' + i;
if (GetDriveTypeW( root ) != DRIVE_FIXED) continue;
+ num_expected_rows = 0;
+ if (!seed_dirs( dirstack, cond, root[0], &num_expected_rows )) clear_dirstack( dirstack );
+
for (;;)
{
path = pop_dir( dirstack, &len );
@@ -1074,12 +1138,19 @@ static enum fill_status fill_directory( struct table *table, const struct expr *
}
rec = (struct record_directory *)(table->data + offset);
rec->accessmask = FILE_ALL_ACCESS;
- rec->name = build_dirname( root[0], new_path );
+ rec->name = build_name( root[0], new_path );
if (!match_row( table, row, cond, &status ))
{
free_row_values( table, row );
continue;
}
+ else if (num_expected_rows && row == num_expected_rows - 1)
+ {
+ row++;
+ FindClose( handle );
+ status = FILL_STATUS_FILTERED;
+ goto done;
+ }
offset += sizeof(*rec);
row++;
}
@@ -1102,6 +1173,37 @@ done:
return status;
}
+static WCHAR *get_filesystem( const WCHAR *root )
+{
+ static const WCHAR ntfsW[] = {'N','T','F','S',0};
+ WCHAR buffer[MAX_PATH + 1];
+
+ if (GetVolumeInformationW( root, NULL, 0, NULL, NULL, NULL, buffer, MAX_PATH + 1 ))
+ return heap_strdupW( buffer );
+ return heap_strdupW( ntfsW );
+}
+
+static UINT64 get_freespace( const WCHAR *dir, UINT64 *disksize )
+{
+ WCHAR root[] = {'\\','\\','.','\\','A',':',0};
+ ULARGE_INTEGER free;
+ DISK_GEOMETRY_EX info;
+ HANDLE handle;
+
+ free.QuadPart = 512 * 1024 * 1024;
+ GetDiskFreeSpaceExW( dir, NULL, NULL, &free );
+
+ root[4] = dir[0];
+ handle = CreateFileW( root, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
+ if (handle != INVALID_HANDLE_VALUE)
+ {
+ if (DeviceIoControl( handle, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, &info, sizeof(info), NULL, NULL ))
+ *disksize = info.DiskSize.QuadPart;
+ CloseHandle( handle );
+ }
+ return free.QuadPart;
+}
+
static enum fill_status fill_diskpartition( struct table *table, const struct expr *cond )
{
static const WCHAR fmtW[] =
More information about the wine-cvs
mailing list