jxing %!s(int64=6) %!d(string=hai) anos
pai
achega
819a404e06
Modificáronse 29 ficheiros con 2043 adicións e 0 borrados
  1. 17 0
      .gitignore
  2. 48 0
      build.gradle
  3. 62 0
      gradle.properties
  4. 172 0
      gradlew
  5. 84 0
      gradlew.bat
  6. 77 0
      scheduler/build.gradle
  7. 25 0
      scheduler/src/main/java/cn/sagacloud/guice/InjectorInit.java
  8. 37 0
      scheduler/src/main/java/cn/sagacloud/mybatis/MyBatisSqlSessionFactory.java
  9. 50 0
      scheduler/src/main/java/cn/sagacloud/mybatis/dao/TaskDAO.java
  10. 13 0
      scheduler/src/main/java/cn/sagacloud/mybatis/mapper/TaskMapper.java
  11. 40 0
      scheduler/src/main/java/cn/sagacloud/mybatis/model/DownloadTaskModel.java
  12. 92 0
      scheduler/src/main/java/cn/sagacloud/mybatis/model/TaskModel.java
  13. 46 0
      scheduler/src/main/java/cn/sagacloud/mybatis/service/TaskService.java
  14. 39 0
      scheduler/src/main/java/cn/sagacloud/pojo/ChannelHandlerContextWrapper.java
  15. 29 0
      scheduler/src/main/java/cn/sagacloud/pojo/Command.java
  16. 23 0
      scheduler/src/main/java/cn/sagacloud/pojo/Config.java
  17. 9 0
      scheduler/src/main/java/cn/sagacloud/pojo/TaskStatus.java
  18. 805 0
      scheduler/src/main/java/cn/sagacloud/proto/MessageProto.java
  19. 19 0
      scheduler/src/main/java/cn/sagacloud/proto/MessageUtil.java
  20. 110 0
      scheduler/src/main/java/cn/sagacloud/server/SchedulerHandler.java
  21. 80 0
      scheduler/src/main/java/cn/sagacloud/server/Server.java
  22. 32 0
      scheduler/src/main/java/cn/sagacloud/utils/CommonUtil.java
  23. 11 0
      scheduler/src/main/proto/MessageProto.proto
  24. 2 0
      scheduler/src/main/resources/config.yml
  25. 32 0
      scheduler/src/main/resources/log4j.properties
  26. 15 0
      scheduler/src/main/resources/mapper/TaskMap.xml
  27. 44 0
      scheduler/src/main/resources/mybatis-config.xml
  28. 27 0
      scheduler/src/test/java/cn/sagacloud/mybatis/TaskTest.java
  29. 3 0
      settings.gradle

+ 17 - 0
.gitignore

@@ -0,0 +1,17 @@
+src/main/.DS_Store
+src/main/resources/.DS_Store
+.DS_Store
+.idea
+*.iml
+log/*
+.classpath
+.project
+.settings/
+src/test/java/
+target/*
+.gradle
+scheduler/build
+scheduler/out
+gradle
+lib
+/src

+ 48 - 0
build.gradle

@@ -0,0 +1,48 @@
+group 'com.sagacloud'
+version '1.0-SNAPSHOT'
+
+buildscript {
+    repositories {
+        //maven{url MAVEN_REPO_PUBLIC_URL}
+        maven{ url "http://maven.aliyun.com/nexus/content/groups/public/"}
+        mavenCentral()
+        jcenter()
+    }
+    dependencies {
+        //classpath group: 'org.springframework.boot', name: 'spring-boot-gradle-plugin', version: SPRING_BOOT_VERSION
+        //classpath group: 'org.jetbrains.kotlin', name: 'kotlin-gradle-plugin', version: KOTLIN_VERSION
+        //classpath group: 'org.jetbrains.dokka', name: 'dokka-gradle-plugin', version: DOKKA_VERSION
+        classpath group: 'com.google.protobuf', name: 'protobuf-gradle-plugin', version: PROTOBUF_GRADLE_VERSION
+        //classpath group: 'com.sybotan', name: 'sybotan-gradle-tools', version: SYBOTAN_KOTLIN_VERSION
+    }
+}
+
+allprojects {
+    repositories {
+//        maven{url MAVEN_REPO_PUBLIC_URL}
+        maven{ url "http://maven.aliyun.com/nexus/content/groups/public/"}
+        maven { url "https://repo.spring.io/milestone" }
+        mavenCentral()
+        jcenter()
+    }
+    tasks.withType(Javadoc) {
+        options{ encoding "UTF-8"
+            charSet "UTF-8"
+            links "http://docs.oracle.com/javase/8/docs/api"
+        }
+    }
+}
+
+//task dokkaAll(type: org.jetbrains.dokka.gradle.DokkaTask) {
+//    jdkVersion = 8
+//    outputFormat = "javadoc"
+//    outputDirectory = "$buildDir/javadoc"
+//    sourceDirs = files(
+//            "sybotan-service-core/src/main/kotlin",
+//            "sybotan-service-hbase/src/main/kotlin",
+//            "sybotan-service-mybatis/src/main/kotlin")
+//}
+
+task clean(type: Delete) {
+    delete rootProject.buildDir
+}

+ 62 - 0
gradle.properties

@@ -0,0 +1,62 @@
+JVM_TARGET = 1.8
+JDK_VERSION = 8
+
+#SYBOTAN_KOTLIN_VERSION = 1.3.5.17
+#SYBOTAN_SERVICE_VERSION = 1.3.5.41
+#
+#MAVEN_REPO_PUBLIC_URL = http://dev.dp.sagacloud.cn:8082/repository/maven-public/
+#MAVEN_REPO_RELEASE_URL = http://dev.dp.sagacloud.cn:8082/repository/maven-releases/
+#MAVEN_REPO_SNAPSHOT_URL = http://dev.dp.sagacloud.cn:8082/repository/maven-snapshots/
+#NEXUS_USERNAME = saga
+#NEXUS_PASSWORD = saga
+
+# https://mvnrepository.com/artifact/com.aliyun.oss/aliyun-sdk-oss
+ALIYUN_OSS_VERSION = 3.3.0
+# https://mvnrepository.com/artifact/org.apache.commons/commons-lang3
+COMMONS_LANG_VERSION = 3.8
+# https://mvnrepository.com/artifact/org.jetbrains.dokka/dokka-gradle-plugin
+DOKKA_VERSION = 0.9.16
+# https://mvnrepository.com/artifact/com.alibaba/druid
+DRUID_VERSION = 1.1.10
+# https://mvnrepository.com/artifact/com.android.tools.build/gradle
+GRADLE_VERSION = 3.3.2
+# https://mvnrepository.com/artifact/io.grpc/grpc-all
+GRPC_VERSION = 1.19.0
+# https://mvnrepository.com/artifact/org.jline/jline
+JLINE_VERSION = 3.9.0
+# https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api
+JUNIT_VERSION = 4.3.1
+KOTLIN_VERSION = 1.3.20
+# https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter
+MYBATIS_VERSION = 2.0.0
+# https://mvnrepository.com/artifact/mysql/mysql-connector-java
+MYSQL_VERSION = 8.0.12
+# https://mvnrepository.com/artifact/io.netty/netty-all
+NETTY_VERSION = 4.1.33.Final
+# https://mvnrepository.com/artifact/javax.persistence/persistence-api
+PERSISTENCE_VERSION = 1.0.2
+# https://mvnrepository.com/artifact/org.postgresql/postgresql
+POSTGRESQL_VERSION = 42.2.5
+# https://mvnrepository.com/artifact/com.google.protobuf/protobuf-lite
+PROTOBUF_VERSION = 3.7.0
+#/ https://mvnrepository.com/artifact/com.google.protobuf/protobuf-gradle-plugin
+PROTOBUF_GRADLE_VERSION = 0.8.8
+# https://mvnrepository.com/artifact/org.slf4j/slf4j-api
+SLF4J_VERSION = 1.7.25
+# https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web
+SPRING_BOOT_VERSION = 2.1.3.RELEASE
+# https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server
+SPRING_CLOUD_VERSION = 1.4.6.RELEASE
+# https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-config
+SPRING_CLOUD_CONFIG_VERSION = 2.0.2.RELEASE
+# https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui
+SWAGGER_VERSION = 2.9.2
+# https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator
+VALIDATOR_VERSION = 6.0.13.Final
+# https://mvnrepository.com/artifact/com.google.zxing/core
+ZXING_VERSION = 3.3.3
+
+# https://repo.spring.io/milestone
+SPRING_CLOUD_DEPENDENCIES = Finchley.RELEASE
+
+

+ 172 - 0
gradlew

@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+    echo "$*"
+}
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Escape application args
+save () {
+    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+    echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+  cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"

+ 84 - 0
gradlew.bat

@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega

+ 77 - 0
scheduler/build.gradle

@@ -0,0 +1,77 @@
+group rootProject.group
+version rootProject.version
+
+apply plugin: 'java'
+//apply plugin: 'org.jetbrains.dokka'
+apply plugin: 'maven'
+apply plugin: 'com.google.protobuf'
+
+sourceCompatibility = JVM_TARGET
+
+//compileKotlin {
+//    kotlinOptions.jvmTarget = JVM_TARGET
+//}
+//compileTestKotlin {
+//    kotlinOptions.jvmTarget = JVM_TARGET
+//}
+
+protobuf {
+    generatedFilesBaseDir = "src"
+    protoc {
+        artifact = "com.google.protobuf:protoc:3.7.0"
+    }
+
+//    plugins {
+//        grpc {
+//            artifact = 'io.grpc:protoc-gen-grpc-java:1.19.0'
+//        }
+//    }
+//    generateProtoTasks {
+//        all()*.plugins {
+//            grpc {}
+//        }
+//    }
+}
+
+dependencies {
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // kotlin 依赖
+//    compile group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib-jdk8', version: KOTLIN_VERSION
+//    compile group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: KOTLIN_VERSION
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // 网络操作依赖
+    // https://mvnrepository.com/artifact/io.netty/netty-all
+    compile group: 'io.netty',  name: 'netty-all',  version: NETTY_VERSION
+    // https://mvnrepository.com/artifact/io.grpc/grpc-all
+    //compile group: 'io.grpc',   name: 'grpc-all',   version: GRPC_VERSION
+
+
+    // https://mvnrepository.com/artifact/com.google.protobuf/protoc
+    //compile group: 'com.google.protobuf', name: 'protoc', version: PROTOBUF_VERSION
+    // https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java
+    compile group: 'com.google.protobuf', name: 'protobuf-java', version: PROTOBUF_VERSION
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // Sybotan依赖
+//    compile group: 'com.sybotan', name: 'sybotan-kotlin-base', version: SYBOTAN_KOTLIN_VERSION
+//    compile group: 'com.sybotan', name: 'sybotan-kotlin-database', version: SYBOTAN_KOTLIN_VERSION
+//    compile group: 'com.sybotan', name: 'sybotan-service-base', version: SYBOTAN_SERVICE_VERSION
+//    compile group: 'com.sybotan', name: 'sybotan-service-mybatis', version: SYBOTAN_SERVICE_VERSION
+//    compile group: 'com.sybotan', name: 'sybotan-service-mongo', version: SYBOTAN_SERVICE_VERSION
+
+    // https://mvnrepository.com/artifact/org.mybatis/mybatis
+    compile group: 'org.mybatis', name: 'mybatis', version: '3.5.0'
+
+    // https://mvnrepository.com/artifact/org.mybatis/mybatis-guice
+    compile group: 'org.mybatis', name: 'mybatis-guice', version: '3.10'
+    // https://mvnrepository.com/artifact/org.yaml/snakeyaml
+    compile group: 'org.yaml', name: 'snakeyaml', version: '1.24'
+    // https://mvnrepository.com/artifact/com.google.inject/guice
+    compile group: 'com.google.inject', name: 'guice', version: '4.2.2'
+
+    testCompile group: 'junit', name: 'junit', version: '4.12'
+    // https://mvnrepository.com/artifact/mysql/mysql-connector-java
+    compile group: 'mysql', name: 'mysql-connector-java', version: '8.0.15'
+
+}

+ 25 - 0
scheduler/src/main/java/cn/sagacloud/guice/InjectorInit.java

@@ -0,0 +1,25 @@
+package cn.sagacloud.guice;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import org.mybatis.guice.XMLMyBatisModule;
+
+public class InjectorInit {
+
+    private static Injector injector;
+    static {
+
+
+        injector = Guice.createInjector(new XMLMyBatisModule() {
+            @Override
+            protected void initialize() {
+                //setEnvironmentId("dev");
+                setClassPathResource("mybatis-config.xml");
+            }
+        });
+    }
+
+    public static Injector getInjector() {
+        return injector;
+    }
+}

+ 37 - 0
scheduler/src/main/java/cn/sagacloud/mybatis/MyBatisSqlSessionFactory.java

@@ -0,0 +1,37 @@
+package cn.sagacloud.mybatis;
+
+import java.io.IOException;
+import java.io.InputStream;
+import org.apache.ibatis.io.Resources;
+import org.apache.ibatis.session.SqlSession;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.apache.ibatis.session.SqlSessionFactoryBuilder;
+
+public class MyBatisSqlSessionFactory {
+    private MyBatisSqlSessionFactory(){}
+    private static volatile SqlSessionFactory sqlSessionFactory = null;
+    public static SqlSessionFactory getSqlSessionFactory(){
+        if(sqlSessionFactory==null){
+            InputStream inputStream;
+            try {
+                synchronized(MyBatisSqlSessionFactory.class) {
+                    if (sqlSessionFactory == null) {
+                        inputStream = Resources.getResourceAsStream("mybatis-config.xml");
+                        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
+                    }
+                }
+//                sqlSessionFactory.getConfiguration().addMapper(UserMapper.class);
+//                sqlSessionFactory.getConfiguration().addMapper(ManufacturerMapper.class);
+//                sqlSessionFactory.getConfiguration().addMapper(BrandMapper.class);
+            }
+            catch(IOException e){
+                System.out.println(e.getMessage());
+                throw new RuntimeException(e.getCause());
+            }
+        }
+        return sqlSessionFactory;
+    }
+    public static SqlSession openSession(){
+        return getSqlSessionFactory().openSession();
+    }
+}

+ 50 - 0
scheduler/src/main/java/cn/sagacloud/mybatis/dao/TaskDAO.java

@@ -0,0 +1,50 @@
+package cn.sagacloud.mybatis.dao;
+
+import cn.sagacloud.mybatis.MyBatisSqlSessionFactory;
+import cn.sagacloud.mybatis.mapper.TaskMapper;
+import cn.sagacloud.mybatis.model.TaskModel;
+import org.apache.ibatis.session.SqlSession;
+import org.mybatis.guice.transactional.Transactional;
+
+public class TaskDAO {
+
+
+    public boolean addTask(TaskModel task) {
+        SqlSession session = null;
+        try {
+            session = MyBatisSqlSessionFactory.openSession();
+            TaskMapper taskMapper = session.getMapper(TaskMapper.class);
+            int id = taskMapper.addTask(task);
+            session.commit();
+            //task.setId(id);
+            return true;
+        } catch (Exception e) {
+            return false;
+        } finally {
+            if (session != null)
+                session.close();
+        }
+    }
+
+    public boolean addDownload(TaskModel task) {
+        SqlSession session = null;
+        try {
+            session = MyBatisSqlSessionFactory.openSession();
+            TaskMapper taskMapper = session.getMapper(TaskMapper.class);
+            if(task.getId() == 0)
+                return false;
+            if(task.getDownloadTaskModelList().size() == 0)
+                return true;
+            int infectedRow = taskMapper.addDownload(task.getDownloadTaskModelList(), task.getId());
+            session.commit();
+            if(infectedRow == task.getDownloadTaskModelList().size())
+                return true;
+            return true;
+        } catch (Exception e) {
+            return false;
+        } finally {
+            if (session != null)
+                session.close();
+        }
+    }
+}

+ 13 - 0
scheduler/src/main/java/cn/sagacloud/mybatis/mapper/TaskMapper.java

@@ -0,0 +1,13 @@
+package cn.sagacloud.mybatis.mapper;
+
+import cn.sagacloud.mybatis.model.DownloadTaskModel;
+import cn.sagacloud.mybatis.model.TaskModel;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+public interface TaskMapper {
+    public int addTask(TaskModel task);
+
+    public int addDownload(@Param("list")List<DownloadTaskModel> downloadTaskModelList, @Param("taskId")int id) ;
+}

+ 40 - 0
scheduler/src/main/java/cn/sagacloud/mybatis/model/DownloadTaskModel.java

@@ -0,0 +1,40 @@
+package cn.sagacloud.mybatis.model;
+
+public class DownloadTaskModel {
+    private int id;
+    private int task_id;
+    private String task_url;
+    private String task_md5;
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public int getTask_id() {
+        return task_id;
+    }
+
+    public void setTask_id(int task_id) {
+        this.task_id = task_id;
+    }
+
+    public String getTask_url() {
+        return task_url;
+    }
+
+    public void setTask_url(String task_url) {
+        this.task_url = task_url;
+    }
+
+    public String getTask_md5() {
+        return task_md5;
+    }
+
+    public void setTask_md5(String task_md5) {
+        this.task_md5 = task_md5;
+    }
+}

+ 92 - 0
scheduler/src/main/java/cn/sagacloud/mybatis/model/TaskModel.java

@@ -0,0 +1,92 @@
+package cn.sagacloud.mybatis.model;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class TaskModel {
+    private int id;
+    private String task_name;
+    private String task_cmd;
+    private String task_param;
+    private int task_status;
+    private String task_result_json;
+    private String task_last_mac;
+    private long task_expected_finish_time;
+
+    private List<DownloadTaskModel> downloadTaskModelList;
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public String getTask_name() {
+        return task_name;
+    }
+
+    public void setTask_name(String task_name) {
+        this.task_name = task_name;
+    }
+
+    public String getTask_cmd() {
+        return task_cmd;
+    }
+
+    public void setTask_cmd(String task_cmd) {
+        this.task_cmd = task_cmd;
+    }
+
+    public String getTask_param() {
+        return task_param;
+    }
+
+    public void setTask_param(String task_param) {
+        this.task_param = task_param;
+    }
+
+    public int getTask_status() {
+        return task_status;
+    }
+
+    public void setTask_status(int task_status) {
+        this.task_status = task_status;
+    }
+
+    public String getTask_result_json() {
+        return task_result_json;
+    }
+
+    public void setTask_result_json(String task_result_json) {
+        this.task_result_json = task_result_json;
+    }
+
+    public String getTask_last_mac() {
+        return task_last_mac;
+    }
+
+    public void setTask_last_mac(String task_last_mac) {
+        this.task_last_mac = task_last_mac;
+    }
+
+    public long getTask_expected_finish_time() {
+        return task_expected_finish_time;
+    }
+
+    public void setTask_expected_finish_time(long task_expected_finish_time) {
+        this.task_expected_finish_time = task_expected_finish_time;
+    }
+
+    public List<DownloadTaskModel> getDownloadTaskModelList() {
+        if(downloadTaskModelList == null )
+            downloadTaskModelList = new ArrayList<>();
+        return downloadTaskModelList;
+    }
+
+    public void setDownloadTaskModelList(List<DownloadTaskModel> downloadTaskModelList) {
+        this.downloadTaskModelList = downloadTaskModelList;
+    }
+}

+ 46 - 0
scheduler/src/main/java/cn/sagacloud/mybatis/service/TaskService.java

@@ -0,0 +1,46 @@
+package cn.sagacloud.mybatis.service;
+
+import cn.sagacloud.mybatis.dao.TaskDAO;
+import cn.sagacloud.mybatis.model.TaskModel;
+import com.google.inject.*;
+import org.mybatis.guice.transactional.Transactional;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+public class TaskService {
+    public TaskDAO taskDAO;
+
+    @Inject
+    public TaskService(TaskDAO taskDAO){
+        this.taskDAO = taskDAO;
+    }
+    @Transactional
+    public boolean addTask(TaskModel task) throws Exception {
+        if(task.getDownloadTaskModelList().size() == 0)
+            throw new Exception("不能添加没有下载文件的任务");
+        if(taskDAO.addTask(task) && taskDAO.addDownload(task))
+            return true;
+        return false;
+    }
+    @Transactional
+    public boolean updateTask(TaskModel task) throws Exception {
+        if(task.getDownloadTaskModelList().size() == 0)
+            throw new Exception("不能添加没有下载文件的任务");
+        taskDAO.addTask(task);
+        taskDAO.addDownload(task);
+        return false;
+    }
+
+
+    public ArrayList<TaskModel> getAllTaskByStatus(List<Integer> statusList) throws Exception {
+
+        return null;
+    }
+
+    public TaskModel getTaskById(int id) throws Exception {
+
+        return null;
+    }
+}

+ 39 - 0
scheduler/src/main/java/cn/sagacloud/pojo/ChannelHandlerContextWrapper.java

@@ -0,0 +1,39 @@
+package cn.sagacloud.pojo;
+
+import io.netty.channel.ChannelHandlerContext;
+
+public class ChannelHandlerContextWrapper {
+    private ChannelHandlerContext ctx;  // 通信handler
+    private long lastRejectTime;        // unix时间片, 精确到秒
+    private String macAddr;             // mac地址
+
+    public ChannelHandlerContextWrapper(ChannelHandlerContext ctx) {
+        this.ctx = ctx;
+        this.lastRejectTime = 0;
+        macAddr = null;
+    }
+
+    public String getMacAddr() {
+        return macAddr;
+    }
+
+    public void setMacAddr(String macAddr) {
+        this.macAddr = macAddr;
+    }
+
+    public ChannelHandlerContext getCtx() {
+        return ctx;
+    }
+
+//    public void setCtx(ChannelHandlerContext chx) {
+//        this.ctx = chx;
+//    }
+
+    public long getLastRejectTime() {
+        return lastRejectTime;
+    }
+
+    public void setLastRejectTime(long lastRejectTime) {
+        this.lastRejectTime = lastRejectTime;
+    }
+}

+ 29 - 0
scheduler/src/main/java/cn/sagacloud/pojo/Command.java

@@ -0,0 +1,29 @@
+package cn.sagacloud.pojo;
+/*
+ * Author: Jxing
+ * Create Time: 2019/3/11
+ */
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public enum Command {
+    SendTask,
+    RefuseTask,
+    AcceptTask,
+    DownloadError,
+    CommandError,
+    TaskSuccess;
+    private static ArrayList<Command> cmdList;
+    static{
+        cmdList = new ArrayList<>();
+        cmdList.addAll(Arrays.asList(Command.values()));
+    }
+    public static Command getCmdById(int index) {
+        if(index > -1 && index < cmdList.size()){
+            return cmdList.get(index);
+        }
+        return null;
+    }
+}

+ 23 - 0
scheduler/src/main/java/cn/sagacloud/pojo/Config.java

@@ -0,0 +1,23 @@
+package cn.sagacloud.pojo;
+
+public class Config {
+
+    private int port;
+    private String mysql;
+
+    public int getPort() {
+        return port;
+    }
+
+    public void setPort(int port) {
+        this.port = port;
+    }
+
+    public String getMysql() {
+        return mysql;
+    }
+
+    public void setMysql(String mysql) {
+        this.mysql = mysql;
+    }
+}

+ 9 - 0
scheduler/src/main/java/cn/sagacloud/pojo/TaskStatus.java

@@ -0,0 +1,9 @@
+package cn.sagacloud.pojo;
+/*
+ * Author: Jxing
+ * Create Time: 2019/3/11
+ */
+
+public enum TaskStatus {
+    Waiting, Sending, Sent, FileDownloadException, CommandExecuteException, Finished
+}

+ 805 - 0
scheduler/src/main/java/cn/sagacloud/proto/MessageProto.java

@@ -0,0 +1,805 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: MessageProto.proto
+
+package cn.sagacloud.proto;
+
+public final class MessageProto {
+  private MessageProto() {}
+  public static void registerAllExtensions(
+      com.google.protobuf.ExtensionRegistryLite registry) {
+  }
+
+  public static void registerAllExtensions(
+      com.google.protobuf.ExtensionRegistry registry) {
+    registerAllExtensions(
+        (com.google.protobuf.ExtensionRegistryLite) registry);
+  }
+  public interface MessageOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:cn.sagacloud.proto.Message)
+      com.google.protobuf.MessageOrBuilder {
+
+    /**
+     * <code>int32 cmd = 1;</code>
+     */
+    int getCmd();
+
+    /**
+     * <code>string className = 2;</code>
+     */
+    java.lang.String getClassName();
+    /**
+     * <code>string className = 2;</code>
+     */
+    com.google.protobuf.ByteString
+        getClassNameBytes();
+
+    /**
+     * <code>string content = 3;</code>
+     */
+    java.lang.String getContent();
+    /**
+     * <code>string content = 3;</code>
+     */
+    com.google.protobuf.ByteString
+        getContentBytes();
+  }
+  /**
+   * Protobuf type {@code cn.sagacloud.proto.Message}
+   */
+  public  static final class Message extends
+      com.google.protobuf.GeneratedMessageV3 implements
+      // @@protoc_insertion_point(message_implements:cn.sagacloud.proto.Message)
+      MessageOrBuilder {
+  private static final long serialVersionUID = 0L;
+    // Use Message.newBuilder() to construct.
+    private Message(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
+      super(builder);
+    }
+    private Message() {
+      className_ = "";
+      content_ = "";
+    }
+
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+    getUnknownFields() {
+      return this.unknownFields;
+    }
+    private Message(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      this();
+      if (extensionRegistry == null) {
+        throw new java.lang.NullPointerException();
+      }
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            case 8: {
+
+              cmd_ = input.readInt32();
+              break;
+            }
+            case 18: {
+              java.lang.String s = input.readStringRequireUtf8();
+
+              className_ = s;
+              break;
+            }
+            case 26: {
+              java.lang.String s = input.readStringRequireUtf8();
+
+              content_ = s;
+              break;
+            }
+            default: {
+              if (!parseUnknownField(
+                  input, unknownFields, extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return cn.sagacloud.proto.MessageProto.internal_static_cn_sagacloud_proto_Message_descriptor;
+    }
+
+    @java.lang.Override
+    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return cn.sagacloud.proto.MessageProto.internal_static_cn_sagacloud_proto_Message_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              cn.sagacloud.proto.MessageProto.Message.class, cn.sagacloud.proto.MessageProto.Message.Builder.class);
+    }
+
+    public static final int CMD_FIELD_NUMBER = 1;
+    private int cmd_;
+    /**
+     * <code>int32 cmd = 1;</code>
+     */
+    public int getCmd() {
+      return cmd_;
+    }
+
+    public static final int CLASSNAME_FIELD_NUMBER = 2;
+    private volatile java.lang.Object className_;
+    /**
+     * <code>string className = 2;</code>
+     */
+    public java.lang.String getClassName() {
+      java.lang.Object ref = className_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        className_ = s;
+        return s;
+      }
+    }
+    /**
+     * <code>string className = 2;</code>
+     */
+    public com.google.protobuf.ByteString
+        getClassNameBytes() {
+      java.lang.Object ref = className_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        className_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    public static final int CONTENT_FIELD_NUMBER = 3;
+    private volatile java.lang.Object content_;
+    /**
+     * <code>string content = 3;</code>
+     */
+    public java.lang.String getContent() {
+      java.lang.Object ref = content_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        content_ = s;
+        return s;
+      }
+    }
+    /**
+     * <code>string content = 3;</code>
+     */
+    public com.google.protobuf.ByteString
+        getContentBytes() {
+      java.lang.Object ref = content_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        content_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    private byte memoizedIsInitialized = -1;
+    @java.lang.Override
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized == 1) return true;
+      if (isInitialized == 0) return false;
+
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    @java.lang.Override
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      if (cmd_ != 0) {
+        output.writeInt32(1, cmd_);
+      }
+      if (!getClassNameBytes().isEmpty()) {
+        com.google.protobuf.GeneratedMessageV3.writeString(output, 2, className_);
+      }
+      if (!getContentBytes().isEmpty()) {
+        com.google.protobuf.GeneratedMessageV3.writeString(output, 3, content_);
+      }
+      unknownFields.writeTo(output);
+    }
+
+    @java.lang.Override
+    public int getSerializedSize() {
+      int size = memoizedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (cmd_ != 0) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt32Size(1, cmd_);
+      }
+      if (!getClassNameBytes().isEmpty()) {
+        size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, className_);
+      }
+      if (!getContentBytes().isEmpty()) {
+        size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, content_);
+      }
+      size += unknownFields.getSerializedSize();
+      memoizedSize = size;
+      return size;
+    }
+
+    @java.lang.Override
+    public boolean equals(final java.lang.Object obj) {
+      if (obj == this) {
+       return true;
+      }
+      if (!(obj instanceof cn.sagacloud.proto.MessageProto.Message)) {
+        return super.equals(obj);
+      }
+      cn.sagacloud.proto.MessageProto.Message other = (cn.sagacloud.proto.MessageProto.Message) obj;
+
+      if (getCmd()
+          != other.getCmd()) return false;
+      if (!getClassName()
+          .equals(other.getClassName())) return false;
+      if (!getContent()
+          .equals(other.getContent())) return false;
+      if (!unknownFields.equals(other.unknownFields)) return false;
+      return true;
+    }
+
+    @java.lang.Override
+    public int hashCode() {
+      if (memoizedHashCode != 0) {
+        return memoizedHashCode;
+      }
+      int hash = 41;
+      hash = (19 * hash) + getDescriptor().hashCode();
+      hash = (37 * hash) + CMD_FIELD_NUMBER;
+      hash = (53 * hash) + getCmd();
+      hash = (37 * hash) + CLASSNAME_FIELD_NUMBER;
+      hash = (53 * hash) + getClassName().hashCode();
+      hash = (37 * hash) + CONTENT_FIELD_NUMBER;
+      hash = (53 * hash) + getContent().hashCode();
+      hash = (29 * hash) + unknownFields.hashCode();
+      memoizedHashCode = hash;
+      return hash;
+    }
+
+    public static cn.sagacloud.proto.MessageProto.Message parseFrom(
+        java.nio.ByteBuffer data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static cn.sagacloud.proto.MessageProto.Message parseFrom(
+        java.nio.ByteBuffer data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static cn.sagacloud.proto.MessageProto.Message parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static cn.sagacloud.proto.MessageProto.Message parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static cn.sagacloud.proto.MessageProto.Message parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static cn.sagacloud.proto.MessageProto.Message parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static cn.sagacloud.proto.MessageProto.Message parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3
+          .parseWithIOException(PARSER, input);
+    }
+    public static cn.sagacloud.proto.MessageProto.Message parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3
+          .parseWithIOException(PARSER, input, extensionRegistry);
+    }
+    public static cn.sagacloud.proto.MessageProto.Message parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3
+          .parseDelimitedWithIOException(PARSER, input);
+    }
+    public static cn.sagacloud.proto.MessageProto.Message parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3
+          .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
+    }
+    public static cn.sagacloud.proto.MessageProto.Message parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3
+          .parseWithIOException(PARSER, input);
+    }
+    public static cn.sagacloud.proto.MessageProto.Message parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3
+          .parseWithIOException(PARSER, input, extensionRegistry);
+    }
+
+    @java.lang.Override
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder() {
+      return DEFAULT_INSTANCE.toBuilder();
+    }
+    public static Builder newBuilder(cn.sagacloud.proto.MessageProto.Message prototype) {
+      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+    }
+    @java.lang.Override
+    public Builder toBuilder() {
+      return this == DEFAULT_INSTANCE
+          ? new Builder() : new Builder().mergeFrom(this);
+    }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code cn.sagacloud.proto.Message}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
+        // @@protoc_insertion_point(builder_implements:cn.sagacloud.proto.Message)
+        cn.sagacloud.proto.MessageProto.MessageOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return cn.sagacloud.proto.MessageProto.internal_static_cn_sagacloud_proto_Message_descriptor;
+      }
+
+      @java.lang.Override
+      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return cn.sagacloud.proto.MessageProto.internal_static_cn_sagacloud_proto_Message_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                cn.sagacloud.proto.MessageProto.Message.class, cn.sagacloud.proto.MessageProto.Message.Builder.class);
+      }
+
+      // Construct using cn.sagacloud.proto.MessageProto.Message.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessageV3
+                .alwaysUseFieldBuilders) {
+        }
+      }
+      @java.lang.Override
+      public Builder clear() {
+        super.clear();
+        cmd_ = 0;
+
+        className_ = "";
+
+        content_ = "";
+
+        return this;
+      }
+
+      @java.lang.Override
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return cn.sagacloud.proto.MessageProto.internal_static_cn_sagacloud_proto_Message_descriptor;
+      }
+
+      @java.lang.Override
+      public cn.sagacloud.proto.MessageProto.Message getDefaultInstanceForType() {
+        return cn.sagacloud.proto.MessageProto.Message.getDefaultInstance();
+      }
+
+      @java.lang.Override
+      public cn.sagacloud.proto.MessageProto.Message build() {
+        cn.sagacloud.proto.MessageProto.Message result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      @java.lang.Override
+      public cn.sagacloud.proto.MessageProto.Message buildPartial() {
+        cn.sagacloud.proto.MessageProto.Message result = new cn.sagacloud.proto.MessageProto.Message(this);
+        result.cmd_ = cmd_;
+        result.className_ = className_;
+        result.content_ = content_;
+        onBuilt();
+        return result;
+      }
+
+      @java.lang.Override
+      public Builder clone() {
+        return super.clone();
+      }
+      @java.lang.Override
+      public Builder setField(
+          com.google.protobuf.Descriptors.FieldDescriptor field,
+          java.lang.Object value) {
+        return super.setField(field, value);
+      }
+      @java.lang.Override
+      public Builder clearField(
+          com.google.protobuf.Descriptors.FieldDescriptor field) {
+        return super.clearField(field);
+      }
+      @java.lang.Override
+      public Builder clearOneof(
+          com.google.protobuf.Descriptors.OneofDescriptor oneof) {
+        return super.clearOneof(oneof);
+      }
+      @java.lang.Override
+      public Builder setRepeatedField(
+          com.google.protobuf.Descriptors.FieldDescriptor field,
+          int index, java.lang.Object value) {
+        return super.setRepeatedField(field, index, value);
+      }
+      @java.lang.Override
+      public Builder addRepeatedField(
+          com.google.protobuf.Descriptors.FieldDescriptor field,
+          java.lang.Object value) {
+        return super.addRepeatedField(field, value);
+      }
+      @java.lang.Override
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof cn.sagacloud.proto.MessageProto.Message) {
+          return mergeFrom((cn.sagacloud.proto.MessageProto.Message)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(cn.sagacloud.proto.MessageProto.Message other) {
+        if (other == cn.sagacloud.proto.MessageProto.Message.getDefaultInstance()) return this;
+        if (other.getCmd() != 0) {
+          setCmd(other.getCmd());
+        }
+        if (!other.getClassName().isEmpty()) {
+          className_ = other.className_;
+          onChanged();
+        }
+        if (!other.getContent().isEmpty()) {
+          content_ = other.content_;
+          onChanged();
+        }
+        this.mergeUnknownFields(other.unknownFields);
+        onChanged();
+        return this;
+      }
+
+      @java.lang.Override
+      public final boolean isInitialized() {
+        return true;
+      }
+
+      @java.lang.Override
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        cn.sagacloud.proto.MessageProto.Message parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (cn.sagacloud.proto.MessageProto.Message) e.getUnfinishedMessage();
+          throw e.unwrapIOException();
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+
+      private int cmd_ ;
+      /**
+       * <code>int32 cmd = 1;</code>
+       */
+      public int getCmd() {
+        return cmd_;
+      }
+      /**
+       * <code>int32 cmd = 1;</code>
+       */
+      public Builder setCmd(int value) {
+        
+        cmd_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>int32 cmd = 1;</code>
+       */
+      public Builder clearCmd() {
+        
+        cmd_ = 0;
+        onChanged();
+        return this;
+      }
+
+      private java.lang.Object className_ = "";
+      /**
+       * <code>string className = 2;</code>
+       */
+      public java.lang.String getClassName() {
+        java.lang.Object ref = className_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          className_ = s;
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>string className = 2;</code>
+       */
+      public com.google.protobuf.ByteString
+          getClassNameBytes() {
+        java.lang.Object ref = className_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          className_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>string className = 2;</code>
+       */
+      public Builder setClassName(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  
+        className_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>string className = 2;</code>
+       */
+      public Builder clearClassName() {
+        
+        className_ = getDefaultInstance().getClassName();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>string className = 2;</code>
+       */
+      public Builder setClassNameBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  checkByteStringIsUtf8(value);
+        
+        className_ = value;
+        onChanged();
+        return this;
+      }
+
+      private java.lang.Object content_ = "";
+      /**
+       * <code>string content = 3;</code>
+       */
+      public java.lang.String getContent() {
+        java.lang.Object ref = content_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          content_ = s;
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>string content = 3;</code>
+       */
+      public com.google.protobuf.ByteString
+          getContentBytes() {
+        java.lang.Object ref = content_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          content_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>string content = 3;</code>
+       */
+      public Builder setContent(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  
+        content_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>string content = 3;</code>
+       */
+      public Builder clearContent() {
+        
+        content_ = getDefaultInstance().getContent();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>string content = 3;</code>
+       */
+      public Builder setContentBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  checkByteStringIsUtf8(value);
+        
+        content_ = value;
+        onChanged();
+        return this;
+      }
+      @java.lang.Override
+      public final Builder setUnknownFields(
+          final com.google.protobuf.UnknownFieldSet unknownFields) {
+        return super.setUnknownFields(unknownFields);
+      }
+
+      @java.lang.Override
+      public final Builder mergeUnknownFields(
+          final com.google.protobuf.UnknownFieldSet unknownFields) {
+        return super.mergeUnknownFields(unknownFields);
+      }
+
+
+      // @@protoc_insertion_point(builder_scope:cn.sagacloud.proto.Message)
+    }
+
+    // @@protoc_insertion_point(class_scope:cn.sagacloud.proto.Message)
+    private static final cn.sagacloud.proto.MessageProto.Message DEFAULT_INSTANCE;
+    static {
+      DEFAULT_INSTANCE = new cn.sagacloud.proto.MessageProto.Message();
+    }
+
+    public static cn.sagacloud.proto.MessageProto.Message getDefaultInstance() {
+      return DEFAULT_INSTANCE;
+    }
+
+    private static final com.google.protobuf.Parser<Message>
+        PARSER = new com.google.protobuf.AbstractParser<Message>() {
+      @java.lang.Override
+      public Message parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new Message(input, extensionRegistry);
+      }
+    };
+
+    public static com.google.protobuf.Parser<Message> parser() {
+      return PARSER;
+    }
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<Message> getParserForType() {
+      return PARSER;
+    }
+
+    @java.lang.Override
+    public cn.sagacloud.proto.MessageProto.Message getDefaultInstanceForType() {
+      return DEFAULT_INSTANCE;
+    }
+
+  }
+
+  private static final com.google.protobuf.Descriptors.Descriptor
+    internal_static_cn_sagacloud_proto_Message_descriptor;
+  private static final 
+    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+      internal_static_cn_sagacloud_proto_Message_fieldAccessorTable;
+
+  public static com.google.protobuf.Descriptors.FileDescriptor
+      getDescriptor() {
+    return descriptor;
+  }
+  private static  com.google.protobuf.Descriptors.FileDescriptor
+      descriptor;
+  static {
+    java.lang.String[] descriptorData = {
+      "\n\022MessageProto.proto\022\022cn.sagacloud.proto" +
+      "\":\n\007Message\022\013\n\003cmd\030\001 \001(\005\022\021\n\tclassName\030\002 " +
+      "\001(\t\022\017\n\007content\030\003 \001(\tB\020B\014MessageProtoH\001b\006" +
+      "proto3"
+    };
+    com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
+        new com.google.protobuf.Descriptors.FileDescriptor.    InternalDescriptorAssigner() {
+          public com.google.protobuf.ExtensionRegistry assignDescriptors(
+              com.google.protobuf.Descriptors.FileDescriptor root) {
+            descriptor = root;
+            return null;
+          }
+        };
+    com.google.protobuf.Descriptors.FileDescriptor
+      .internalBuildGeneratedFileFrom(descriptorData,
+        new com.google.protobuf.Descriptors.FileDescriptor[] {
+        }, assigner);
+    internal_static_cn_sagacloud_proto_Message_descriptor =
+      getDescriptor().getMessageTypes().get(0);
+    internal_static_cn_sagacloud_proto_Message_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+        internal_static_cn_sagacloud_proto_Message_descriptor,
+        new java.lang.String[] { "Cmd", "ClassName", "Content", });
+  }
+
+  // @@protoc_insertion_point(outer_class_scope)
+}

+ 19 - 0
scheduler/src/main/java/cn/sagacloud/proto/MessageUtil.java

@@ -0,0 +1,19 @@
+package cn.sagacloud.proto;
+/*
+ * Author: Jxing
+ * Create Time: 2019/3/22
+ */
+
+public class MessageUtil {
+    public static MessageProto.Message buildMessage(int cmd, String className, String content){
+        MessageProto.Message.Builder builder = MessageProto.Message.newBuilder();
+        builder.setCmd(cmd);
+        builder.setClassName(className);
+        builder.setContent(content);
+        return builder.build();
+    }
+
+    public static void printMessage(MessageProto.Message msg){
+        System.out.println("msg : cmd : " + msg.getCmd() + ", className : " + msg.getClassName() + ", content : " + msg.getContent());
+    }
+}

+ 110 - 0
scheduler/src/main/java/cn/sagacloud/server/SchedulerHandler.java

@@ -0,0 +1,110 @@
+package cn.sagacloud.server;
+/*
+ * Author: Jxing
+ * Create Time: 2019/3/20
+ */
+
+import cn.sagacloud.pojo.ChannelHandlerContextWrapper;
+import cn.sagacloud.pojo.Command;
+import cn.sagacloud.pojo.TaskStatus;
+import cn.sagacloud.proto.MessageUtil;
+import cn.sagacloud.proto.MessageProto;
+import cn.sagacloud.utils.CommonUtil;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundHandlerAdapter;
+
+import java.net.SocketAddress;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class SchedulerHandler extends ChannelInboundHandlerAdapter {
+    ArrayList<ChannelHandlerContextWrapper> clientList;
+    private ChannelHandlerContextWrapper ctxw;
+    public static Map<TaskStatus, Set<Command>> allowedStatusCommand = new ConcurrentHashMap<>();
+    static {
+        allowedStatusCommand.put(TaskStatus.Waiting, CommonUtil.createSet(Command.TaskSuccess));
+        allowedStatusCommand.put(TaskStatus.Sending, CommonUtil.createSet(Command.AcceptTask, Command.RefuseTask, Command.TaskSuccess));
+        allowedStatusCommand.put(TaskStatus.Sent, CommonUtil.createSet(Command.CommandError, Command.DownloadError, Command.TaskSuccess));
+        allowedStatusCommand.put(TaskStatus.FileDownloadException, CommonUtil.createSet(Command.TaskSuccess));
+        allowedStatusCommand.put(TaskStatus.CommandExecuteException, CommonUtil.createSet(Command.TaskSuccess));
+        allowedStatusCommand.put(TaskStatus.Finished, CommonUtil.createSet());
+    }
+
+    public SchedulerHandler(ArrayList<ChannelHandlerContextWrapper> clientList) {
+        this.clientList = clientList;
+    }
+
+    /**
+     * 刚添加上handler的时候    1
+     * @param ctx
+     */
+    @Override
+    public void handlerAdded(ChannelHandlerContext ctx) {
+        SocketAddress addr = ctx.channel().remoteAddress();
+        System.out.println("client incoming");
+    }
+
+    /**
+     *  客户端活动状态         2
+     * @param ctx
+     */
+    @Override
+    public void channelActive(ChannelHandlerContext ctx) {
+        ctxw = new ChannelHandlerContextWrapper(ctx);
+        this.clientList.add(ctxw);
+        //ctx.channel().writeAndFlush("connected !"+System.currentTimeMillis());
+    }
+
+    /**
+     * 客户端服务器互发消息      3
+     * @param ctx
+     * @param msg
+     * @throws Exception
+     */
+    @Override
+    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
+        try {
+            // Do something with msg
+            MessageProto.Message message = (MessageProto.Message)msg;
+            MessageUtil.printMessage(message);
+            MessageProto.Message myMsg = MessageUtil.buildMessage(message.getCmd() + 1,
+                    message.getClassName() + " from server",
+                    message.getContent() + " from server");
+
+            ctx.writeAndFlush(myMsg);  // 异步
+        } finally {
+            // 如果ctx write 或 writeAndFlush过的话, 就不用释放msg
+            //ReferenceCountUtil.release(msg);
+        }
+    }
+
+    /**
+     * 客户端异常原因  4
+     * @param ctx
+     * @param cause
+     */
+    @Override
+    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
+        System.out.println("client exceptionCaught : " + cause.getMessage());
+    }
+
+    /**
+     * 客户端非活动状态  5
+     * @param ctx
+     */
+    @Override
+    public void channelInactive(ChannelHandlerContext ctx) {
+        System.out.println("client channelInactive");
+    }
+
+    /**
+     * 客户端断开连接 6
+     * @param ctx
+     */
+    @Override
+    public void handlerRemoved(ChannelHandlerContext ctx) {
+        this.clientList.remove(ctxw);
+    }
+}

+ 80 - 0
scheduler/src/main/java/cn/sagacloud/server/Server.java

@@ -0,0 +1,80 @@
+package cn.sagacloud.server;
+/*
+ * Author: Jxing
+ * Create Time: 2019/3/20
+ */
+
+import cn.sagacloud.pojo.ChannelHandlerContextWrapper;
+import cn.sagacloud.pojo.Config;
+import cn.sagacloud.proto.MessageProto;
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.ChannelOption;
+import io.netty.channel.ChannelPipeline;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.channel.socket.nio.NioServerSocketChannel;
+import io.netty.handler.codec.protobuf.ProtobufDecoder;
+import io.netty.handler.codec.protobuf.ProtobufEncoder;
+import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
+import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
+import org.yaml.snakeyaml.Yaml;
+
+import java.util.ArrayList;
+
+public class Server {
+    ServerBootstrap bootstrap = new ServerBootstrap();
+    private NioEventLoopGroup acceptGroup = new NioEventLoopGroup();
+    private NioEventLoopGroup workerGroup = new NioEventLoopGroup();
+    private Channel channel = null;
+    Config config;
+    ArrayList<ChannelHandlerContextWrapper> clientList = new ArrayList<>();
+    public Server(){
+        // 初始化serverSocket
+        bootstrap.group(acceptGroup, workerGroup)
+                .channel(NioServerSocketChannel.class)
+                .option(ChannelOption.SO_BROADCAST, true)
+                .childHandler(new ChannelInitializer<SocketChannel>(){
+                    @Override
+                    protected void initChannel(SocketChannel ch) throws Exception {
+                        ChannelPipeline pipeline = ch.pipeline();
+                        pipeline.addLast(new ProtobufVarint32FrameDecoder());
+                        // 设置解码
+                        pipeline.addLast("decoder", new ProtobufDecoder(MessageProto.Message.getDefaultInstance()));
+                        pipeline.addLast(new ProtobufVarint32LengthFieldPrepender());
+                        // 设置编码
+                        pipeline.addLast("encoder", new ProtobufEncoder());
+                        pipeline.addLast(new SchedulerHandler(clientList));
+
+                    }
+                })
+        .option(ChannelOption.SO_BACKLOG, 128)
+        .childOption(ChannelOption.SO_KEEPALIVE, true);
+        // 初始化配置
+        config = new Yaml().loadAs(Server.class.getClassLoader().getResourceAsStream("config.yml"), Config.class);
+        // 初始化Task(从sql到内存)
+
+    }
+
+    public void start() throws InterruptedException {
+        try {
+            // 启动服务
+            channel = bootstrap.bind(config.getPort()).sync().channel();
+            //println("Revit Dispatcher start success $port");
+            channel.closeFuture().sync();
+        } finally {
+            workerGroup.shutdownGracefully();
+            acceptGroup.shutdownGracefully();
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+//        int port = 6666;
+//        if (args.length > 0) {
+//            port = Integer.parseInt(args[0]);
+//        }
+        new Server().start();
+    }
+
+}

+ 32 - 0
scheduler/src/main/java/cn/sagacloud/utils/CommonUtil.java

@@ -0,0 +1,32 @@
+package cn.sagacloud.utils;
+/*
+ * Author: Jxing
+ * Create Time: 2019/3/12
+ */
+
+import cn.sagacloud.pojo.Command;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.util.HashSet;
+import java.util.Set;
+
+public class CommonUtil {
+    public static Set<Command> createSet(Command... elements) {
+        Set<Command> set = new HashSet<>();
+        for (Command e : elements) {
+            set.add(e);
+        }
+        return set;
+    }
+
+    public static byte[] getBytes(char[] chars) {
+        Charset cs = Charset.forName("UTF-8");
+        CharBuffer cb = CharBuffer.allocate(chars.length);
+        cb.put(chars);
+        cb.flip();
+        ByteBuffer bb = cs.encode(cb);
+        return bb.array();
+    }
+}

+ 11 - 0
scheduler/src/main/proto/MessageProto.proto

@@ -0,0 +1,11 @@
+syntax = "proto3";
+
+package cn.sagacloud.proto;
+option optimize_for = SPEED;
+//option java_package = "cn.sagacloud.server.proto";
+option java_outer_classname = "MessageProto";
+message Message{
+    int32 cmd = 1;
+    string className = 2;
+    string content = 3;
+}

+ 2 - 0
scheduler/src/main/resources/config.yml

@@ -0,0 +1,2 @@
+port: 6666
+mysql: server=127.0.0.1;uid=root;pwd=123456

+ 32 - 0
scheduler/src/main/resources/log4j.properties

@@ -0,0 +1,32 @@
+### 设置###
+log4j.rootLogger = debug,stdout,D,E,I
+
+### 输出信息到控制抬 ###
+log4j.appender.stdout = org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Target = System.out
+log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
+
+### 输出DEBUG 级别以上的日志到=E://logs/error.log ###
+log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
+log4j.appender.D.File = E:/logs/log.log
+log4j.appender.D.Append = true
+log4j.appender.D.Threshold = DEBUG
+log4j.appender.D.layout = org.apache.log4j.PatternLayout
+log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n
+
+### 输出ERROR 级别以上的日志到=E://logs/error.log ###
+log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
+log4j.appender.E.File =E:/logs/error.log
+log4j.appender.E.Append = true
+log4j.appender.E.Threshold = ERROR
+log4j.appender.E.layout = org.apache.log4j.PatternLayout
+log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n
+
+### 输出INFO 级别以上的日志到=E://logs/error.log ###
+log4j.appender.I = org.apache.log4j.DailyRollingFileAppender
+log4j.appender.I.File =E:/logs/info.log
+log4j.appender.I.Append = true
+log4j.appender.I.Threshold = INFO
+log4j.appender.I.layout = org.apache.log4j.PatternLayout
+log4j.appender.I.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

+ 15 - 0
scheduler/src/main/resources/mapper/TaskMap.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
+<mapper namespace="cn.sagacloud.mybatis.mapper.TaskMapper">
+    <insert id="addTask" parameterType="cn.sagacloud.mybatis.model.TaskModel" useGeneratedKeys="true" keyProperty="id">
+        INSERT INTO `task`(task_name, task_cmd, task_param, task_status, task_result_json, task_last_mac, task_expected_finish_time)
+        VALUE(#{task_name},#{task_cmd},#{task_param},#{task_status},#{task_result_json},#{task_last_mac},#{task_expected_finish_time});
+    </insert>
+
+    <insert id="addDownload" parameterType="cn.sagacloud.mybatis.model.DownloadTaskModel" useGeneratedKeys="true" keyProperty="list.id">
+        INSERT INTO `download`(task_id,task_url,task_md5) VALUES
+        <foreach collection="list" item="item" separator=",">
+            (#{taskId},#{item.task_url},#{item.task_md5})
+        </foreach>
+    </insert>
+</mapper>

+ 44 - 0
scheduler/src/main/resources/mybatis-config.xml

@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+
+<!DOCTYPE configuration
+        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-config.dtd">
+
+<configuration>
+    <!--<settings>-->
+        <!--输出日志-->
+        <!--<setting name="logImpl" value="STDOUT_LOGGING" />-->
+    <!--</settings>-->
+
+    <typeHandlers>
+        <!--<typeHandler jdbcType="INTEGER" javaType="java.lang.Integer" handler="com.sagacloud.utils.typeHandler.NullToZero"/>-->
+    </typeHandlers>
+
+    <environments default="development">
+        <environment id="development">
+            <transactionManager type="JDBC">
+            </transactionManager>
+            <dataSource type="POOLED">
+                <property name="driver" value="com.mysql.jdbc.Driver"/>
+                <!--<property name="url" value="jdbc:mysql://101.201.234.108:3306/venders?serverTimezone=UTC"/>-->
+                <!--<property name="url" value="jdbc:mysql://172.16.3.12:3306/venders?serverTimezone=UTC"/>-->
+                <property name="url" value="jdbc:mysql://127.0.0.1:3306/scheduler?serverTimezone=UTC"/>
+                <!--<property name="username" value="pbsage"/>-->
+                <property name="username" value="root"/>
+                <property name="password" value="123456"/>
+            </dataSource>
+        </environment>
+    </environments>
+
+    <mappers>
+        <mapper resource="mapper/TaskMap.xml"/>
+        <!--<mapper resource="mapper/BrandMap.xml"/>-->
+        <!--<mapper resource="mapper/ProductMap.xml"/>-->
+        <!--<mapper resource="mapper/SpecificationMap.xml"/>-->
+        <!--<mapper resource="mapper/ContractMap.xml"/>-->
+        <!--<mapper resource="mapper/AuxiliaryMap.xml"/>-->
+    </mappers>
+
+
+</configuration>

+ 27 - 0
scheduler/src/test/java/cn/sagacloud/mybatis/TaskTest.java

@@ -0,0 +1,27 @@
+package cn.sagacloud.mybatis;
+
+import cn.sagacloud.guice.InjectorInit;
+import cn.sagacloud.mybatis.dao.TaskDAO;
+import cn.sagacloud.mybatis.model.DownloadTaskModel;
+import cn.sagacloud.mybatis.model.TaskModel;
+import cn.sagacloud.mybatis.service.TaskService;
+import com.google.inject.Inject;
+import org.junit.Test;
+
+public class TaskTest {
+    TaskService service = InjectorInit.getInjector().getInstance(TaskService.class);
+    @Test
+    public void addTask() throws Exception {
+        //service = new TaskService(new TaskDAO());
+        TaskModel task = new TaskModel();
+        task.setTask_cmd("1");
+        task.setTask_name("a");
+        task.setTask_status(0);
+        task.setTask_expected_finish_time(60);
+        DownloadTaskModel down = new DownloadTaskModel();
+        down.setTask_url("http://down.xitongwanjia.com/windows10_64_201903.iso");
+        down.setTask_md5("fagdasfasdsfsdff");
+        task.getDownloadTaskModelList().add(down);
+        System.out.println(service.addTask(task));
+    }
+}

+ 3 - 0
settings.gradle

@@ -0,0 +1,3 @@
+rootProject.name = 'server'
+include 'scheduler'
+