Thread Ordnerstruktur in DB abbilden - evt. eigene DB (File) schreiben? (34 answers)
Opened by lousek at 2011-02-24 00:10

lousek
 2011-03-01 00:32
#146125 #146125
User since
2011-01-19
28 Artikel
BenutzerIn

user image
So ... mein Script funktioniert jetzt soweit, dass es leider am Schluss der oberste Ordner "übrig" im Hash-Tree, sprich der wird nicht gelöscht ... warum genau?

Ist der oberste Ordner evt. nicht als Hash-Referenz "gespeichert", und da ich nur Hash-Referenzen lösche wird dieser dann nicht gelöscht?

Code (perl): (dl )
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
243
244
245
246
247
248
249
250
251
252
253
#!/usr/bin/perl -w

use strict;
use DBI;
use Data::Dumper;
use Data::TreeDumper;

# Define variables
my $db;
my $user;
my $pass;
my $host;
my $dbh;
my $stime;
my $etime;
my $endtime;
my %hash;

## DB data
$db             = "ofrs";
$user   = "ofrs";
$pass   = "ofrs";
$host   = "localhost";

# Connect to DB
$dbh = DBI->connect("DBI:mysql:$db:$host", $user, $pass);

# Set time before import
$stime = time;

# Sync a replication folder on the disk with the database
checkFS("/data/test1"); 

# Set time after import
$etime = time;
$endtime = ($etime - $stime);

# Print needed time
print "Needed $endtime seconds ...\n";

# Creates a hash tree for a replication folder using the pathes in the database
# Syntax: makeTree($repFolder)
# Return Value: hash-tree (hash) 
sub makeTree {
  # Set & define the variables
  my $path = $_[0];
  my $tree={};
  
  # Set query
  my $query = "SELECT path FROM dir WHERE path = '$path';";

  # Run query
  my $sth = $dbh->prepare($query);
  $sth->execute();

  # Use the query results ...
  while (my @result = $sth->fetchrow_array) {
    my $path = $result[0];
    
    # ... and add each path to the hash-tree
    addToTree($tree,$path);  
       
  }

  # return the hash-tree
  return $tree;  
    
}

# add a Path to the hash-tree
# Syntax: addToTree($tree,$path)
# Return value: none
sub addToTree {
  # Set & define the variables
  my $tree = $_[0];
  my $path = $_[1];
  
  # Split the path up to its parts  
  my @parts = split('/',$path);

  # Delete the first (empty) part  
  shift @parts;

  # Delete the trailing slash at the end of the path if exists  
  my $file=1;
  unless($parts[-1])
  {
    $file=0;
    pop(@parts);
  }
  
  # build the hash-tree for this path
  my $ref=\$tree;
  $ref=\$$ref->{$_} for(@parts);

}

# build the pathes from the hash-tree
# Syntax: buildPathes($tree)
# Return value: path-list (array-reference)
sub buildPathes
{
  # Set & define variables
  my $tree=shift;
  my $path=shift // '';
  my @list;
  
  # walk through all levels and sort them
  for my $name (sort(keys(%$tree)))
  {
    my $elm=$tree->{$name};

    if($elm && ref($elm) eq 'HASH')
    {
      
      # run the function recursive
      my $lst=buildPathes($elm,"$path/$name");
      push(@list,@$lst);
    }
    else
    { push(@list,"$path/$name"); }
  }

  # return the list of pathes from the hash-tree
  return \@list;
}

# sync a replication folder on the disk with the database
# Syntax: checkFS($repPath)
# Return value: none
sub checkFS {
  # Set & define variables
  my $path = $_[0];

  # create the hash-tree for this path / replication folder 
  my $tree = makeTree($path);

  # check if the folder on the disk exists in the database
  checkFolder($path, $tree);

  # build the pathes from the hashes left in the hash-tree  
  my $onlyDB = buildPathes($tree);

  # print the pathes out  
  print "OnlyDB-Pathes:\n";
  print Dumper($onlyDB);
  
#  foreach my $path (@$onlyDB) {
#    DELETE THE MISSING FOLDERS FROM THE DATABASE
#  }
  
}

# check a folder and its subfolder if they exists in the hash-tree
# Syntax: checkFolder($path, $tree)
# Return value: none
sub checkFolder {
  # Set variables
        my @subfolders;
  my $path;
  my @parts;
  my $name;
  my $hash;
  my $tmphash;
  my $found;
  my $childNotFound;

  # Load arguments into variables
        if (-d $_[0]) {
    $path = $_[0]; # Load path into variable
  } else {
    # Exit script if no path is specified
    print "Error: No valid path specified\n";
    exit(1);    
  }
  if (defined($_[1])) {
    $hash = $_[1]; # Load hash into variable
  } else {
    # Exit script if no hash is specified
    print "Error: No hash specified\n";
    exit(1);    
  }

  # Set variables
  $childNotFound = 0;

  # split the path to its parts
        @parts=split(/\//, $path);
        shift @parts;
        $name = $parts[-1];
        $found = 0;
        
        $tmphash = \%hash;
        for (my $i = 0; $i < @parts; $i++) { # walk through each part of the path
         my $part = $parts[$i];
                if(defined($tmphash->{$part}))  { # Does the part exists in the hash-tree?
                        if($i == @parts-1) { # Is this the last part of the path?
                                $found=1; # Yes, the folder is in the database!
                        } else { # Not the last part of the path
                                $tmphash=$tmphash->{$part}; # Go one level further
                        }
                } else {                  
                        last; # The path is not in the database
                }
        }  

  if ($found == 0) {
    # Insert current directory into DB
    # Set query
    my $query = "INSERT INTO dir (path) VALUES (\"$path\");";
  
    # Run query
    $dbh->do($query);    
  }

  # Open the current directory  
  opendir (DIR, $path) or die "Unable to open $path: $!";

  # Exclude "." and ".."
  my @files = grep { !/^\.{1,2}$/ } readdir (DIR);

  # Close directory
  closedir (DIR);
  
  # Set the full path for all files
  @files = map { $path . '/' . $_ } @files;


  # Write each subfolder into the array @subfolders
  foreach my $file (@files) {
    if (-d $file) {
      push (@subfolders, $file)
    }  
  }
  
  # If there are any subfolders then ...
  if (@subfolders > 0) {
    foreach my $subfolder (@subfolders) {
      # ... put the subfolder into the DB using the subfolder's path and the id of the current directory
      $childNotFound = checkFolder($subfolder, \%hash);
    }    
  } 
  
  # if this directory was found in the path and if it has no subfolders, then delete it from the hash-tree
  if ($found == 1 && !keys(%{$tmphash->{$name}})) {
    delete $tmphash->{$name};
    return 0;
  } else {
    # return 1 if this folder is either not in the hash-tree or if this directory has subfolders
    return 1;
  }
    
}

View full thread Ordnerstruktur in DB abbilden - evt. eigene DB (File) schreiben?