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

Returns a new instance of 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)

Returns the value of attribute state.



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

def state
  @state
end

#statusObject (readonly)

Returns the value of attribute status.



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

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



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

def clean!
  @status = :clean
end

#clean?Boolean

Returns:

  • (Boolean)


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

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

Returns:

  • (Boolean)


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

def dirty?
  @status == :dirty
end

#eql?(other) ⇒ Boolean

Returns:

  • (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



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

def fail!
  @status = :failed
end

#failed?Boolean

Returns:

  • (Boolean)


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

def failed?
  @status == :failed
end

#hashObject



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

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

#inspectObject



121
122
123
# File 'lib/build/graph/node.rb', line 121

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

Returns:

  • (Boolean)


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

def requires_update?
  not clean?
end

#unknown?Boolean

Returns:

  • (Boolean)


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

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.



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

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.



108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/build/graph/node.rb', line 108

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

Returns:

  • (Boolean)


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

def updating?
  @fiber != nil
end