]> git.openstreetmap.org Git - rails.git/blobdiff - app/controllers/amf_controller.rb
use render proc to write out results, see if that makes things faster
[rails.git] / app / controllers / amf_controller.rb
index c5a7c30ead5ac5f56559e51a8c3ef59b49405660..72f1dd74eb9bed75047aa2beacdf6c2cb90baaaf 100644 (file)
@@ -33,25 +33,31 @@ class AmfController < ApplicationController
       bytes=getlong(req)                               #  | get total size in bytes
       args=getvalue(req)                               #  | get response (probably an array)
 
+      RAILS_DEFAULT_LOGGER.info("  Message: #{message}")
+
       case message
-      when 'getpresets';       results[index]=putdata(index,getpresets)
-      when 'whichways';                results[index]=putdata(index,whichways(args))
-      when 'getway';           results[index]=putdata(index,getway(args))
-      when 'putway';           results[index]=putdata(index,putway(args))
-      when 'deleteway';                results[index]=putdata(index,deleteway(args))
+                 when 'getpresets';    results[index]=putdata(index,getpresets)
+                 when 'whichways';             results[index]=putdata(index,whichways(args))
+                 when 'getway';                results[index]=putdata(index,getway(args))
+                 when 'putway';                results[index]=putdata(index,putway(args))
+                 when 'deleteway';             results[index]=putdata(index,deleteway(args))
       end
     end
 
     # ------------------
     # Write out response
 
+    RAILS_DEFAULT_LOGGER.info("  Response: start")
     response.headers["Content-Type"]="application/x-amf"
     a,b=results.length.divmod(256)
-    ans=0.chr+0.chr+0.chr+0.chr+a.chr+b.chr
-    results.each do |k,v|
-      ans+=v
-    end
-    render :text => ans
+       render :text => proc { |response, output| 
+        output.write 0.chr+0.chr+0.chr+0.chr+a.chr+b.chr
+               results.each do |k,v|
+                 RAILS_DEFAULT_LOGGER.info("  Response: encode #{k}")
+                 output.write(v)
+               end
+       }
+    RAILS_DEFAULT_LOGGER.info("  Response: end")
 
   end
 
@@ -70,6 +76,8 @@ class AmfController < ApplicationController
     presettype=''
     presetcategory=''
 
+    RAILS_DEFAULT_LOGGER.info("  Message: getpresets")
+
     #          File.open("config/potlatch/presets.txt") do |file|
 
     # Temporary patch to get around filepath problem
@@ -168,6 +176,13 @@ EOF
   #            corner-crossing ways, it simply enlarges the bounding box by +/- 0.01
 
   def whichways(args)
+    xmin = args[0].to_f-0.01
+    ymin = args[1].to_f-0.01
+    xmax = args[2].to_f+0.01
+    ymax = args[3].to_f+0.01
+
+    RAILS_DEFAULT_LOGGER.info("  Message: whichways, bbox=#{xmin},#{ymin},#{xmax},#{ymax}")
+
     waylist=WaySegment.find_by_sql("SELECT DISTINCT current_way_segments.id AS wayid"+
        "  FROM current_way_segments,current_segments,current_nodes,current_ways "+
        " WHERE segment_id=current_segments.id "+
@@ -175,8 +190,8 @@ EOF
        "   AND node_a=current_nodes.id "+
           "   AND current_ways.id=current_way_segments.id "+
           "   AND current_ways.visible=1 "+
-       "   AND (latitude  BETWEEN "+(args[1].to_f-0.01).to_s+" AND "+(args[3].to_f+0.01).to_s+") "+
-       "   AND (longitude BETWEEN "+(args[0].to_f-0.01).to_s+" AND "+(args[2].to_f+0.01).to_s+")")
+       "   AND (latitude  BETWEEN "+ymin.to_s+" AND "+ymax.to_s+") "+
+       "   AND (longitude BETWEEN "+xmin.to_s+" AND "+xmax.to_s+")")
 
        ways = waylist.collect {|a| a.wayid.to_i } # get an array of way id's
 
@@ -184,8 +199,8 @@ EOF
        "  FROM current_nodes "+
        "  LEFT OUTER JOIN current_segments cs1 ON cs1.node_a=current_nodes.id "+
        "  LEFT OUTER JOIN current_segments cs2 ON cs2.node_b=current_nodes.id "+
-       " WHERE (latitude  BETWEEN "+(args[1].to_f-0.01).to_s+" AND "+(args[3].to_f+0.01).to_s+") "+
-       "   AND (longitude BETWEEN "+(args[0].to_f-0.01).to_s+" AND "+(args[2].to_f-0.01).to_s+") "+
+       " WHERE (latitude  BETWEEN "+ymin.to_s+" AND "+ymax.to_s+") "+
+       "   AND (longitude BETWEEN "+xmin.to_s+" AND "+xmax.to_s+") "+
        "   AND cs1.id IS NULL AND cs2.id IS NULL "+
        "   AND current_nodes.visible=1")
 
@@ -206,6 +221,8 @@ EOF
     xmin = ymin = 999999
     xmax = ymax = -999999
 
+    RAILS_DEFAULT_LOGGER.info("  Message: getway, id=#{wayid}")
+
     readwayquery(wayid).each {|row|
       xs1=long2coord(row['long1'].to_f,baselong,masterscale); ys1=lat2coord(row['lat1'].to_f,basey,masterscale)
       xs2=long2coord(row['long2'].to_f,baselong,masterscale); ys2=lat2coord(row['lat2'].to_f,basey,masterscale)
@@ -240,6 +257,8 @@ EOF
     ActiveRecord::Base.connection.execute("SET #{db_now}=NOW()")
     originalway=originalway.to_i
 
+    RAILS_DEFAULT_LOGGER.info("  Message: putway, id=#{originalway}")
+
     # -- 3.    read original way into memory
 
     xc={}; yc={}; tagc={}; seg={}
@@ -263,7 +282,7 @@ EOF
 
     xmin = ymin = 999999
     xmax = ymax = -999999
-    insertsql = nodelist =  ''
+    insertsql = ''
     renumberednodes={}
 
     points.each_index do |i|
@@ -288,24 +307,18 @@ EOF
         if (xs!=xc[node] or (ys/0.0000001).round!=(yc[node]/0.0000001).round or tagstr!=tagc[node])
           ActiveRecord::Base.connection.insert("INSERT INTO nodes (id,latitude,longitude,timestamp,user_id,visible,tags) VALUES (#{node},#{ys},#{xs},#{db_now},#{uid},1,#{tagsql})")
           ActiveRecord::Base.connection.update("UPDATE current_nodes SET latitude=#{ys},longitude=#{xs},timestamp=#{db_now},user_id=#{uid},tags=#{tagsql},visible=1 WHERE id=#{node}")
-        else
-          if (nodelist!='') then nodelist+=',' end; nodelist+=node.to_s
         end
       else
         # old node, created in another way and now added to this way
-        if (nodelist!='') then nodelist+=',' end; nodelist+=node.to_s
       end
 
     end
 
-    if nodelist!='' then
-      ActiveRecord::Base.connection.update("UPDATE current_nodes SET timestamp=#{db_now},user_id=#{uid},visible=1 WHERE id IN (#{nodelist})")
-    end
 
     # -- 6.i compare segments
 
     numberedsegments={}
-    seglist=''
+    seglist=''                         # list of existing segments that we want to keep
     for i in (0..(points.length-2))
       if (points[i+1][3].to_i==0) then next end
       segid=points[i+1][5].to_i
@@ -324,14 +337,10 @@ EOF
     end
     # numberedsegments.each{|a,b| RAILS_DEFAULT_LOGGER.error("Sending back: seg no. #{a} -> id #{b}") }
 
-    if seglist!='' then
-      ActiveRecord::Base.connection.update("UPDATE current_segments SET timestamp=#{db_now},user_id=#{uid},visible=1 WHERE id IN (#{seglist})")
-    end
-
 
     # -- 6.ii insert new way segments
 
-    createuniquesegments(way,db_uqs)
+    createuniquesegments(way,db_uqs,seglist)   # segments which appear in this way but no other
 
     #          delete segments from uniquesegments (and not in modified way)
 
@@ -340,7 +349,6 @@ EOF
       SELECT DISTINCT segment_id,node_a,node_b,#{db_now},#{uid},0
         FROM current_segments AS cs, #{db_uqs} AS us
        WHERE cs.id=us.segment_id AND cs.visible=1 
-         AND (cs.timestamp!=#{db_now} OR cs.user_id!=#{uid})
     EOF
     ActiveRecord::Base.connection.insert(sql)
 
@@ -348,13 +356,12 @@ EOF
          UPDATE current_segments AS cs, #{db_uqs} AS us
           SET cs.timestamp=#{db_now},cs.visible=0,cs.user_id=#{uid} 
         WHERE cs.id=us.segment_id AND cs.visible=1 
-          AND (cs.timestamp!=#{db_now} OR cs.user_id!=#{uid})
     EOF
     ActiveRecord::Base.connection.update(sql)
 
     #          delete nodes not in modified way or any other segments
 
-    createuniquenodes(db_uqs,db_uqn)
+    createuniquenodes(db_uqs,db_uqn)   # nodes which appear in this way but no other
 
     sql=<<-EOF
                INSERT INTO nodes (id,latitude,longitude,timestamp,user_id,visible)  
@@ -401,7 +408,7 @@ EOF
       if v[0,6]=='(type ' then next end
       if insertsql !='' then insertsql +=',' end
       if currentsql!='' then currentsql+=',' end
-      insertsql +="(#{way},'"+sqlescape(k)+"','"+sqlescape(v)+"',version)"
+      insertsql +="(#{way},'"+sqlescape(k)+"','"+sqlescape(v)+"',#{version})"
       currentsql+="(#{way},'"+sqlescape(k)+"','"+sqlescape(v)+"')"
     end
 
@@ -417,6 +424,9 @@ EOF
 
   def deleteway(args)
     usertoken,way=args
+
+    RAILS_DEFAULT_LOGGER.info("  Message: deleteway, id=#{way}")
+
     uid=getuserid(usertoken); if !uid then return end
        way=way.to_i
 
@@ -424,7 +434,7 @@ EOF
        db_uqn='unin'+uid.to_s+way.to_i.abs.to_s+Time.new.to_i.to_s     # temp uniquenodes table name, typically 51 chars
        db_now='@now'+uid.to_s+way.to_i.abs.to_s+Time.new.to_i.to_s     # 'now' variable name, typically 51 chars
        ActiveRecord::Base.connection.execute("SET #{db_now}=NOW()")
-       createuniquesegments(way,db_uqs)
+       createuniquesegments(way,db_uqs,'')
 
        # -     delete any otherwise unused segments
 
@@ -490,8 +500,8 @@ def readwayquery(id)
       "   ORDER BY sequence_id"
 end
 
-def createuniquesegments(way,uqs_name)
-  # Finds segments which appear in this way and no other
+def createuniquesegments(way,uqs_name,seglist)
+  # Finds segments which appear in (previous version of) this way and no other
   sql=<<-EOF
       CREATE TEMPORARY TABLE #{uqs_name}
               SELECT a.segment_id
@@ -502,6 +512,7 @@ def createuniquesegments(way,uqs_name)
                  AND b.id != #{way}
                WHERE b.segment_id IS NULL
     EOF
+  if (seglist!='') then sql+=" AND a.segment_id NOT IN (#{seglist})" end
   ActiveRecord::Base.connection.execute(sql)
 end
 
@@ -555,9 +566,9 @@ end
 def getuserid(token)
   token=sqlescape(token)
   if (token=~/^(.+)\+(.+)$/) then
-    return ActiveRecord::Base.connection.select_value("SELECT id FROM users WHERE active=1 AND timeout>NOW() AND email='#{$1}' AND pass_crypt=MD5('#{$2}')")
+    return ActiveRecord::Base.connection.select_value("SELECT id FROM users WHERE active=1 AND email='#{$1}' AND pass_crypt=MD5('#{$2}')")
   else
-    return ActiveRecord::Base.connection.select_value("SELECT id FROM users WHERE active=1 AND timeout>NOW() AND token='#{token}'")
+    return ActiveRecord::Base.connection.select_value("SELECT id FROM users WHERE active=1 AND token='#{token}'")
   end
 end