To edit pages or tickets please login with username/password: aaf/aaf

Changeset 321

Show
Ignore:
Timestamp:
02/18/08 20:36:05 (8 months ago)
Author:
jk
Message:

drb somewhat works

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/demo/app/models/comment.rb

    r308 r321  
    2828  # do this in our custom to_doc method) 
    2929  acts_as_ferret( :store_class_name => true,  
    30                   :remote           => ENV['AAF_REMOTE'] == 'true',  # for testing drb remote indexing 
    31                   :raise_drb_errors => ENV['RAISE_DRB_ERRORS'] == 'true', 
    3230                  :fields => { 
    3331                    :content => { :store => :yes }, 
  • trunk/demo/app/models/content_base.rb

    r317 r321  
    1515                               :description   => { :boost => 1, :store => :yes }, 
    1616                               :special       => {} }, 
    17                   :store_class_name => true, 
    18                   :boost => :record_boost, 
    19                   :raise_drb_errors => ENV['RAISE_DRB_ERRORS'] == 'true', 
    20                   :remote           => ENV['AAF_REMOTE'] == 'true') 
     17                  :boost => :record_boost) 
    2118 
    2219  def comment_count; 0 end 
  • trunk/demo/config/environment.rb

    r318 r321  
    5555# Include your application configuration below 
    5656 
     57ActsAsFerret::remote = false if ENV['AAF_REMOTE'] != 'true' 
     58ActsAsFerret::raise_drb_errors = ENV['RAISE_DRB_ERRORS'] == 'true' 
     59 
    5760# define the index shared by the SharedIndex1 and SharedIndex2 classes 
    5861ActsAsFerret::define_index 'shared', :remote           => ENV['AAF_REMOTE'] == 'true', 
  • trunk/plugin/acts_as_ferret/lib/act_methods.rb

    r320 r321  
    6363    # last Hash argument. 
    6464    def acts_as_ferret(options={}) 
    65       # default to DRb mode 
    66       options[:remote] = true if options[:remote].nil? 
    67  
    68       # force local mode if running *inside* the Ferret server - somewhere the 
    69       # real indexing has to be done after all :-) 
    70       # Usually the automatic detection of server mode works fine, however if you  
    71       # require your model classes in environment.rb they will get loaded before the  
    72       # DRb server is started, so this code is executed too early and detection won't  
    73       # work. In this case you'll get endless loops resulting in "stack level too deep"  
    74       # errors.  
    75       # To get around this, start the DRb server with the environment variable  
    76       # FERRET_USE_LOCAL_INDEX set to '1'. 
    77       logger.debug "Asked for a remote server ? #{options[:remote].inspect}, ENV[\"FERRET_USE_LOCAL_INDEX\"] is #{ENV["FERRET_USE_LOCAL_INDEX"].inspect}, looks like we are#{ActsAsFerret::Remote::Server.running || ENV['FERRET_USE_LOCAL_INDEX'] ? '' : ' not'} the server" 
    78       options.delete(:remote) if ENV["FERRET_USE_LOCAL_INDEX"] || ActsAsFerret::Remote::Server.running 
    79  
    80       if options[:remote] && options[:remote] !~ /^druby/ 
    81         # read server location from config/ferret_server.yml 
    82         options[:remote] = ActsAsFerret::Remote::Config.new.uri rescue nil 
    83       end 
    84  
    85       if options[:remote] 
    86         logger.info "Will use remote index server which should be available at #{options[:remote]}" 
    87       else 
    88         logger.info "Will use local index." 
    89       end 
    9065 
    9166      extend ClassMethods 
  • trunk/plugin/acts_as_ferret/lib/acts_as_ferret.rb

    r320 r321  
    2626 
    2727require 'ferret_find_methods' 
     28require 'remote_functions' 
    2829require 'blank_slate' 
    2930require 'bulk_indexer' 
     
    3839 
    3940require 'multi_index' 
     41require 'remote_multi_index' 
    4042require 'more_like_this' 
    4143 
     
    105107    :boost       => 1.0 
    106108  } 
     109 
     110  @@raise_drb_errors = false 
     111  mattr_writer :raise_drb_errors 
     112  def self.raise_drb_errors?; @@raise_drb_errors end 
     113   
     114  @@remote = nil 
     115  mattr_accessor :remote 
     116  def self.remote? 
     117    if @@remote.nil? 
     118      if ENV["FERRET_USE_LOCAL_INDEX"] || ActsAsFerret::Remote::Server.running 
     119        @@remote = false 
     120      else 
     121        @@remote = ActsAsFerret::Remote::Config.new.uri rescue false 
     122      end 
     123      if @@remote 
     124        logger.info "Will use remote index server which should be available at #{@@remote}" 
     125      else 
     126        logger.info "Will use local index." 
     127      end 
     128    end 
     129    @@remote 
     130  end 
     131  remote? 
     132 
    107133 
    108134  # Globally declares an index. 
     
    153179 
    154180 
    155     unless index_definition[:remote] 
     181    unless remote? 
    156182      ActsAsFerret::ensure_directory index_definition[:index_dir]  
    157183      index_definition[:index_base_dir] = index_definition[:index_dir] 
     
    185211  # returns the index with the given name. 
    186212  def self.get_index(name) 
     213    name = name.to_sym 
    187214    raise IndexNotDefined.new(name) unless ferret_indexes.has_key?(name) 
    188215    ferret_indexes[name] 
     
    284311  # creates a new Index instance. 
    285312  def self.create_index_instance(definition) 
    286     (definition[:remote] ? RemoteIndex : LocalIndex).new(definition) 
     313    (remote? ? RemoteIndex : LocalIndex).new(definition) 
    287314  end 
    288315 
     
    313340  # returns a MultiIndex instance operating on a MultiReader 
    314341  def self.multi_index(indexes) 
    315     key = indexes.map{ |i| i.index_name.to_s }.sort.join(",") 
    316     ActsAsFerret::multi_indexes[key] ||= MultiIndex.new(indexes) 
     342    index_names = indexes.dup 
     343    index_names = index_names.map(&:to_s) if Symbol === index_names.first 
     344    if String === index_names.first 
     345      indexes = index_names.map{ |name| get_index name } 
     346    else 
     347      index_names = index_names.map{ |i| i.index_name.to_s } 
     348    end 
     349    key = index_names.sort.join(",") 
     350    ActsAsFerret::multi_indexes[key] ||= (remote? ? ActsAsFerret::RemoteMultiIndex : ActsAsFerret::MultiIndex).new(indexes) 
    317351  end 
    318352 
  • trunk/plugin/acts_as_ferret/lib/ferret_server.rb

    r318 r321  
    9797 
    9898      ################################################################################# 
    99       # handles all incoming method calls, and sends them on to the LocalIndex 
    100       # instance of the correct model class
     99      # handles all incoming method calls, and sends them on to the correct local index 
     100      # instance
    101101      # 
    102       # Calls are not queued atm, so this will block until the call returned. 
     102      # Calls are not queued, so this will block until the call returned. 
    103103      # 
    104104      def method_missing(name, *args) 
    105105        @logger.debug "\#method_missing(#{name.inspect}, #{args.inspect})" 
    106         retried = false 
    107         index_name = args.shift 
    108         index = ActsAsFerret::get_index(index_name) 
     106 
     107        index = if name.to_s =~ /^multi_(.+)/ 
     108          name = $1 
     109          index_names = args.shift 
     110          ActsAsFerret::multi_index(index_names) 
     111        else 
     112          index_name = args.shift 
     113          ActsAsFerret::get_index(index_name) 
     114        end 
    109115 
    110116        # TODO find another way to implement the reconnection logic (maybe in 
     
    130136      end 
    131137 
     138      def register_class(class_name) 
     139        @logger.debug "############ registerclass #{class_name}" 
     140        class_name.constantize 
     141        @logger.debug "index for class #{class_name}: #{ActsAsFerret::ferret_indexes[class_name.underscore.to_sym]}" 
     142 
     143      end 
     144 
    132145      # make sure we have a versioned index in place, building one if necessary 
    133146      def ensure_index_exists(index_name) 
    134147        @logger.debug "DRb server: ensure_index_exists for index #{index_name}" 
    135         definition = ActsAsFerret::index_definition(index_name) 
     148        definition = ActsAsFerret::get_index(index_name).index_definition 
    136149        dir = definition[:index_dir] 
    137150        unless File.directory?(dir) && File.file?(File.join(dir, 'segments')) && dir =~ %r{/\d+(_\d+)?$} 
  • trunk/plugin/acts_as_ferret/lib/multi_index.rb

    r320 r321  
    11module ActsAsFerret #:nodoc: 
     2 
     3  class MultiIndexBase 
     4    include FerretFindMethods 
     5    attr_accessor :logger 
     6 
     7    def initialize(indexes, options = {}) 
     8      # ensure all models indexes exist 
     9      @indexes = indexes 
     10      indexes.each { |i| i.ensure_index_exists } 
     11      default_fields = indexes.inject([]) do |fields, idx|  
     12        fields + [ idx.index_definition[:ferret][:default_field] ] 
     13      end.flatten.uniq 
     14      @options = { 
     15        :default_field => default_fields 
     16      }.update(options) 
     17      @logger = IndexLogger.new(ActsAsFerret::logger, "multi: #{indexes.map(&:index_name).join(',')}") 
     18    end 
     19 
     20    def ar_find(query, options = {}, ar_options = {}) 
     21      limit = options.delete(:limit) 
     22      offset = options.delete(:offset) || 0 
     23      options[:limit] = :all 
     24      total_hits, result = super query, options, ar_options   
     25      total_hits = result.size if ar_options[:conditions] 
     26      if limit && limit != :all 
     27        result = result[offset..limit+offset-1] 
     28      end 
     29      [total_hits, result] 
     30    end 
     31     
     32    def determine_stored_fields(options) 
     33      return nil unless options.has_key?(:lazy) 
     34      stored_fields = [] 
     35      @indexes.each do |index| 
     36        stored_fields += index.determine_stored_fields(options) 
     37      end 
     38      return stored_fields.uniq 
     39    end 
     40 
     41    def shared? 
     42      false 
     43    end 
     44       
     45  end 
    246   
    3       # This class can be used to search multiple physical indexes at once. 
    4       class MultiIndex 
    5         include FerretFindMethods 
    6         attr_accessor :logger 
    7          
    8         def initialize(indexes, options = {}) 
    9           # ensure all models indexes exist 
    10           @indexes = indexes 
    11           indexes.each { |i| i.ensure_index_exists } 
    12           default_fields = indexes.inject([]) do |fields, idx|  
    13             fields + [ idx.index_definition[:ferret][:default_field] ] 
    14           end.flatten.uniq 
    15           @options = { 
    16             :default_field => default_fields 
    17           }.update(options) 
    18           @logger = IndexLogger.new(ActsAsFerret::logger, "multi: #{indexes.map(&:index_name).join(',')}") 
     47  # This class can be used to search multiple physical indexes at once. 
     48  class MultiIndex < MultiIndexBase 
     49     
     50    def extract_stored_fields(doc, stored_fields) 
     51      ActsAsFerret::get_index_for(doc[:class_name]).extract_stored_fields(doc, stored_fields) unless stored_fields.blank? 
     52    end 
     53 
     54    def total_hits(q, options = {}) 
     55      search(q, options).total_hits 
     56    end 
     57     
     58    def search(query, options={}) 
     59      query = process_query(query) 
     60      logger.debug "parsed query: #{query.to_s}" 
     61      searcher.search(query, options) 
     62    end 
     63 
     64    def search_each(query, options = {}, &block) 
     65      query = process_query(query) 
     66      searcher.search_each(query, options, &block) 
     67    end 
     68 
     69    # checks if all our sub-searchers still are up to date 
     70    def latest? 
     71      #return false unless @reader 
     72      # segfaults with 0.10.4 --> TODO report as bug @reader.latest? 
     73      @reader and @reader.latest? 
     74      #@sub_readers.each do |r|  
     75      #  return false unless r.latest?  
     76      #end 
     77      #true 
     78    end 
     79 
     80    def searcher 
     81      ensure_searcher 
     82      @searcher 
     83    end 
     84     
     85    def doc(i) 
     86      searcher[i] 
     87    end 
     88    alias :[] :doc 
     89     
     90    def query_parser 
     91      @query_parser ||= Ferret::QueryParser.new(@options) 
     92    end 
     93     
     94    def process_query(query) 
     95      query = query_parser.parse(query) if query.is_a?(String) 
     96      return query 
     97    end 
     98 
     99    def close 
     100      @searcher.close if @searcher 
     101      @reader.close if @reader 
     102    end 
     103 
     104    protected 
     105 
     106      def ensure_searcher 
     107        unless latest? 
     108          @sub_readers = @indexes.map { |idx|  
     109            begin 
     110              reader = Ferret::Index::IndexReader.new(idx.index_definition[:index_dir]) 
     111              logger.debug "sub-reader opened: #{reader}" 
     112              reader 
     113            rescue Exception 
     114              raise "error opening reader on index for class #{clazz.inspect}: #{$!}" 
     115            end 
     116          } 
     117          close 
     118          @reader = Ferret::Index::IndexReader.new(@sub_readers) 
     119          @searcher = Ferret::Search::Searcher.new(@reader) 
    19120        end 
     121      end 
    20122 
    21         def ar_find(query, options = {}, ar_options = {}) 
    22           limit = options.delete(:limit) 
    23           offset = options.delete(:offset) || 0 
    24           options[:limit] = :all 
    25           total_hits, result = super query, options, ar_options   
    26           total_hits = result.size if ar_options[:conditions] 
    27           if limit && limit != :all 
    28             result = result[offset..limit+offset-1] 
    29           end 
    30           [total_hits, result] 
    31         end 
    32          
    33         def determine_stored_fields(options) 
    34           return nil unless options.has_key?(:lazy) 
    35           stored_fields = [] 
    36           @indexes.each do |index| 
    37             stored_fields += index.determine_stored_fields(options) 
    38           end 
    39           return stored_fields.uniq 
    40         end 
    41  
    42         def extract_stored_fields(doc, stored_fields) 
    43           ActsAsFerret::get_index_for(doc[:class_name]).extract_stored_fields(doc, stored_fields) unless stored_fields.blank? 
    44         end 
    45  
    46         def total_hits(q, options = {}) 
    47           search(q, options).total_hits 
    48         end 
    49          
    50         def search(query, options={}) 
    51           query = process_query(query) 
    52           logger.debug "parsed query: #{query.to_s}" 
    53           searcher.search(query, options) 
    54         end 
    55  
    56         def search_each(query, options = {}, &block) 
    57           query = process_query(query) 
    58           searcher.search_each(query, options, &block) 
    59         end 
    60  
    61         # checks if all our sub-searchers still are up to date 
    62         def latest? 
    63           #return false unless @reader 
    64           # segfaults with 0.10.4 --> TODO report as bug @reader.latest? 
    65           @reader and @reader.latest? 
    66           #@sub_readers.each do |r|  
    67           #  return false unless r.latest?  
    68           #end 
    69           #true 
    70         end 
    71  
    72         def shared? 
    73           false 
    74         end 
    75           
    76         def searcher 
    77           ensure_searcher 
    78           @searcher 
    79         end 
    80          
    81         def doc(i) 
    82           searcher[i] 
    83         end 
    84         alias :[] :doc 
    85          
    86         def query_parser 
    87           @query_parser ||= Ferret::QueryParser.new(@options) 
    88         end 
    89          
    90         def process_query(query) 
    91           query = query_parser.parse(query) if query.is_a?(String) 
    92           return query 
    93         end 
    94  
    95         def close 
    96           @searcher.close if @searcher 
    97           @reader.close if @reader 
    98         end 
    99  
    100         protected 
    101  
    102           def ensure_searcher 
    103             unless latest? 
    104               @sub_readers = @indexes.map { |idx|  
    105                 begin 
    106                   reader = Ferret::Index::IndexReader.new(idx.index_definition[:index_dir]) 
    107                   logger.debug "sub-reader opened: #{reader}" 
    108                   reader 
    109                 rescue Exception 
    110                   raise "error opening reader on index for class #{clazz.inspect}: #{$!}" 
    111                 end 
    112               } 
    113               close 
    114               @reader = Ferret::Index::IndexReader.new(@sub_readers) 
    115               @searcher = Ferret::Search::Searcher.new(@reader) 
    116             end 
    117           end 
    118  
    119       end # of class MultiIndex 
     123  end # of class MultiIndex 
    120124 
    121125end 
  • trunk/plugin/acts_as_ferret/lib/remote_index.rb

    r319 r321  
    55  # basically forwards all calls to the remote server. 
    66  class RemoteIndex < AbstractIndex 
     7    include RemoteFunctions 
    78 
    89    def initialize(config) 
    910      super 
    10       @server = DRbObject.new(nil, config[:remote]) 
     11      @server = DRbObject.new(nil, ActsAsFerret::remote) 
     12    end 
     13 
     14    # Cause model classes to be loaded (and indexes get declared) on the DRb 
     15    # side of things. 
     16    def register_class(clazz, options) 
     17      handle_drb_error { @server.register_class clazz.name } 
    1118    end 
    1219 
    1320    def method_missing(method_name, *args) 
    14       args.unshift model_class_name 
     21      args.unshift index_name 
    1522      handle_drb_error { @server.send(method_name, *args) } 
    1623    end 
     
    2128    }.each do |method_name, default_result| 
    2229      define_method method_name do |*args| 
    23         args.unshift model_class_name 
     30        args.unshift index_name 
    2431        handle_drb_error(default_result) { @server.send method_name, *args } 
    2532      end 
     
    2734 
    2835    def find_ids(q, options = {}, &proc) 
    29       total_hits, results = handle_drb_error([0, []]) { @server.find_ids(model_class_name, q, options) } 
    30       block_given? ? yield_results(total_hits, results, &proc) : [ total_hits, results ] 
    31     end 
    32  
    33     def id_multi_search(query, models, options, &proc) 
    34       total_hits, results = handle_drb_error([0, []]) { @server.id_multi_search(model_class_name, query, models, options) } 
     36      total_hits, results = handle_drb_error([0, []]) { @server.find_ids(index_name, q, options) } 
    3537      block_given? ? yield_results(total_hits, results, &proc) : [ total_hits, results ] 
    3638    end 
     
    3840    # add record to index 
    3941    def add(record) 
    40       handle_drb_error { @server.add record.class.name, record.to_doc } 
     42      handle_drb_error { @server.add index_name, record.to_doc } 
    4143    end 
    4244    alias << add 
     
    4446    private 
    4547 
    46     def handle_drb_error(return_value_in_case_of_error = false) 
    47       yield 
    48     rescue DRb::DRbConnError => e 
    49       logger.error "DRb connection error: #{e}" 
    50       logger.warn e.backtrace.join("\n") 
    51       raise e if index_definition[:raise_drb_errors] 
    52       return_value_in_case_of_error 
    53     end 
    54  
    55     def yield_results(total_hits, results) 
    56       results.each do |result| 
    57         yield result[:model], result[:id], result[:score], result[:data] 
    58       end 
    59       total_hits 
    60     end 
    61  
    62     def model_class_name 
    63       index_definition[:class_name] 
    64     end 
     48    #def model_class_name 
     49    #  index_definition[:class_name] 
     50    #end 
    6551 
    6652  end 

To edit pages or tickets please login with username/password: aaf/aaf