File: utils.rb

package info (click to toggle)
ruby-logging 2.2.2-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 660 kB
  • sloc: ruby: 6,139; sh: 11; makefile: 2
file content (170 lines) | stat: -rw-r--r-- 4,594 bytes parent folder | download | duplicates (3)
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

require 'thread'
require 'rbconfig'

# --------------------------------------------------------------------------
class String

  # call-seq:
  #    shrink( width, ellipses = '...' )    #=> string
  #
  # Shrink the size of the current string to the given _width_ by removing
  # characters from the middle of the string and replacing them with
  # _ellipses_. If the _width_ is greater than the length of the string, the
  # string is returned unchanged. If the _width_ is less than the length of
  # the _ellipses_, then the _ellipses_ are returned.
  #
  def shrink( width, ellipses = '...')
    raise ArgumentError, "width cannot be negative: #{width}" if width < 0

    return self if length <= width

    remove = length - width + ellipses.length
    return ellipses.dup if remove >= length

    left_end = (length + 1 - remove) / 2
    right_start = left_end + remove

    left = self[0,left_end]
    right = self[right_start,length-right_start]

    left << ellipses << right
  end
end

# --------------------------------------------------------------------------
class Module

  # call-seq:
  #    logger_name    #=> string
  #
  # Returns a predictable logger name for the current module or class. If
  # used within an anonymous class, the first non-anonymous class name will
  # be used as the logger name. If used within a meta-class, the name of the
  # actual class will be used as the logger name. If used within an
  # anonymous module, the string 'anonymous' will be returned.
  #
  def logger_name
    return name unless name.nil? or name.empty?

    # check if this is a metaclass (or eigenclass)
    if ancestors.include? Class
      inspect =~ %r/#<Class:([^#>]+)>/
      return $1
    end

    # see if we have a superclass
    if respond_to? :superclass
      return superclass.logger_name
    end

    # we are an anonymous module
    ::Logging.log_internal(-2) {
      'cannot return a predictable, unique name for anonymous modules'
    }
    return 'anonymous'
  end
end

# --------------------------------------------------------------------------
class File

  # Returns <tt>true</tt> if another process holds an exclusive lock on the
  # file. Returns <tt>false</tt> if this is not the case.
  #
  # If a <tt>block</tt> of code is passed to this method, it will be run iff
  # this process can obtain an exclusive lock on the file. The block will be
  # run while this lock is held, and the exclusive lock will be released when
  # the method returns.
  #
  # The exclusive lock is requested in a non-blocking mode. This method will
  # return immediately (and the block will not be executed) if an exclusive
  # lock cannot be obtained.
  #
  def flock?
    status = flock(LOCK_EX|LOCK_NB)
    case status
    when false; true
    when 0; block_given? ? yield : false
    else
      raise SystemCallError, "flock failed with status: #{status}"
    end
  ensure
    flock LOCK_UN
  end

  # Execute a <tt>block</tt> in the context of a shared lock on this file. A
  # shared lock will be obtained on the file, the block executed, and the lock
  # released.
  #
  def flock_sh
    flock LOCK_SH
    yield
  ensure
    flock LOCK_UN
  end

  # :stopdoc:
  conf = defined?(RbConfig) ? RbConfig::CONFIG : Config::CONFIG
  if conf['host_os'] =~ /mswin|windows|cygwin|mingw/i
    # don't lock files on windows
    undef :flock?, :flock_sh
    def flock?() yield; end
    def flock_sh() yield; end
  end
  # :startdoc:

end

# --------------------------------------------------------------------------
module FileUtils

  # Concatenate the contents of the _src_ file to the end of the _dest_ file.
  # If the _dest_ file does not exist, then the _src_ file is copied to the
  # _dest_ file using +copy_file+.
  #
  def concat( src, dest )
    if File.exist?(dest)
      bufsize = File.stat(dest).blksize || 8192
      buffer = String.new

      File.open(dest, 'a') { |d|
        File.open(src, 'r') { |r|
          while bytes = r.read(bufsize, buffer)
            d.syswrite bytes
          end
        }
      }
    else
      copy_file(src, dest)
    end
  end
  module_function :concat
end

# --------------------------------------------------------------------------
class ReentrantMutex < Mutex

  def initialize
    super
    @locker = nil
  end

  alias_method :original_synchronize, :synchronize

  def synchronize
    if @locker == Thread.current
      yield
    else
      original_synchronize {
        begin
          @locker = Thread.current
          yield
        ensure
          @locker = nil
        end
      }
    end
  end
end  # ReentrantMutex