func commandVerticalSplitClone(wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) worker.Worker { tables := subFlags.String("tables", "", "comma separated list of tables to replicate (used for vertical split)") strategy := subFlags.String("strategy", "", "which strategy to use for restore, use 'mysqlctl multirestore -strategy=-help' for more info") sourceReaderCount := subFlags.Int("source_reader_count", defaultSourceReaderCount, "number of concurrent streaming queries to use on the source") destinationPackCount := subFlags.Int("destination_pack_count", defaultDestinationPackCount, "number of packets to pack in one destination insert") minTableSizeForSplit := subFlags.Int("min_table_size_for_split", defaultMinTableSizeForSplit, "tables bigger than this size on disk in bytes will be split into source_reader_count chunks if possible") destinationWriterCount := subFlags.Int("destination_writer_count", defaultDestinationWriterCount, "number of concurrent RPCs to execute on the destination") subFlags.Parse(args) if subFlags.NArg() != 1 { log.Fatalf("command VerticalSplitClone requires <destination keyspace/shard>") } keyspace, shard := shardParamToKeyspaceShard(subFlags.Arg(0)) var tableArray []string if *tables != "" { tableArray = strings.Split(*tables, ",") } worker, err := worker.NewVerticalSplitCloneWorker(wr, *cell, keyspace, shard, tableArray, *strategy, *sourceReaderCount, *destinationPackCount, uint64(*minTableSizeForSplit), *destinationWriterCount) if err != nil { log.Fatalf("cannot create worker: %v", err) } return worker }
func interactiveVerticalSplitClone(wr *wrangler.Wrangler, w http.ResponseWriter, r *http.Request) { if err := r.ParseForm(); err != nil { httpError(w, "cannot parse form: %s", err) return } keyspace := r.FormValue("keyspace") if keyspace == "" { // display the list of possible keyspaces to choose from result := make(map[string]interface{}) keyspaces, err := keyspacesWithServedFrom(wr) if err != nil { result["Error"] = err.Error() } else { result["Keyspaces"] = keyspaces } executeTemplate(w, verticalSplitCloneTemplate, result) return } tables := r.FormValue("tables") if tables == "" { // display the input form result := make(map[string]interface{}) result["Keyspace"] = keyspace result["DefaultSourceReaderCount"] = fmt.Sprintf("%v", defaultSourceReaderCount) result["DefaultDestinationPackCount"] = fmt.Sprintf("%v", defaultDestinationPackCount) result["DefaultMinTableSizeForSplit"] = fmt.Sprintf("%v", defaultMinTableSizeForSplit) result["DefaultDestinationWriterCount"] = fmt.Sprintf("%v", defaultDestinationWriterCount) executeTemplate(w, verticalSplitCloneTemplate2, result) return } tableArray := strings.Split(tables, ",") // get other parameters strategy := r.FormValue("strategy") sourceReaderCountStr := r.FormValue("sourceReaderCount") sourceReaderCount, err := strconv.ParseInt(sourceReaderCountStr, 0, 64) if err != nil { httpError(w, "cannot parse sourceReaderCount: %s", err) return } destinationPackCountStr := r.FormValue("destinationPackCount") destinationPackCount, err := strconv.ParseInt(destinationPackCountStr, 0, 64) if err != nil { httpError(w, "cannot parse destinationPackCount: %s", err) return } minTableSizeForSplitStr := r.FormValue("minTableSizeForSplit") minTableSizeForSplit, err := strconv.ParseInt(minTableSizeForSplitStr, 0, 64) if err != nil { httpError(w, "cannot parse minTableSizeForSplit: %s", err) return } destinationWriterCountStr := r.FormValue("destinationWriterCount") destinationWriterCount, err := strconv.ParseInt(destinationWriterCountStr, 0, 64) if err != nil { httpError(w, "cannot parse destinationWriterCount: %s", err) return } // start the clone job wrk, err := worker.NewVerticalSplitCloneWorker(wr, *cell, keyspace, "0", tableArray, strategy, int(sourceReaderCount), int(destinationPackCount), uint64(minTableSizeForSplit), int(destinationWriterCount)) if err != nil { httpError(w, "cannot create worker: %v", err) } if _, err := setAndStartWorker(wrk); err != nil { httpError(w, "cannot set worker: %s", err) return } http.Redirect(w, r, servenv.StatusURLPath(), http.StatusTemporaryRedirect) }