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