Class: Build::Graph::Node

Inherits:
Object
  • Object
show all
Defined in:
lib/build/graph/node.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(controller, inputs, outputs) ⇒ Node



26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/build/graph/node.rb', line 26

def initialize(controller, inputs, outputs)
  @controller = controller

  @state = Files::IOState.new(inputs, outputs)

  @status = :unknown
  @fiber = nil

  # These are immutable - rather than change them, create a new node:
  @inputs = inputs
  @outputs = outputs

  @controller.add(self)
end

Instance Attribute Details

#inputsObject (readonly)

Returns the value of attribute inputs.



73
74
75
# File 'lib/build/graph/node.rb', line 73

def inputs
  @inputs
end

#outputsObject (readonly)

Returns the value of attribute outputs.



74
75
76
# File 'lib/build/graph/node.rb', line 74

def outputs
  @outputs
end

#stateObject (readonly)

The IOState for this node.



77
78
79
# File 'lib/build/graph/node.rb', line 77

def state
  @state
end

#statusObject (readonly)

The status of this node.



80
81
82
# File 'lib/build/graph/node.rb', line 80

def status
  @status
end

Instance Method Details

#changed!(outputs = []) ⇒ Object

It is possible this function is called unnecessarily. The state check confirms whether a change occurred or not.



58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/build/graph/node.rb', line 58

def changed!(outputs = [])
  # Don't do anything if we are already dirty.
  return if dirty?
    
  if @state.intersects?(outputs) || @state.update!
    # puts "** Dirty: #{@inputs.to_a.inspect} -> #{@outputs.to_a.inspect}"

    # Could possibly use unknown status here.
    @status = :dirty

    # If this node changes, we force all other nodes which depend on this node to be dirty.
    @controller.update(directories, @outputs)
  end
end

#clean!Object



94
95
96
# File 'lib/build/graph/node.rb', line 94

def clean!
  @status = :clean
end

#clean?Boolean



90
91
92
# File 'lib/build/graph/node.rb', line 90

def clean?
  @status == :clean
end

#directoriesObject



49
50
51
# File 'lib/build/graph/node.rb', line 49

def directories
  @state.files.roots
end

#dirty?Boolean



86
87
88
# File 'lib/build/graph/node.rb', line 86

def dirty?
  @status == :dirty
end

#eql?(other) ⇒ Boolean



41
42
43
# File 'lib/build/graph/node.rb', line 41

def eql?(other)
  other.kind_of?(self.class) and @inputs.eql?(other.inputs) and @outputs.eql?(other.outputs)
end

#fail!Object



98
99
100
# File 'lib/build/graph/node.rb', line 98

def fail!
  @status = :failed
end

#failed?Boolean



102
103
104
# File 'lib/build/graph/node.rb', line 102

def failed?
  @status == :failed
end

#hashObject



45
46
47
# File 'lib/build/graph/node.rb', line 45

def hash
  [@inputs, @outputs].hash
end

#inspectObject



124
125
126
# File 'lib/build/graph/node.rb', line 124

def inspect
  "<#{dirty? ? '*' : ''}inputs=#{inputs.inspect} outputs=#{outputs.inspect} fiber=#{@fiber.inspect} fresh=#{@state.fresh?}>"
end

#remove!Object



53
54
55
# File 'lib/build/graph/node.rb', line 53

def remove!
  @controller.delete(self)
end

#requires_update?Boolean



128
129
130
# File 'lib/build/graph/node.rb', line 128

def requires_update?
  not clean?
end

#unknown?Boolean



82
83
84
# File 'lib/build/graph/node.rb', line 82

def unknown?
  @status == :unknown
end

#update!(walker) ⇒ Object

Perform some actions to update this node, returns when completed, and the node is no longer dirty.



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/build/graph/node.rb', line 133

def update!(walker)
  #puts "Walking #{@inputs.to_a.inspect} -> #{@outputs.to_a.inspect} (dirty=#{dirty?} @fiber=#{@fiber.inspect})"

  # If a fiber already exists, this node is in the process of updating.
  if requires_update? and @fiber == nil
    # puts "Beginning: #{@inputs.to_a.inspect} -> #{@outputs.to_a.inspect}"
  
    @fiber = Fiber.new do
      task = walker.task(self)
    
      task.visit
    
      # Commit changes:
      # puts "** Committing: #{@inputs.to_a.inspect} -> #{@outputs.to_a.inspect}"
    
      @state.update!
      @fiber = nil
    
      task.exit
    end

    @fiber.resume
  end
end

#update_status!Object

If we are in the initial state, we need to check if the outputs are fresh.



111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/build/graph/node.rb', line 111

def update_status!
  #puts "Update status: #{@inputs.inspect} -> #{@outputs.inspect} (status=#{@status} @fiber=#{@fiber.inspect}) @status=#{@status} @state.fresh?=#{@state.fresh?}"

  if @status == :unknown
    # This could be improved - only stale files should be reported, instead we report all.
    unless @state.fresh?
      changed!(self.inputs)
    else
      @status = :clean
    end
  end
end

#updating?Boolean



106
107
108
# File 'lib/build/graph/node.rb', line 106

def updating?
  @fiber != nil
end