func (b *Bucket) Refresh() error { pool := b.pool tmpb := &Bucket{} err := pool.client.parseURLResponse(b.URI, tmpb) if err != nil { return err } pools := b.getConnPools() // We need this lock to ensure that bucket refreshes happening because // of NMVb errors received during bulkGet do not end up over-writing // pool.inUse. b.Lock() for _, pool := range pools { if pool != nil { pool.inUse = false } } newcps := make([]*connectionPool, len(tmpb.VBSMJson.ServerList)) for i := range newcps { pool := b.getConnPoolByHost(tmpb.VBSMJson.ServerList[i]) if pool != nil && pool.inUse == false { // if the hostname and index is unchanged then reuse this pool newcps[i] = pool pool.inUse = true continue } if b.ah != nil { newcps[i] = newConnectionPool( tmpb.VBSMJson.ServerList[i], b.ah, PoolSize, PoolOverflow) } else { newcps[i] = newConnectionPool( tmpb.VBSMJson.ServerList[i], b.authHandler(), PoolSize, PoolOverflow) } } b.replaceConnPools2(newcps) tmpb.ah = b.ah atomic.StorePointer(&b.vBucketServerMap, unsafe.Pointer(&tmpb.VBSMJson)) b.nodeListLock.Lock() atomic.StorePointer(&b.nodeList, unsafe.Pointer(&tmpb.NodesJSON)) b.nodeListLock.Unlock() b.Unlock() return nil }
func (b *Bucket) UpdateBucket() error { var failures int var returnErr error for { if failures == MAX_RETRY_COUNT { log.Printf(" Maximum failures reached. Exiting loop...") return fmt.Errorf("Max failures reached. Last Error %v", returnErr) } nodes := b.Nodes() if len(nodes) < 1 { return fmt.Errorf("No healthy nodes found") } startNode := rand.Intn(len(nodes)) node := nodes[(startNode)%len(nodes)] streamUrl := fmt.Sprintf("http://%s/pools/default/bucketsStreaming/%s", node.Hostname, b.Name) log.Printf(" Trying with %s", streamUrl) req, err := http.NewRequest("GET", streamUrl, nil) if err != nil { return err } err = maybeAddAuth(req, b.pool.client.ah) if err != nil { return err } res, err := doHTTPRequestForUpdate(req) if err != nil { return err } if res.StatusCode != 200 { bod, _ := ioutil.ReadAll(io.LimitReader(res.Body, 512)) log.Printf("Failed to connect to host, unexpected status code: %v. Body %s", res.StatusCode, bod) res.Body.Close() returnErr = fmt.Errorf("Failed to connect to host. Status %v Body %s", res.StatusCode, bod) failures++ continue } dec := json.NewDecoder(res.Body) tmpb := &Bucket{} for { err := dec.Decode(&tmpb) if err != nil { log.Printf(" Unable to decode response %v", err) returnErr = err res.Body.Close() break } // if we got here, reset failure count failures = 0 b.Lock() // mark all the old connection pools for deletion pools := b.getConnPools() for _, pool := range pools { if pool != nil { pool.inUse = false } } newcps := make([]*connectionPool, len(tmpb.VBSMJson.ServerList)) for i := range newcps { // get the old connection pool and check if it is still valid pool := b.getConnPoolByHost(tmpb.VBSMJson.ServerList[i]) if pool != nil && pool.inUse == false { // if the hostname and index is unchanged then reuse this pool newcps[i] = pool pool.inUse = true continue } // else create a new pool if b.ah != nil { newcps[i] = newConnectionPool( tmpb.VBSMJson.ServerList[i], b.ah, PoolSize, PoolOverflow) } else { newcps[i] = newConnectionPool( tmpb.VBSMJson.ServerList[i], b.authHandler(), PoolSize, PoolOverflow) } } b.replaceConnPools2(newcps) tmpb.ah = b.ah atomic.StorePointer(&b.vBucketServerMap, unsafe.Pointer(&tmpb.VBSMJson)) atomic.StorePointer(&b.nodeList, unsafe.Pointer(&tmpb.NodesJSON)) b.Unlock() log.Printf("Got new configuration for bucket %s", b.Name) } // we are here because of an error failures++ continue } return nil }