[Limacute-commit] r230 - trunk/tools/cybar

limacute at projects.linpro.no limacute at projects.linpro.no
Mon Jan 21 23:27:57 CET 2008


Author: limacute
Date: 2008-01-21 23:27:56 +0100 (Mon, 21 Jan 2008)
New Revision: 230

Modified:
   trunk/tools/cybar/cybar.ml
Log:
Refactored handling of backed up users that are deleted from mailspool. Corrected handling of ^ and . in name.

Modified: trunk/tools/cybar/cybar.ml
===================================================================
--- trunk/tools/cybar/cybar.ml	2008-01-18 17:40:58 UTC (rev 229)
+++ trunk/tools/cybar/cybar.ml	2008-01-21 22:27:56 UTC (rev 230)
@@ -148,7 +148,11 @@
           with 
             | Unix.Unix_error _ -> {src_stat with Unix.st_mtime = 0.}
         in
-          if src_stat.Unix.st_mtime > dst_stat.Unix.st_mtime 
+          (*
+           * If dst mtime is in the past of src, it is an old backup.
+           * If dst mtime is in the future of src, it is an incomplete transfer
+           *)
+          if src_stat.Unix.st_mtime <> dst_stat.Unix.st_mtime 
           then
             begin
               let size = file_copy_via ~via:None ~src ~dst in  
@@ -553,17 +557,32 @@
     ;;
   end
 
-type user = {localpart:string;domain:string option} ;;
+type user = {localpart:string;domain:string option;deleted_age:(float*string) option} ;;
 
+(* Show user with information about delete time *)
 let show_user user = 
   let post = match user.domain with
     | None -> ""
     | Some domain -> "@" ^ domain
   in
+  let post = match user.deleted_age with
+    | None -> post
+    | Some (age,agestr) -> post ^ " deleted at "^agestr 
+  in
     user.localpart ^ post
 ;;
 
+(* Create the email (uid) of the user, ignoring delete_age *)  
+let uid_of_user user = 
+  let post = match user.domain with
+    | None -> ""
+    | Some domain -> "@" ^ domain
+  in
+    user.localpart ^ post
+;;
+
 let hat_regexp = Str.regexp "\\^";;
+let deleted_user_regexp = Str.regexp "^\\(.+\\)\\.\\([0-9]+\\)$";;
 
 let cyrus_escape s = 
   Str.global_replace (Str.regexp "\\.") "^" s
@@ -949,7 +968,7 @@
  * Show the imap name of the user
  *)
 let imap_name user = 
-  "user"^options.hierarchysep^(show_user user)
+  "user"^options.hierarchysep^(uid_of_user user)
 ;;
 
 (** Wildcard listing for cyrus of user with mailboxes *)
@@ -1062,8 +1081,19 @@
           | (localpart::localparts) -> 
               begin
                 let dir = Filename.concat base localpart in
+                  (* transform localpart.age into different semantic parts *)
+                let (localpart,age) = 
+                  if Str.string_match deleted_user_regexp localpart 0 then
+                    let agestr = Str.matched_group 2 localpart in
+                    let age = float_of_string agestr in
+                    let localpart = Str.matched_group 1 localpart in
+                      (localpart,Some (age,agestr))
+                  else
+                    (localpart,None)
+                in
+                  (* replace ^ with . since cyrus does a ^ to . conversion. *)
                 let localpart = Str.global_replace hat_regexp "." localpart in
-                let user = {localpart=localpart;domain=domain} in
+                let user = {localpart=localpart;domain=domain;deleted_age=age} in
                 let collected = collector ~collected ~user ~dir in
                   begin
                     verbose (lazy("Found user "^(show_user user))) ; 
@@ -1149,25 +1179,20 @@
   *)
 let find_deleted_user_backup_and_sieve_dir deleted_user =
   let now = Unix.time () in
-  let deleted_user_regexp = Str.regexp "^\\(.+\\)\\.\\([0-9]+\\)$" in
   let collector ~collected ~user ~dir = 
-      if Str.string_match deleted_user_regexp user.localpart 0 
-      then  
+      match user.deleted_age with
+        | Some (age,agestr) -> 
         begin
-          let localpart = Str.matched_group 1 user.localpart in
-          let agestr = Str.matched_group 2 user.localpart in
-          let age = float_of_string agestr in
           let priority = now -. age in (** Most recently deleted user has smallest number, thus highest priority *)
-          let user = {user with localpart =localpart} in
-            if user = deleted_user then begin
-                verbose (lazy("The user "^(show_user user)^" deleted at "^agestr^" is candidate for restore."));
+            if user.localpart = deleted_user.localpart && user.domain = deleted_user.domain then begin
+                verbose (lazy("The user "^(show_user user)^" deleted at "^(agestr)^" is candidate for restore."));
                 PriorityQueue.insert collected priority (dir,user,agestr)
             end else begin
                 verbose (lazy("The user "^(show_user user)^" is not a restore candidate for "^(show_user deleted_user)^"."));
                 collected
             end
         end
-      else collected 
+        | None -> collected 
   in
   let virtdomains = options.virtdomains in
   let hashimapspool = true in
@@ -1191,33 +1216,31 @@
   * *)
 let find_backup_users () = 
   let collector ~collected ~user ~dir = 
-    let priority = (Unix.stat dir).Unix.st_mtime in
-    let deleted_user_regexp = Str.regexp "^\\(.+\\)\\.\\([0-9]+\\)$" in
-      if Str.string_match deleted_user_regexp user.localpart 0 
-      then  
+      match user.deleted_age with
+      | Some (age,agestr) -> 
         begin
         begin
-         let localpart = Str.matched_group 1 user.localpart in
-         let age = Str.matched_group 2 user.localpart in
-         let age = float_of_string age in
-         let user = {user with localpart =localpart} in
            if age < options.backup_age 
            then 
              begin
                if options.dry_run
-               then verbose (lazy("Skipping purge of expired user "^(show_user user)))
-               else Unixutil.rm ~recursive:true ~force:true dir 
+               then verbose (lazy("Skipping purge of expired user "^(show_user user)^" from "^agestr^"."))
+               else begin
+                 verbose (lazy("Purge of expired user "^(show_user user))) ;
+                 Unixutil.rm ~recursive:true ~force:true dir 
+               end
              end
            else verbose (lazy("User "^(show_user user)^" has not expired from backup yet"))
         end ;
         collected
         end
-      else 
-      begin
-        verbose (lazy("The user "^(show_user user)^" was last backed up "^(string_of_float priority))) ;
-        Hashtbl.add collected user.localpart (priority,user) ;
-        collected
-      end
+      | None -> 
+        begin
+          let priority = (Unix.stat dir).Unix.st_mtime in
+          verbose (lazy("The user "^(show_user user)^" was last backed up "^(string_of_float priority))) ;
+          Hashtbl.add collected user.localpart (priority,user) ;
+          collected
+        end
   in
   let virtdomains = options.virtdomains in
   let hashimapspool = true in
@@ -1271,7 +1294,7 @@
   let rec rename_backup_of_users = function
     | [] -> ()
     | (deleted_user::deleted_users) -> 
-        let uid = show_user deleted_user in
+        let uid = uid_of_user deleted_user in
         if options.uidfilter uid then
         begin
           verbose (lazy("User "^uid^" deleted in mailspool, updating backup.")) ;
@@ -1812,7 +1835,7 @@
           if options.run
           then
             let (priority,(user,dir),users_to_backup) = PriorityQueue.extract users_to_backup in
-            let uid = (show_user user) in
+            let uid = (uid_of_user user) in
               begin
                 begin
                   if options.uidfilter uid
@@ -1859,7 +1882,7 @@
 let mboxlines_collector ~size ~user = 
   let mboxlines = Buffer.create size in
   let mboxline ~cyrbase =
-    let line = ((show_cyrus user)^cyrbase^"\tdefault\t"^(show_user user)^"\tlrswipcda\t\n") in
+    let line = ((show_cyrus user)^cyrbase^"\tdefault\t"^(uid_of_user user)^"\tlrswipcda\t\n") in
     verbose (lazy("mboxline:"^line));
     Buffer.add_string mboxlines line ; 
   in
@@ -1869,7 +1892,7 @@
 (* Create a regular expression that matches the email address of the given user.
  *)
 let create_uidfilter_for_user user = 
-  let uid = show_user user in
+  let uid = uid_of_user user in
     (* Replace "." with "\.", modulo string and regexp handling of \ *)
   let re_uid = Str.global_replace (Str.regexp "\\.") "\\." uid in 
   let regexp = Str.regexp ("^"^re_uid^"$") in 
@@ -2183,13 +2206,14 @@
     * Return list of users in backup that are valid for recovery.
     *)
   let find_recoverable_users () = 
-    let deleted_user_regexp = Str.regexp "^\\(.+\\)\\.\\([0-9]+\\)$" in
     let collector ~collected ~user ~dir = 
       verbose (lazy("Checking if recovery is needed for "^(show_user user)));
-      if Str.string_match deleted_user_regexp user.localpart 0 
-      then collected
-      else 
-        begin
+      match user.deleted_age with
+        | Some (age,agestr) -> begin
+          verbose (lazy("Skipping recovery of deleted user "^(show_user user)^"deleted at "^(agestr)^".")) ;
+          collected
+        end
+        | None -> begin
           verbose (lazy("Planning to do recovery for user "^(show_user user))) ;
           (user,dir)::collected
         end
@@ -2248,7 +2272,7 @@
               then None
               else Some (String.sub domain 1 (length-1)) (* remove the @ *) 
           in
-            cont {localpart=localpart;domain=domain} 
+            cont {localpart=localpart;domain=domain;deleted_age=None} 
         end
       else onfail ()
     in



More information about the Limacute-commit mailing list