evesync 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/LICENSE +25 -0
 - data/Rakefile +83 -0
 - data/bin/evedatad +34 -0
 - data/bin/evehand +36 -0
 - data/bin/evemond +42 -0
 - data/bin/evesync +164 -0
 - data/bin/evesyncd +44 -0
 - data/bin/start +16 -0
 - data/config/example.conf +58 -0
 - data/lib/evesync/config.rb +63 -0
 - data/lib/evesync/constants.rb +17 -0
 - data/lib/evesync/database.rb +107 -0
 - data/lib/evesync/discover.rb +77 -0
 - data/lib/evesync/err.rb +25 -0
 - data/lib/evesync/handler/file.rb +28 -0
 - data/lib/evesync/handler/package.rb +30 -0
 - data/lib/evesync/handler.rb +89 -0
 - data/lib/evesync/ipc/client.rb +37 -0
 - data/lib/evesync/ipc/data/file.rb +64 -0
 - data/lib/evesync/ipc/data/hashable.rb +74 -0
 - data/lib/evesync/ipc/data/ignore.rb +22 -0
 - data/lib/evesync/ipc/data/package.rb +58 -0
 - data/lib/evesync/ipc/data/utils.rb +14 -0
 - data/lib/evesync/ipc/data.rb +50 -0
 - data/lib/evesync/ipc/ipc.rb +42 -0
 - data/lib/evesync/ipc/server.rb +56 -0
 - data/lib/evesync/log.rb +66 -0
 - data/lib/evesync/ntp.rb +16 -0
 - data/lib/evesync/os/linux/arch/package_manager.rb +29 -0
 - data/lib/evesync/os/linux/arch/package_watcher.rb +59 -0
 - data/lib/evesync/os/linux/arch.rb +2 -0
 - data/lib/evesync/os/linux/base_package_manager.rb +80 -0
 - data/lib/evesync/os/linux/deb/dpkg.rb +30 -0
 - data/lib/evesync/os/linux/deb/package_manager.rb +38 -0
 - data/lib/evesync/os/linux/deb/package_watcher.rb +32 -0
 - data/lib/evesync/os/linux/deb.rb +2 -0
 - data/lib/evesync/os/linux/rhel/package_manager.rb +42 -0
 - data/lib/evesync/os/linux/rhel/package_watcher.rb +32 -0
 - data/lib/evesync/os/linux/rhel/rpm.rb +41 -0
 - data/lib/evesync/os/linux/rhel.rb +3 -0
 - data/lib/evesync/os/linux.rb +9 -0
 - data/lib/evesync/os.rb +2 -0
 - data/lib/evesync/sync.rb +209 -0
 - data/lib/evesync/trigger/base.rb +56 -0
 - data/lib/evesync/trigger/file.rb +20 -0
 - data/lib/evesync/trigger/package.rb +20 -0
 - data/lib/evesync/trigger.rb +106 -0
 - data/lib/evesync/utils.rb +51 -0
 - data/lib/evesync/watcher/file.rb +156 -0
 - data/lib/evesync/watcher/interface.rb +21 -0
 - data/lib/evesync/watcher/package.rb +8 -0
 - data/lib/evesync/watcher.rb +68 -0
 - data/lib/evesync.rb +3 -0
 - metadata +198 -0
 
    
        checksums.yaml
    ADDED
    
    | 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ---
         
     | 
| 
      
 2 
     | 
    
         
            +
            SHA256:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 9a1973a7b7ed425602bbb593496479cfb6ce24e57d5f490ee2d54c52e76375cb
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: a593092487578200014b495d75a77c20a9798525d00fe9e9ab94ed26b4eba8fd
         
     | 
| 
      
 5 
     | 
    
         
            +
            SHA512:
         
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: b06baf168fac9f60cc20995b586712b1de0cf1f13ab32be858d916686d4a770ea67eba82f9b0967bee7b6cc1d664f788d5c4717489320d224a1f2e724ac1ad4c
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 7178b8ffc3f5a120438ffd5a0ea1a61fbb3c1a2b9b4b55a90242fadd5b2abcc61379af372bd1575551076b59583d3472faab46214f4c9b3c5687cacf83cfd424
         
     | 
    
        data/LICENSE
    ADDED
    
    | 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            BSD 2-Clause License
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Copyright (c) 2018, Valentine Kiselev
         
     | 
| 
      
 4 
     | 
    
         
            +
            All rights reserved.
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            Redistribution and use in source and binary forms, with or without
         
     | 
| 
      
 7 
     | 
    
         
            +
            modification, are permitted provided that the following conditions are met:
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            * Redistributions of source code must retain the above copyright notice, this
         
     | 
| 
      
 10 
     | 
    
         
            +
              list of conditions and the following disclaimer.
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            * Redistributions in binary form must reproduce the above copyright notice,
         
     | 
| 
      
 13 
     | 
    
         
            +
              this list of conditions and the following disclaimer in the documentation
         
     | 
| 
      
 14 
     | 
    
         
            +
              and/or other materials provided with the distribution.
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
         
     | 
| 
      
 17 
     | 
    
         
            +
            AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
         
     | 
| 
      
 18 
     | 
    
         
            +
            IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
         
     | 
| 
      
 19 
     | 
    
         
            +
            DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
         
     | 
| 
      
 20 
     | 
    
         
            +
            FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
         
     | 
| 
      
 21 
     | 
    
         
            +
            DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
         
     | 
| 
      
 22 
     | 
    
         
            +
            SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
         
     | 
| 
      
 23 
     | 
    
         
            +
            CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
         
     | 
| 
      
 24 
     | 
    
         
            +
            OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
         
     | 
| 
      
 25 
     | 
    
         
            +
            OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
         
     | 
    
        data/Rakefile
    ADDED
    
    | 
         @@ -0,0 +1,83 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'rspec/core/rake_task'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'find'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'mkmf'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require_relative 'lib/evesync'
         
     | 
| 
      
 5 
     | 
    
         
            +
            VERSION = Evesync::VERSION
         
     | 
| 
      
 6 
     | 
    
         
            +
            GEMSPEC = 'evesync.gemspec'.freeze
         
     | 
| 
      
 7 
     | 
    
         
            +
            GEMFILE = "evesync-#{VERSION}.gem".freeze
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            task default: %i[lint build]
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            task :lint do
         
     | 
| 
      
 12 
     | 
    
         
            +
              sh 'rubocop -l lib' if find_executable 'rubocop'
         
     | 
| 
      
 13 
     | 
    
         
            +
            end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            task :rdoc do
         
     | 
| 
      
 16 
     | 
    
         
            +
              sh 'rdoc --ri'
         
     | 
| 
      
 17 
     | 
    
         
            +
              sh 'rdoc'
         
     | 
| 
      
 18 
     | 
    
         
            +
            end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            task install: [GEMFILE] do
         
     | 
| 
      
 21 
     | 
    
         
            +
              sh "gem install --local #{GEMFILE}"
         
     | 
| 
      
 22 
     | 
    
         
            +
            end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            task build: GEMFILE
         
     | 
| 
      
 25 
     | 
    
         
            +
            file GEMFILE do
         
     | 
| 
      
 26 
     | 
    
         
            +
              sh "gem build #{GEMSPEC}"
         
     | 
| 
      
 27 
     | 
    
         
            +
            end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            RSpec::Core::RakeTask.new(:spec)
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
            task test: :spec
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            task :clean, [:remove_rpm] do |_t, args|
         
     | 
| 
      
 34 
     | 
    
         
            +
              args.with_defaults(:remove_rpm => 1)
         
     | 
| 
      
 35 
     | 
    
         
            +
              rm_rf('tmp')
         
     | 
| 
      
 36 
     | 
    
         
            +
              rm_rf('doc')
         
     | 
| 
      
 37 
     | 
    
         
            +
              rm_rf('mkmf.log')
         
     | 
| 
      
 38 
     | 
    
         
            +
              rm_rf(Dir['*.zip'])
         
     | 
| 
      
 39 
     | 
    
         
            +
              rm_rf('RPM') if args[:remove_rpm] == 1
         
     | 
| 
      
 40 
     | 
    
         
            +
              rm_rf("evesync-#{VERSION}")
         
     | 
| 
      
 41 
     | 
    
         
            +
              rm_rf(GEMFILE)
         
     | 
| 
      
 42 
     | 
    
         
            +
            end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
            task todos: :todo
         
     | 
| 
      
 45 
     | 
    
         
            +
            task :todo do
         
     | 
| 
      
 46 
     | 
    
         
            +
              puts "==== \033[0;31mTODOs\033[0m in code"
         
     | 
| 
      
 47 
     | 
    
         
            +
              puts `find bin lib dockerfiles -type f -exec grep --color=always TODO   \{} \+ ||:`
         
     | 
| 
      
 48 
     | 
    
         
            +
              puts "==== \033[0;31mFIXMEs\033[0m in code"
         
     | 
| 
      
 49 
     | 
    
         
            +
              puts `find bin lib dockerfiles -type f -exec grep --color=always FIXME  \{} \+ ||:`
         
     | 
| 
      
 50 
     | 
    
         
            +
            end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
            task :lines do
         
     | 
| 
      
 53 
     | 
    
         
            +
              sh 'find . -name "*.rb" -exec grep -v -E "^\s*#|^\s*$" \{} \+ | wc -l'
         
     | 
| 
      
 54 
     | 
    
         
            +
            end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
            ## Docker related targets
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
            task :docker do
         
     | 
| 
      
 59 
     | 
    
         
            +
              sh 'docker-compose build'
         
     | 
| 
      
 60 
     | 
    
         
            +
            end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
            task :up do
         
     | 
| 
      
 63 
     | 
    
         
            +
              sh 'docker-compose up -d'
         
     | 
| 
      
 64 
     | 
    
         
            +
            end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
            task :down do
         
     | 
| 
      
 67 
     | 
    
         
            +
              sh 'docker-compose stop || docker-compose kill ||:'
         
     | 
| 
      
 68 
     | 
    
         
            +
              sh 'docker-compose rm --force ||:'
         
     | 
| 
      
 69 
     | 
    
         
            +
            end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
            task :rpm do
         
     | 
| 
      
 72 
     | 
    
         
            +
              sh("rpmbuild -bb "\
         
     | 
| 
      
 73 
     | 
    
         
            +
                 "--define 'VERSION #{VERSION}' "\
         
     | 
| 
      
 74 
     | 
    
         
            +
                 "--define 'RELEASE `git rev-list HEAD master --count`' "\
         
     | 
| 
      
 75 
     | 
    
         
            +
                 "--define '_builddir #{Dir.pwd}' "\
         
     | 
| 
      
 76 
     | 
    
         
            +
                 "--define '_rpmdir #{Dir.pwd}/RPM/' "\
         
     | 
| 
      
 77 
     | 
    
         
            +
                 "evesync.spec")
         
     | 
| 
      
 78 
     | 
    
         
            +
              sh('chown -R 1000:1000 RPM')
         
     | 
| 
      
 79 
     | 
    
         
            +
            end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
            task :'build-rpm' do
         
     | 
| 
      
 82 
     | 
    
         
            +
              sh('echo rake rpm | docker-compose run build-centos')
         
     | 
| 
      
 83 
     | 
    
         
            +
            end
         
     | 
    
        data/bin/evedatad
    ADDED
    
    | 
         @@ -0,0 +1,34 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
            # -*- mode: ruby -*-
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require 'evesync/ipc/server'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'evesync/log'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'evesync/database'
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            Evesync::Log.info('Database daemon starting...')
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            database = Evesync::Database.new
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            # Creating an IPC server to accept data
         
     | 
| 
      
 13 
     | 
    
         
            +
            data_server = Evesync::IPC::Server.new(
         
     | 
| 
      
 14 
     | 
    
         
            +
              port: :evedatad,
         
     | 
| 
      
 15 
     | 
    
         
            +
              proxy: database
         
     | 
| 
      
 16 
     | 
    
         
            +
            ).start
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            Signal.trap('TERM') do
         
     | 
| 
      
 19 
     | 
    
         
            +
              data_server.stop
         
     | 
| 
      
 20 
     | 
    
         
            +
              exit(0)
         
     | 
| 
      
 21 
     | 
    
         
            +
            end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            Evesync::Log.info('Database daemon started!')
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            begin
         
     | 
| 
      
 26 
     | 
    
         
            +
              loop do
         
     | 
| 
      
 27 
     | 
    
         
            +
                sleep 3600 # FIXME: 1 hour, rewrite better
         
     | 
| 
      
 28 
     | 
    
         
            +
                # zip db if needed, save backup
         
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
            rescue SignalException => e
         
     | 
| 
      
 31 
     | 
    
         
            +
              data_server.stop
         
     | 
| 
      
 32 
     | 
    
         
            +
              Evesync::Log.warn("Database daemon received signal: #{e.signm}(#{e.signo})")
         
     | 
| 
      
 33 
     | 
    
         
            +
              exit(0)
         
     | 
| 
      
 34 
     | 
    
         
            +
            end
         
     | 
    
        data/bin/evehand
    ADDED
    
    | 
         @@ -0,0 +1,36 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
            # -*- mode: ruby -*-
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require 'evesync/log'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'evesync/ipc/server'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'evesync/handler'
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            Evesync::Log.info('Handle daemon starting...')
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            all_handler = Evesync::Handler.new
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            handler_server = Evesync::IPC::Server.new(
         
     | 
| 
      
 13 
     | 
    
         
            +
              port: :evehand,
         
     | 
| 
      
 14 
     | 
    
         
            +
              proxy: all_handler,
         
     | 
| 
      
 15 
     | 
    
         
            +
              ip: '*' # accept remote requests
         
     | 
| 
      
 16 
     | 
    
         
            +
            ).start
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            Evesync::Log.info('Handle daemon started!')
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            # Signal handling
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            Signal.trap('TERM') do
         
     | 
| 
      
 23 
     | 
    
         
            +
              handler_server.stop
         
     | 
| 
      
 24 
     | 
    
         
            +
              exit(0)
         
     | 
| 
      
 25 
     | 
    
         
            +
            end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            begin
         
     | 
| 
      
 28 
     | 
    
         
            +
              loop do
         
     | 
| 
      
 29 
     | 
    
         
            +
                sleep 3600 # FIXME: 1 hour, rewrite better
         
     | 
| 
      
 30 
     | 
    
         
            +
                # FIXME: know what to do
         
     | 
| 
      
 31 
     | 
    
         
            +
              end
         
     | 
| 
      
 32 
     | 
    
         
            +
            rescue SignalException => e
         
     | 
| 
      
 33 
     | 
    
         
            +
              handler_server.stop
         
     | 
| 
      
 34 
     | 
    
         
            +
              Evesync::Log.warn("Received signal: #{e.signm}(#{e.signo})")
         
     | 
| 
      
 35 
     | 
    
         
            +
              exit(0)
         
     | 
| 
      
 36 
     | 
    
         
            +
            end
         
     | 
    
        data/bin/evemond
    ADDED
    
    | 
         @@ -0,0 +1,42 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
            # -*- mode: ruby -*-
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require 'evesync/log'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'evesync/ipc/server'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'evesync/trigger'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'evesync/watcher'
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            Evesync::Log.info 'Monitoring daemon starting...'
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            queue = Queue.new
         
     | 
| 
      
 12 
     | 
    
         
            +
            trigger = Evesync::Trigger.new(queue)
         
     | 
| 
      
 13 
     | 
    
         
            +
            watcher = Evesync::Watcher.new(queue)
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            [trigger, watcher].each(&:start)
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            evesync_server = Evesync::IPC::Server.new(
         
     | 
| 
      
 18 
     | 
    
         
            +
              port: :evemond,
         
     | 
| 
      
 19 
     | 
    
         
            +
              proxy: trigger
         
     | 
| 
      
 20 
     | 
    
         
            +
            ).start
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            Evesync::Log.info 'Monitoring daemon started!'
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            # Signal handling
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
            Signal.trap('SIGINT') do
         
     | 
| 
      
 27 
     | 
    
         
            +
              [watcher, trigger].each(&:stop)
         
     | 
| 
      
 28 
     | 
    
         
            +
              evesync_server.stop
         
     | 
| 
      
 29 
     | 
    
         
            +
              exit(0)
         
     | 
| 
      
 30 
     | 
    
         
            +
            end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            begin
         
     | 
| 
      
 33 
     | 
    
         
            +
              loop do
         
     | 
| 
      
 34 
     | 
    
         
            +
                sleep 100
         
     | 
| 
      
 35 
     | 
    
         
            +
                # FIXME: know what to do
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
            rescue SignalException => e
         
     | 
| 
      
 38 
     | 
    
         
            +
              watcher.stop
         
     | 
| 
      
 39 
     | 
    
         
            +
              evesync_server.stop
         
     | 
| 
      
 40 
     | 
    
         
            +
              Evesync::Log.warn("Monitoring daemon received signal: #{e.signm}(#{e.signo})")
         
     | 
| 
      
 41 
     | 
    
         
            +
              exit(0)
         
     | 
| 
      
 42 
     | 
    
         
            +
            end
         
     | 
    
        data/bin/evesync
    ADDED
    
    | 
         @@ -0,0 +1,164 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
            # -*- mode: ruby -*-
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require 'optparse'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'socket'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'find'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'zip'
         
     | 
| 
      
 8 
     | 
    
         
            +
            require 'evesync'
         
     | 
| 
      
 9 
     | 
    
         
            +
            require 'evesync/log'
         
     | 
| 
      
 10 
     | 
    
         
            +
            require 'evesync/utils'
         
     | 
| 
      
 11 
     | 
    
         
            +
            require 'evesync/database'
         
     | 
| 
      
 12 
     | 
    
         
            +
            require 'evesync/config'
         
     | 
| 
      
 13 
     | 
    
         
            +
            require 'evesync/sync'
         
     | 
| 
      
 14 
     | 
    
         
            +
            require 'evesync/ipc/client'
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            DB_TAG = 'db'
         
     | 
| 
      
 17 
     | 
    
         
            +
            FILES_TAG = 'files'
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            opts = {}
         
     | 
| 
      
 20 
     | 
    
         
            +
            $program = File.basename($0)
         
     | 
| 
      
 21 
     | 
    
         
            +
            #Evesync::Log.level = :warn
         
     | 
| 
      
 22 
     | 
    
         
            +
            Evesync::Log.simple = true
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            OptionParser.new do |parser|
         
     | 
| 
      
 25 
     | 
    
         
            +
              parser.banner = "#{$program} [OPTIONS...]
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            "
         
     | 
| 
      
 28 
     | 
    
         
            +
              parser.summary_width = 20
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
              parser.on('-l', '--load FILE', 'Load events from file') do |f|
         
     | 
| 
      
 31 
     | 
    
         
            +
                unless File.file? f
         
     | 
| 
      
 32 
     | 
    
         
            +
                  puts "File is absent: #{f}"
         
     | 
| 
      
 33 
     | 
    
         
            +
                  exit 1
         
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
      
 35 
     | 
    
         
            +
                opts['load_file'] = f
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
              parser.on('-z', '--zip [DEST]', 'Zip current database') do |d|
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                # Pretty default name
         
     | 
| 
      
 41 
     | 
    
         
            +
                hostname = Socket.gethostname
         
     | 
| 
      
 42 
     | 
    
         
            +
                hostname = hostname == 'localhost' \
         
     | 
| 
      
 43 
     | 
    
         
            +
                           ? Evesync::Utils::local_ip : hostname
         
     | 
| 
      
 44 
     | 
    
         
            +
                time_now = Time.now.strftime('%Y.%m.%d-%H:%M:%S')
         
     | 
| 
      
 45 
     | 
    
         
            +
                opts['zip'] = d || "#{$program}_#{hostname}_#{time_now}.zip"
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                # Validation
         
     | 
| 
      
 48 
     | 
    
         
            +
                unless File.directory? File.dirname opts['zip']
         
     | 
| 
      
 49 
     | 
    
         
            +
                  puts "Directory doesn't exist: #{File.dirname opts['zip']}"
         
     | 
| 
      
 50 
     | 
    
         
            +
                  exit 1
         
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
              end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
              parser.on('-f', '--force', 'Enforce synchronization') do
         
     | 
| 
      
 55 
     | 
    
         
            +
                opts['sync'] = true
         
     | 
| 
      
 56 
     | 
    
         
            +
              end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
              parser.on_tail('-v', '--version', "Version of #{$program}") do
         
     | 
| 
      
 59 
     | 
    
         
            +
                puts Evesync::VERSION
         
     | 
| 
      
 60 
     | 
    
         
            +
                exit
         
     | 
| 
      
 61 
     | 
    
         
            +
              end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
              parser.on_tail('-h', '--help', 'Help message') do
         
     | 
| 
      
 64 
     | 
    
         
            +
                puts parser
         
     | 
| 
      
 65 
     | 
    
         
            +
                exit
         
     | 
| 
      
 66 
     | 
    
         
            +
              end
         
     | 
| 
      
 67 
     | 
    
         
            +
            end.parse!
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
            def force_sync
         
     | 
| 
      
 70 
     | 
    
         
            +
              sync_client = Evesync::IPC::Client.new(
         
     | 
| 
      
 71 
     | 
    
         
            +
                port: :evesyncd
         
     | 
| 
      
 72 
     | 
    
         
            +
              )
         
     | 
| 
      
 73 
     | 
    
         
            +
              sync_client.synchronize
         
     | 
| 
      
 74 
     | 
    
         
            +
            end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
            def files_in(folder)
         
     | 
| 
      
 77 
     | 
    
         
            +
              begin
         
     | 
| 
      
 78 
     | 
    
         
            +
                Find.find(folder).collect { |file| file }
         
     | 
| 
      
 79 
     | 
    
         
            +
              rescue StandardError
         
     | 
| 
      
 80 
     | 
    
         
            +
                puts "No files in #{folder}"
         
     | 
| 
      
 81 
     | 
    
         
            +
                []
         
     | 
| 
      
 82 
     | 
    
         
            +
              end
         
     | 
| 
      
 83 
     | 
    
         
            +
            end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
            def zip(out)
         
     | 
| 
      
 86 
     | 
    
         
            +
              databases = {
         
     | 
| 
      
 87 
     | 
    
         
            +
                DB_TAG => {
         
     | 
| 
      
 88 
     | 
    
         
            +
                  Evesync::Config[:evedatad]['db_path'] =>
         
     | 
| 
      
 89 
     | 
    
         
            +
                  files_in(Evesync::Config[:evedatad]['db_path'])
         
     | 
| 
      
 90 
     | 
    
         
            +
                },
         
     | 
| 
      
 91 
     | 
    
         
            +
                FILES_TAG => {
         
     | 
| 
      
 92 
     | 
    
         
            +
                  Evesync::Config[:evedatad]['db_files_path'] =>
         
     | 
| 
      
 93 
     | 
    
         
            +
                  files_in(Evesync::Config[:evedatad]['db_files_path'])
         
     | 
| 
      
 94 
     | 
    
         
            +
                }
         
     | 
| 
      
 95 
     | 
    
         
            +
              }
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
              Zip::File.open(out, Zip::File::CREATE) do |zip|
         
     | 
| 
      
 98 
     | 
    
         
            +
                databases.each do |key, entries|
         
     | 
| 
      
 99 
     | 
    
         
            +
                  entries.each do |base_path, files|
         
     | 
| 
      
 100 
     | 
    
         
            +
                    files.each do |file|
         
     | 
| 
      
 101 
     | 
    
         
            +
                      relative_path = Pathname.new(file)
         
     | 
| 
      
 102 
     | 
    
         
            +
                                        .relative_path_from(Pathname.new(base_path))
         
     | 
| 
      
 103 
     | 
    
         
            +
                      zip.add(File.join(key, relative_path.to_s), file)
         
     | 
| 
      
 104 
     | 
    
         
            +
                    end
         
     | 
| 
      
 105 
     | 
    
         
            +
                  end
         
     | 
| 
      
 106 
     | 
    
         
            +
                end
         
     | 
| 
      
 107 
     | 
    
         
            +
              end
         
     | 
| 
      
 108 
     | 
    
         
            +
            end
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
            def load_file(filename)
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
              Dir.mktmpdir($program) do |tmpdir|
         
     | 
| 
      
 113 
     | 
    
         
            +
                # Unpacking...
         
     | 
| 
      
 114 
     | 
    
         
            +
                Zip::File.open(filename) do |zip|
         
     | 
| 
      
 115 
     | 
    
         
            +
                  zip.each do |entry|
         
     | 
| 
      
 116 
     | 
    
         
            +
                    entry.extract(File.join(tmpdir, entry.name))
         
     | 
| 
      
 117 
     | 
    
         
            +
                  end
         
     | 
| 
      
 118 
     | 
    
         
            +
                end
         
     | 
| 
      
 119 
     | 
    
         
            +
             
     | 
| 
      
 120 
     | 
    
         
            +
                db_path = File.join(tmpdir, DB_TAG)
         
     | 
| 
      
 121 
     | 
    
         
            +
                db_files_path = File.join(tmpdir, FILES_TAG)
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
      
 123 
     | 
    
         
            +
                loaded_db = Evesync::Database.new(
         
     | 
| 
      
 124 
     | 
    
         
            +
                  db_path,
         
     | 
| 
      
 125 
     | 
    
         
            +
                  db_files_path
         
     | 
| 
      
 126 
     | 
    
         
            +
                )
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
                local_db = Evesync::IPC::Client.new(
         
     | 
| 
      
 129 
     | 
    
         
            +
                  port: :evedatad
         
     | 
| 
      
 130 
     | 
    
         
            +
                )
         
     | 
| 
      
 131 
     | 
    
         
            +
             
     | 
| 
      
 132 
     | 
    
         
            +
                diff = Evesync::Sync::diff_missed(
         
     | 
| 
      
 133 
     | 
    
         
            +
                  v1: local_db.events,
         
     | 
| 
      
 134 
     | 
    
         
            +
                  v2: loaded_db.events
         
     | 
| 
      
 135 
     | 
    
         
            +
                )
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
                new_messages = loaded_db.messages(diff)
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
                sync_client = Evesync::IPC::Client.new(
         
     | 
| 
      
 140 
     | 
    
         
            +
                  port: :evesyncd
         
     | 
| 
      
 141 
     | 
    
         
            +
                )
         
     | 
| 
      
 142 
     | 
    
         
            +
             
     | 
| 
      
 143 
     | 
    
         
            +
                sync_client.apply_events(new_messages)
         
     | 
| 
      
 144 
     | 
    
         
            +
              end
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
            end
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
            def evesync(opts)
         
     | 
| 
      
 149 
     | 
    
         
            +
              if opts['sync']
         
     | 
| 
      
 150 
     | 
    
         
            +
                puts 'Synchronization enforced'
         
     | 
| 
      
 151 
     | 
    
         
            +
                force_sync
         
     | 
| 
      
 152 
     | 
    
         
            +
              end
         
     | 
| 
      
 153 
     | 
    
         
            +
             
     | 
| 
      
 154 
     | 
    
         
            +
              if opts['load_file']
         
     | 
| 
      
 155 
     | 
    
         
            +
                load_file opts['load_file']
         
     | 
| 
      
 156 
     | 
    
         
            +
              end
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
              if opts['zip']
         
     | 
| 
      
 159 
     | 
    
         
            +
                zip(opts['zip'])
         
     | 
| 
      
 160 
     | 
    
         
            +
                puts(opts['zip'])
         
     | 
| 
      
 161 
     | 
    
         
            +
              end
         
     | 
| 
      
 162 
     | 
    
         
            +
            end
         
     | 
| 
      
 163 
     | 
    
         
            +
             
     | 
| 
      
 164 
     | 
    
         
            +
            evesync opts
         
     | 
    
        data/bin/evesyncd
    ADDED
    
    | 
         @@ -0,0 +1,44 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
            # -*- mode: ruby -*-
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require 'evesync/log'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'evesync/sync'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'evesync/config'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'evesync/ipc/server'
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            # Exiting if `auto_discover = false'
         
     | 
| 
      
 10 
     | 
    
         
            +
            unless Evesync::Config['auto_discover']
         
     | 
| 
      
 11 
     | 
    
         
            +
              Evesync::Log.info('Synchronizing not required')
         
     | 
| 
      
 12 
     | 
    
         
            +
              exit(0)
         
     | 
| 
      
 13 
     | 
    
         
            +
            end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            Evesync::Log.info('Synchronizing daemon starting...')
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            sync = Evesync::Sync.new
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            sync_server = Evesync::IPC::Server.new(
         
     | 
| 
      
 20 
     | 
    
         
            +
              port: :evesyncd,
         
     | 
| 
      
 21 
     | 
    
         
            +
              proxy: sync
         
     | 
| 
      
 22 
     | 
    
         
            +
            ).start
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            Signal.trap('TERM') do
         
     | 
| 
      
 25 
     | 
    
         
            +
              sync_server.stop
         
     | 
| 
      
 26 
     | 
    
         
            +
              exit(0)
         
     | 
| 
      
 27 
     | 
    
         
            +
            end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            Evesync::Log.info('Synchronizing daemon started!')
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
            few_seconds = Evesync::Config['discover_timeout'].to_i
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            sync.discover                   # discovering nodes
         
     | 
| 
      
 34 
     | 
    
         
            +
            sleep 3                         # giving 3 seconds to complete
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
            begin
         
     | 
| 
      
 37 
     | 
    
         
            +
              loop do
         
     | 
| 
      
 38 
     | 
    
         
            +
                sync.synchronize            # updating this node
         
     | 
| 
      
 39 
     | 
    
         
            +
                sleep few_seconds           # ... in some interval
         
     | 
| 
      
 40 
     | 
    
         
            +
              end
         
     | 
| 
      
 41 
     | 
    
         
            +
            rescue SignalException
         
     | 
| 
      
 42 
     | 
    
         
            +
              sync_server.stop
         
     | 
| 
      
 43 
     | 
    
         
            +
              exit(0)
         
     | 
| 
      
 44 
     | 
    
         
            +
            end
         
     | 
    
        data/bin/start
    ADDED
    
    
    
        data/config/example.conf
    ADDED
    
    | 
         @@ -0,0 +1,58 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # This is a configuration file example
         
     | 
| 
      
 2 
     | 
    
         
            +
            # It contains all information about daemons that can be changed
         
     | 
| 
      
 3 
     | 
    
         
            +
            # It's TOML formatted file, so feel free to use this format
         
     | 
| 
      
 4 
     | 
    
         
            +
            # without any restrictions.
         
     | 
| 
      
 5 
     | 
    
         
            +
            #
         
     | 
| 
      
 6 
     | 
    
         
            +
            # For more information about TOML format see:
         
     | 
| 
      
 7 
     | 
    
         
            +
            #   - https://github.com/toml-lang/toml
         
     | 
| 
      
 8 
     | 
    
         
            +
            #   - https://en.wikipedia.org/wiki/TOML
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            # Available log levels:
         
     | 
| 
      
 11 
     | 
    
         
            +
            # debug info warn error fatal
         
     | 
| 
      
 12 
     | 
    
         
            +
            loglevel = 'debug'
         
     | 
| 
      
 13 
     | 
    
         
            +
            # Delay in seconds for discovery package sending
         
     | 
| 
      
 14 
     | 
    
         
            +
            discover_timeout = 600
         
     | 
| 
      
 15 
     | 
    
         
            +
            # Automate discovering
         
     | 
| 
      
 16 
     | 
    
         
            +
            auto_discover = true
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            ntp = 'us.pool.ntp.org'
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            [evemond]			# System Monitor daemon
         
     | 
| 
      
 21 
     | 
    
         
            +
            port = 55443
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            # A list of remote nodes ips to keep connected with
         
     | 
| 
      
 24 
     | 
    
         
            +
            remotes = [ ]
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
            # Files to watch and synchronize
         
     | 
| 
      
 27 
     | 
    
         
            +
            watch = [
         
     | 
| 
      
 28 
     | 
    
         
            +
                '/etc/pam.d/login',
         
     | 
| 
      
 29 
     | 
    
         
            +
                '/etc/pam.d/other',
         
     | 
| 
      
 30 
     | 
    
         
            +
            ]
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            # Interval for gathering files' changes
         
     | 
| 
      
 33 
     | 
    
         
            +
            watch_interval = 3
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            # TODO:
         
     | 
| 
      
 36 
     | 
    
         
            +
            ignore_packages = [
         
     | 
| 
      
 37 
     | 
    
         
            +
                'ruby',
         
     | 
| 
      
 38 
     | 
    
         
            +
            ]
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
            # TODO:
         
     | 
| 
      
 41 
     | 
    
         
            +
            ignore_files = [
         
     | 
| 
      
 42 
     | 
    
         
            +
                '/etc/hosts',
         
     | 
| 
      
 43 
     | 
    
         
            +
            ]
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
            [evehand]			# System Handler daemon
         
     | 
| 
      
 47 
     | 
    
         
            +
            port = 55432
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
            [evedatad]			# System Data daemon
         
     | 
| 
      
 51 
     | 
    
         
            +
            port = 54321
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
            [evesyncd]
         
     | 
| 
      
 54 
     | 
    
         
            +
            port = 64653
         
     | 
| 
      
 55 
     | 
    
         
            +
            broadcast_port = 64564
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
            # Copyright (c) Kiselev Valentin 2019
         
     | 
| 
         @@ -0,0 +1,63 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'toml-rb'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'evesync/utils'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'evesync/constants'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'evesync/log'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module Evesync
         
     | 
| 
      
 7 
     | 
    
         
            +
              module Config
         
     | 
| 
      
 8 
     | 
    
         
            +
                class << self
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  DEFAULTS = {
         
     | 
| 
      
 11 
     | 
    
         
            +
                    'ntp' => '',
         
     | 
| 
      
 12 
     | 
    
         
            +
                    'evemond' => {
         
     | 
| 
      
 13 
     | 
    
         
            +
                      'port'           => Constants::MOOND_PORT,
         
     | 
| 
      
 14 
     | 
    
         
            +
                      'remotes'        => [],
         
     | 
| 
      
 15 
     | 
    
         
            +
                      'watch'          => [],
         
     | 
| 
      
 16 
     | 
    
         
            +
                      'watch_interval' => Constants::WATCH_INTERVAL
         
     | 
| 
      
 17 
     | 
    
         
            +
                    },
         
     | 
| 
      
 18 
     | 
    
         
            +
                    'evedatad' => {
         
     | 
| 
      
 19 
     | 
    
         
            +
                      'port'           => Constants::DATAD_PORT,
         
     | 
| 
      
 20 
     | 
    
         
            +
                      'db_path'        => Constants::DB_PATH,
         
     | 
| 
      
 21 
     | 
    
         
            +
                      'db_files_path'  => Constants::DB_FILES_PATH
         
     | 
| 
      
 22 
     | 
    
         
            +
                    },
         
     | 
| 
      
 23 
     | 
    
         
            +
                    'evehand'  => {
         
     | 
| 
      
 24 
     | 
    
         
            +
                      'port' => Constants::HAND_PORT
         
     | 
| 
      
 25 
     | 
    
         
            +
                    },
         
     | 
| 
      
 26 
     | 
    
         
            +
                    'evesyncd' => {
         
     | 
| 
      
 27 
     | 
    
         
            +
                      'port' => Constants::SYNC_PORT
         
     | 
| 
      
 28 
     | 
    
         
            +
                    },
         
     | 
| 
      
 29 
     | 
    
         
            +
                    'discover_timeout' => Constants::DISCOVER_TIMEOUT
         
     | 
| 
      
 30 
     | 
    
         
            +
                  }
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  def [](daemon)
         
     | 
| 
      
 34 
     | 
    
         
            +
                    read_config if needs_reading
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                    @@config[daemon.to_s]
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                  def reread
         
     | 
| 
      
 40 
     | 
    
         
            +
                    read_config
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                  private
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                  def read_config
         
     | 
| 
      
 46 
     | 
    
         
            +
                    config = begin
         
     | 
| 
      
 47 
     | 
    
         
            +
                               TomlRB.load_file(Constants::CONFIG_FILE)
         
     | 
| 
      
 48 
     | 
    
         
            +
                             rescue StandardError => e
         
     | 
| 
      
 49 
     | 
    
         
            +
                               Log.error("Config ERROR: Couldn't parse file #{Constants::CONFIG_FILE}")
         
     | 
| 
      
 50 
     | 
    
         
            +
                               Log.error("Config ERROR MESSAGE: #{e}")
         
     | 
| 
      
 51 
     | 
    
         
            +
                               Log.error("Config ERROR: Using default configuration")
         
     | 
| 
      
 52 
     | 
    
         
            +
                               {}
         
     | 
| 
      
 53 
     | 
    
         
            +
                             end
         
     | 
| 
      
 54 
     | 
    
         
            +
                    @@config = DEFAULTS.deep_merge(config)
         
     | 
| 
      
 55 
     | 
    
         
            +
                    Log.info("Config initialized!")
         
     | 
| 
      
 56 
     | 
    
         
            +
                  end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                  def needs_reading
         
     | 
| 
      
 59 
     | 
    
         
            +
                    ! defined? @@config
         
     | 
| 
      
 60 
     | 
    
         
            +
                  end
         
     | 
| 
      
 61 
     | 
    
         
            +
                end
         
     | 
| 
      
 62 
     | 
    
         
            +
              end
         
     | 
| 
      
 63 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,17 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Evesync
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Constants
         
     | 
| 
      
 3 
     | 
    
         
            +
                MOOND_PORT = '55443'.freeze
         
     | 
| 
      
 4 
     | 
    
         
            +
                DATAD_PORT = '54321'.freeze
         
     | 
| 
      
 5 
     | 
    
         
            +
                HAND_PORT  = '55432'.freeze
         
     | 
| 
      
 6 
     | 
    
         
            +
                SYNC_PORT  = '64653'.freeze
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                CONFIG_FILE   = '/etc/evesync.conf'.freeze
         
     | 
| 
      
 9 
     | 
    
         
            +
                DB_PATH       = '/var/lib/evesync/db/'.freeze
         
     | 
| 
      
 10 
     | 
    
         
            +
                DB_FILES_PATH = '/var/lib/evesync/files/'.freeze
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                DEFAULT_LOGLEVEL = 'debug'.freeze
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                DISCOVER_TIMEOUT = 3600
         
     | 
| 
      
 15 
     | 
    
         
            +
                WATCH_INTERVAL   = 2
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,107 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'fileutils'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'json'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'lmdb'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'evesync/config'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'evesync/constants'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'evesync/ipc/data/package'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'evesync/ipc/data/file'
         
     | 
| 
      
 8 
     | 
    
         
            +
            require 'evesync/ipc/data/ignore'
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            module Evesync
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
              ##
         
     | 
| 
      
 13 
     | 
    
         
            +
              # *Database* class is a proxy for *evedatad* daemon
         
     | 
| 
      
 14 
     | 
    
         
            +
              # implements at least one method: +save+. Allows
         
     | 
| 
      
 15 
     | 
    
         
            +
              # Local +evemond+ save messages about changes
         
     | 
| 
      
 16 
     | 
    
         
            +
              #
         
     | 
| 
      
 17 
     | 
    
         
            +
              # Messages should be serializable (JSON)
         
     | 
| 
      
 18 
     | 
    
         
            +
              #
         
     | 
| 
      
 19 
     | 
    
         
            +
              # TODO:
         
     | 
| 
      
 20 
     | 
    
         
            +
              #  * Think about how it can be widened
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              class Database
         
     | 
| 
      
 23 
     | 
    
         
            +
                def initialize(db_path=nil, db_files_path=nil)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  path = db_path || Config[:evedatad]['db_path']
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  unless ::File.exist? path
         
     | 
| 
      
 27 
     | 
    
         
            +
                    # FIXME: only root. handle exception
         
     | 
| 
      
 28 
     | 
    
         
            +
                    FileUtils.mkdir_p(path)
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
                  @env = LMDB.new(path)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  @db = @env.database
         
     | 
| 
      
 32 
     | 
    
         
            +
                  @files_path = db_files_path || Config[:evedatad]['db_files_path']
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                # Save message to database, key is timestamp+object
         
     | 
| 
      
 36 
     | 
    
         
            +
                def save(message)
         
     | 
| 
      
 37 
     | 
    
         
            +
                  Log.debug("Database save: #{message}")
         
     | 
| 
      
 38 
     | 
    
         
            +
                  db_add_entry(message)
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                  if message.is_a? Evesync::IPC::Data::File
         
     | 
| 
      
 41 
     | 
    
         
            +
                    Log.debug("Database save file action: #{message.action}")
         
     | 
| 
      
 42 
     | 
    
         
            +
                    unless message.action ==
         
     | 
| 
      
 43 
     | 
    
         
            +
                           IPC::Data::File::Action::DELETE
         
     | 
| 
      
 44 
     | 
    
         
            +
                      save_file(message)
         
     | 
| 
      
 45 
     | 
    
         
            +
                    end
         
     | 
| 
      
 46 
     | 
    
         
            +
                  end
         
     | 
| 
      
 47 
     | 
    
         
            +
                  true
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                # Events simplified: object => [timestamp...]
         
     | 
| 
      
 51 
     | 
    
         
            +
                def events
         
     | 
| 
      
 52 
     | 
    
         
            +
                  events = {}
         
     | 
| 
      
 53 
     | 
    
         
            +
                  @db.each do |key, _|
         
     | 
| 
      
 54 
     | 
    
         
            +
                    timestamp, object = parse_event(key)
         
     | 
| 
      
 55 
     | 
    
         
            +
                    events[object] ||= []
         
     | 
| 
      
 56 
     | 
    
         
            +
                    events[object].push(timestamp)
         
     | 
| 
      
 57 
     | 
    
         
            +
                  end
         
     | 
| 
      
 58 
     | 
    
         
            +
                  events
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                # Messages for events: object => {timestamp => message}
         
     | 
| 
      
 62 
     | 
    
         
            +
                def messages(events)
         
     | 
| 
      
 63 
     | 
    
         
            +
                  ev_msgs = {}
         
     | 
| 
      
 64 
     | 
    
         
            +
                  @db.each do |key, message|
         
     | 
| 
      
 65 
     | 
    
         
            +
                    timestamp, object = parse_event(key)
         
     | 
| 
      
 66 
     | 
    
         
            +
                    next unless events.include?(object)
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                    ev_msgs[object] ||= {}
         
     | 
| 
      
 69 
     | 
    
         
            +
                    if events[object].include?(timestamp)
         
     | 
| 
      
 70 
     | 
    
         
            +
                      ev_msgs[object][timestamp] = message
         
     | 
| 
      
 71 
     | 
    
         
            +
                    end
         
     | 
| 
      
 72 
     | 
    
         
            +
                  end
         
     | 
| 
      
 73 
     | 
    
         
            +
                  ev_msgs
         
     | 
| 
      
 74 
     | 
    
         
            +
                end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                private
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                def db_add_entry(message)
         
     | 
| 
      
 79 
     | 
    
         
            +
                  Log.debug('Database adding entry...')
         
     | 
| 
      
 80 
     | 
    
         
            +
                  key = create_key(message)
         
     | 
| 
      
 81 
     | 
    
         
            +
                  value = create_value(message)
         
     | 
| 
      
 82 
     | 
    
         
            +
                  @db[key] = value
         
     | 
| 
      
 83 
     | 
    
         
            +
                  Log.debug('Database adding entry done!')
         
     | 
| 
      
 84 
     | 
    
         
            +
                end
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                def create_key(message)
         
     | 
| 
      
 87 
     | 
    
         
            +
                  "#{message.timestamp}_#{message.name}"
         
     | 
| 
      
 88 
     | 
    
         
            +
                end
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
                def create_value(message)
         
     | 
| 
      
 91 
     | 
    
         
            +
                  message.to_hash.to_json
         
     | 
| 
      
 92 
     | 
    
         
            +
                end
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
                def parse_event(key)
         
     | 
| 
      
 95 
     | 
    
         
            +
                  key.split('_', 2)
         
     | 
| 
      
 96 
     | 
    
         
            +
                end
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
                def save_file(file)
         
     | 
| 
      
 99 
     | 
    
         
            +
                  Log.debug('Database saving file...')
         
     | 
| 
      
 100 
     | 
    
         
            +
                  fulldest = File.join(@files_path,
         
     | 
| 
      
 101 
     | 
    
         
            +
                                       file.name + ".#{file.timestamp}")
         
     | 
| 
      
 102 
     | 
    
         
            +
                  FileUtils.mkdir_p(File.dirname(fulldest))
         
     | 
| 
      
 103 
     | 
    
         
            +
                  FileUtils.cp(file.name, fulldest)
         
     | 
| 
      
 104 
     | 
    
         
            +
                  Log.debug('Database saving file done!')
         
     | 
| 
      
 105 
     | 
    
         
            +
                end
         
     | 
| 
      
 106 
     | 
    
         
            +
              end
         
     | 
| 
      
 107 
     | 
    
         
            +
            end
         
     |