package main /* #include #include #include #include "client.h" #include "netio.h" #include "controller.capnp.h" #include "helper.h" typedef struct { xcecli_ctx_t ctx; uintptr_t go_handler; void* go_apiserver; } apiserver_ctx_t; extern int go_callback(uintptr_t, xce_request_t*, apiserver_ctx_t *); static int xce_apiserver_handler(xce_request_t *req, void *arg) { int rc = -EINVAL; apiserver_ctx_t *ctx = (apiserver_ctx_t *)arg; if (ctx == NULL) { return -EINVAL; } if (ctx->go_handler != 0) { rc = go_callback(ctx->go_handler, req, arg); } return rc; } static int xce_apiserver_init(xce_client_config_t *config, apiserver_ctx_t *ctx) { int rc; if ((config == NULL) || (ctx == NULL)) { return -EINVAL; } rc = xcecli_ctx_init(&(ctx->ctx), config); if (rc < 0) { return rc; } xcecli_set_handler(ctx->ctx, (xce_request_handler_t)xce_apiserver_handler, ctx); rc = xcecli_start(ctx->ctx); if (rc < 0) { return rc; } rc = xcecli_join(ctx->ctx, HostRole_apiserver, NULL); return rc; } static xce_job_t **dataset_jobs(dataset_t *d) { return (xce_job_t **)d->rows; } static xce_worker_t **dataset_workers(dataset_t *d) { return (xce_worker_t **)d->rows; } */ import "C" import ( "fmt" "unsafe" "runtime/cgo" "log" "net/http" ) type ApiServer struct { // add data here } //export go_callback func go_callback(h C.uintptr_t, req *C.xce_request_t, ctx *C.apiserver_ctx_t) C.int { fn := cgo.Handle(h).Value().(func(*C.xce_request_t,*C.apiserver_ctx_t) C.int) return fn(req, ctx); } func (apiserver *ApiServer) handle_config(config *C.xce_configdata_t) C.int { switch (config.data_which) { case C.ConfigData_data_clusterconfig: fmt.Printf("cluster configuration received\n") // Extract configuration information from config // - queues // - resources information // - and other information default: // fmt.Printf("unhandled config request %d\n", config.data_which) } return 0 } func print_job(job *C.xce_job_t) { fmt.Printf("jobid `%v' user `%s' queue `%s'\n",uint64(job.jobid), C.GoString(job.submit.user), C.GoString(job.submit.queue)) } func print_worker(w *C.xce_worker_t) { fmt.Printf("worker `%s'\n", C.GoString(w.name)) } func (apiserver *ApiServer) handle_job_push(jobs []*C.xce_job_t) C.int { // add all jobs to apiserver for i := range jobs { print_job(jobs[i]) } return 0 } func (apiserver *ApiServer) handle_worker_push(workers []*C.xce_worker_t) C.int { // add all workers to api server for i := range workers { print_worker(workers[i]) } return 0 } func (apiserver *ApiServer)handle_dataset(dataset *C.dataset_t) C.int { fmt.Printf("handle dataset table %d\n", dataset.table) switch(dataset.table) { case C.Data_data_schedjobs: fmt.Printf("%d jobs arrived\n", dataset.nrows) var theJobs **C.xce_job_t = C.dataset_jobs(dataset) jobs := unsafe.Slice(theJobs, dataset.nrows) return apiserver.handle_job_push(jobs) case C.Data_data_schedworkers: fmt.Printf("%d workers arrived\n", dataset.nrows) var theWorkers **C.xce_worker_t = C.dataset_workers(dataset) workers := unsafe.Slice(theWorkers, dataset.nrows) return apiserver.handle_worker_push(workers) default: // } return 0 } func go_req_handler(request *C.xce_request_t, ctx *C.apiserver_ctx_t) C.int { var from = C.GoString(request.from.name) var body_which = request.body_which var apiserver = (*ApiServer)(unsafe.Pointer(ctx.go_apiserver)) fmt.Println("api server handler called") fmt.Printf("op `%s' body_which %d from %s\n", C.GoString(C.xce_request_op_name(request)), body_which, from) switch (request.opcode) { case C.OPCode_push: switch (body_which) { case C.Request_body_configpushmsg: // handle push config return apiserver.handle_config((*C.xce_configdata_t)(unsafe.Pointer(C.xce_request_body(request)))) case C.Request_body_datamsg: // handle pushed data msg return apiserver.handle_dataset((*C.dataset_t)(unsafe.Pointer(C.xce_request_body(request)))) default: // something wrong } default: } C.free_Request(request) return 0 } func init_config(config *C.xce_client_config_t) C.int { config.nmasters =1 config.masters[0] = C.CString("localhost") config.master_ports[0] = C.int(9990); config.from = C.CString("xce_apiserver") config.key = C.CString("keepsecret$") return 0 } func (apiserver *ApiServer) handle_job_query(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "URL.Path = %q\n", r.URL.Path) } func main() { var config C.xce_client_config_t var ctx C.apiserver_ctx_t var apiserver ApiServer init_config(&config) h := cgo.NewHandle(go_req_handler) defer h.Delete() ctx.go_handler = C.uintptr_t(h) ctx.go_apiserver = unsafe.Pointer(&apiserver) rc := C.xce_apiserver_init(&config, &ctx) fmt.Printf("rc %d\n", rc); http.HandleFunc("/jobs", (&apiserver).handle_job_query) log.Fatal(http.ListenAndServe("localhost:8000", nil)) }