Ejemplo n.º 1
0
  @Override
  public void onDisable() {
    if (pool != null) {
      // Poison the PubSub listener
      psl.poison();
      getProxy().getScheduler().cancel(this);
      integrityCheck.cancel();
      heartbeatTask.cancel();
      getProxy().getPluginManager().unregisterListeners(this);

      try (Jedis tmpRsc = pool.getResource()) {
        tmpRsc.hdel("heartbeats", configuration.getServerId());
        if (tmpRsc.scard("proxy:" + configuration.getServerId() + ":usersOnline") > 0) {
          Set<String> players =
              tmpRsc.smembers("proxy:" + configuration.getServerId() + ":usersOnline");
          for (String member : players) RedisUtil.cleanUpPlayer(member, tmpRsc);
        }
      }

      pool.destroy();
    }
  }
Ejemplo n.º 2
0
  private void loadConfig() throws IOException, JedisConnectionException {
    if (!getDataFolder().exists()) {
      getDataFolder().mkdir();
    }

    File file = new File(getDataFolder(), "config.yml");

    if (!file.exists()) {
      file.createNewFile();
      try (InputStream in = getResourceAsStream("example_config.yml");
          OutputStream out = new FileOutputStream(file)) {
        ByteStreams.copy(in, out);
      }
    }

    final Configuration configuration =
        ConfigurationProvider.getProvider(YamlConfiguration.class).load(file);

    final String redisServer = configuration.getString("redis-server", "localhost");
    final int redisPort = configuration.getInt("redis-port", 6379);
    String redisPassword = configuration.getString("redis-password");
    String serverId = configuration.getString("server-id");

    if (redisPassword != null && (redisPassword.isEmpty() || redisPassword.equals("none"))) {
      redisPassword = null;
    }

    // Configuration sanity checks.
    if (serverId == null || serverId.isEmpty()) {
      throw new RuntimeException("server-id is not specified in the configuration or is empty");
    }

    if (redisServer != null && !redisServer.isEmpty()) {
      final String finalRedisPassword = redisPassword;
      FutureTask<JedisPool> task =
          new FutureTask<>(
              new Callable<JedisPool>() {
                @Override
                public JedisPool call() throws Exception {
                  // With recent versions of Jedis, we must set the classloader to the one
                  // BungeeCord used
                  // to load RedisBungee with.
                  ClassLoader previous = Thread.currentThread().getContextClassLoader();
                  Thread.currentThread().setContextClassLoader(RedisBungee.class.getClassLoader());

                  // Create the pool...
                  JedisPoolConfig config = new JedisPoolConfig();
                  config.setMaxTotal(configuration.getInt("max-redis-connections", 8));
                  JedisPool pool =
                      new JedisPool(config, redisServer, redisPort, 0, finalRedisPassword);

                  // Reset classloader and return the pool
                  Thread.currentThread().setContextClassLoader(previous);
                  return pool;
                }
              });

      getProxy().getScheduler().runAsync(this, task);

      try {
        pool = task.get();
      } catch (InterruptedException | ExecutionException e) {
        throw new RuntimeException("Unable to create Redis pool", e);
      }

      // Test the connection
      try (Jedis rsc = pool.getResource()) {
        rsc.ping();
        // If that worked, now we can check for an existing, alive Bungee:
        File crashFile = new File(getDataFolder(), "restarted_from_crash.txt");
        if (crashFile.exists()) {
          crashFile.delete();
        } else if (rsc.hexists("heartbeats", serverId)) {
          try {
            long value = Long.parseLong(rsc.hget("heartbeats", serverId));
            if (System.currentTimeMillis() < value + 20000) {
              getLogger()
                  .severe(
                      "You have launched a possible impostor BungeeCord instance. Another instance is already running.");
              getLogger()
                  .severe("For data consistency reasons, RedisBungee will now disable itself.");
              getLogger()
                  .severe(
                      "If this instance is coming up from a crash, create a file in your RedisBungee plugins directory with the name 'restarted_from_crash.txt' and RedisBungee will not perform this check.");
              throw new RuntimeException("Possible impostor instance!");
            }
          } catch (NumberFormatException ignored) {
          }
        }

        FutureTask<Void> task2 =
            new FutureTask<>(
                new Callable<Void>() {
                  @Override
                  public Void call() throws Exception {
                    httpClient = new OkHttpClient();
                    Dispatcher dispatcher = new Dispatcher(getExecutorService());
                    httpClient.setDispatcher(dispatcher);
                    NameFetcher.setHttpClient(httpClient);
                    UUIDFetcher.setHttpClient(httpClient);
                    RedisBungee.configuration =
                        new RedisBungeeConfiguration(RedisBungee.this.getPool(), configuration);
                    return null;
                  }
                });

        getProxy().getScheduler().runAsync(this, task2);

        try {
          task2.get();
        } catch (InterruptedException | ExecutionException e) {
          throw new RuntimeException("Unable to create HTTP client", e);
        }

        getLogger().log(Level.INFO, "Successfully connected to Redis.");
      } catch (JedisConnectionException e) {
        pool.destroy();
        pool = null;
        throw e;
      }
    } else {
      throw new RuntimeException("No redis server specified!");
    }
  }