require "focuslight" require "focuslight/config" require "focuslight/logger" require "focuslight/graph" require "sequel" class Focuslight::Data include Focuslight::Logger def initialize @db = Sequel.connect(Focuslight::Config.get(:dburl), logger: Focuslight.logger, timeout: Focuslight::Config.get(:dbtimeout)) @datadir = Focuslight::Config.get(:datadir) @floatings = Focuslight::Config.get(:float_support) == "y" if @db.database_type == :sqlite @db.run 'PRAGMA journal_mode = WAL' @db.run 'PRAGMA synchronous = NORMAL' end @graphs = @db.from(:graphs) @complex_graphs = @db.from(:complex_graphs) end def number_type @floatings ? Float : :Bignum end def create_tables ntype = number_type @db.transaction do @db.create_table :graphs do primary_key :id, Integer # Notice that SQLite actually creates integer primary key column :service_name, String, null: false column :section_name, String, null: false column :graph_name, String, null: false column :number, ntype, default: 0 column :mode, String, default: "gauge", null: false column :description, String, default: "", null: false column :sort, Integer, default: 0, null: false column :color, String, default: "#00CC00", null: false column :ulimit, ntype, default: 1000_0000_0000_0000, null: false column :llimit, ntype, default: 0, null: false column :type, String, default: "AREA", null: false String :meta, text: true column :created_at, Integer, null: false column :updated_at, Integer, null: false unique [:service_name, :section_name, :graph_name] end @db.create_table :complex_graphs do primary_key :id, Integer # Notice that SQLite actually creates integer primary key column :service_name, String, null: false column :section_name, String, null: false column :graph_name, String, null: false column :number, ntype, default: 0 column :description, String, default: "", null: false column :sort, Integer, default: 0, null: false String :meta, text: true column :created_at, Integer, null: false column :updated_at, Integer, null: false unique [:service_name, :section_name, :graph_name] end end end def execute(*args) @db.run(*args) end def transaction @db.transaction do yield @db end end def get(service, section, graph) data = @graphs.where(service_name: service, section_name: section, graph_name: graph).first data && Focuslight::Graph.concrete(data) end def get_by_id(id) data = @graphs[id: id] data && Focuslight::Graph.concrete(data) end def get_by_id_for_rrdupdate(id, target=:normal) # get_by_id_for_rrdupdate_short == get_by_id_for_rrdupdate(id, :short) data = @graphs[id: id] return nil unless data graph = Focuslight::Graph.concrete(data) end def update(service_name, section_name, graph_name, number, mode, color) data = nil @db.transaction do data = @graphs.where(service_name: service_name, section_name: section_name, graph_name: graph_name).first if data graph = Focuslight::Graph.concrete(data) if mode == 'count' number += graph.number end if mode != 'modified' || (mode == 'modified' && graph.number != number) color = graph.color if color.empty? @graphs.where(id: graph.id).update(number: number, mode: mode, color: color, updated_at: Time.now.to_i) end else color = '#' + ['33', '66', '99', 'cc'].shuffle.slice(0,3).join if color.empty? # COLUMNS = %w(service_name section_name graph_name number mode color llimit created_at updated_at) columns = Focuslight::SimpleGraph::COLUMNS.join(',') # PLACEHOLDERS = COLUMNS.map{|c| '?'} placeholders = Focuslight::SimpleGraph::PLACEHOLDERS.join(',') current_time = Time.now.to_i @graphs.insert( service_name: service_name, section_name: section_name, graph_name: graph_name, number: number, mode: mode, color: color, llimit: -1000000000, created_at: current_time, updated_at: current_time) end data = @graphs.where(service_name: service_name, section_name: section_name, graph_name: graph_name).first end # transaction Focuslight::Graph.concrete(data) end def update_graph(id, args) graph = get_by_id(id) return nil unless graph graph.update(args) @graphs.where(id: graph.id) .update( service_name: graph.service, section_name: graph.section, graph_name: graph.graph, description: graph.description, sort: graph.sort, color: graph.color, type: graph.type, llimit: graph.llimit, ulimit: graph.ulimit, meta: graph.meta ) true end def update_graph_description(id, description) @graphs.where(id: id).update(description: description) true end def get_services rows1 = @graphs.order(:service_name).all rows2 = @complex_graphs.order(:service_name).all (rows1 + rows2).map{|row| row[:service_name]}.uniq.sort end def get_sections(service) rows1 = @graphs.select(:section_name).order(:section_name).where(service_name: service).all rows2 = @complex_graphs.select(:section_name).order(:section_name).where(service_name: service).all (rows1 + rows2).map{|row| row[:section_name]}.uniq.sort end def get_graphs(service, section) rows1 = @graphs.order(Sequel.desc(:sort)).where(service_name: service, section_name: section).all rows2 = @complex_graphs.order(Sequel.desc(:sort)).where(service_name: service, section_name: section).all (rows1 + rows2).map{|row| Focuslight::Graph.concrete(row)}.sort{|a,b| b.sort <=> a.sort} end def get_all_graph_id @graphs.select(:id).all end def get_all_graph_name @graphs.select(:id, :service_name, :section_name, :graph_name).reverse_order(:service_name, :section_name, :graph_name).all end def get_all_graph_all rows = @graphs.reverse_order(:service_name, :section_name, :graph_name).all rows.map{|row| Focuslight::Graph.concrete(row)} end def remove(id) @db.transaction do @graphs.where(id: id).delete end end def get_complex(service, section, graph) data = @complex_graphs.where(service_name: service, section_name: section, graph_name: graph).first data && Focuslight::Graph.concrete(data) end def get_complex_by_id(id) data = @complex_graphs.where(id: id).first data && Focuslight::Graph.concrete(data) end def create_complex(service, section, graph, args) description = args[:description] sort = args[:sort] meta = Focuslight::ComplexGraph.meta_clean(args).to_json now = Time.now.to_i @complex_graphs.insert( service_name: service, section_name: section, graph_name: graph, description: description, sort: sort.to_i, meta: meta, created_at: now, updated_at: now, ) get_complex(service, section, graph) end def update_complex(id, args) graph = get_complex_by_id(id) return nil unless graph graph.update(args) @complex_graphs.where(id: graph.id) .update( service_name: graph.service, section_name: graph.section, graph_name: graph.graph, description: graph.description, sort: graph.sort, meta: graph.meta, updated_at: Time.now.to_i, ) get_complex_by_id(id) end def remove_complex(id) @complex_graphs.where(id: id).delete end def get_all_complex_graph_id @complex_graphs.select(:id).all end def get_all_complex_graph_name @complex_graphs.select(:id, :service_name, :section_name, :graph_name).reverse_order(:service_name, :section_name, :graph_name).all end def get_all_complex_graph_all rows = @complex_graphs.reverse_order(:service_name, :section_name, :graph_name) return [] unless rows rows.map{|row| Focuslight::Graph.concrete(row)} end end