github.com/cloud-foundations/dominator@v0.0.0-20221004181915-6e4fee580046/imageserver/rpcd/getImageUpdates.go (about)

     1  package rpcd
     2  
     3  import (
     4  	"github.com/Cloud-Foundations/Dominator/lib/image"
     5  	"github.com/Cloud-Foundations/Dominator/lib/srpc"
     6  	"github.com/Cloud-Foundations/Dominator/proto/imageserver"
     7  )
     8  
     9  func (t *srpcType) GetImageUpdates(conn *srpc.Conn) error {
    10  	defer conn.Flush()
    11  	t.logger.Printf("New image replication client connected from: %s\n",
    12  		conn.RemoteAddr())
    13  	select {
    14  	case <-t.finishedReplication:
    15  	default:
    16  		t.logger.Println(
    17  			"Blocking replication client until I've finished replicating")
    18  		<-t.finishedReplication
    19  		t.logger.Printf(
    20  			"Replication finished, unblocking replication client: %s\n",
    21  			conn.RemoteAddr())
    22  	}
    23  	t.incrementNumReplicationClients(true)
    24  	defer t.incrementNumReplicationClients(false)
    25  	addChannel := t.imageDataBase.RegisterAddNotifier()
    26  	deleteChannel := t.imageDataBase.RegisterDeleteNotifier()
    27  	mkdirChannel := t.imageDataBase.RegisterMakeDirectoryNotifier()
    28  	defer t.imageDataBase.UnregisterAddNotifier(addChannel)
    29  	defer t.imageDataBase.UnregisterDeleteNotifier(deleteChannel)
    30  	defer t.imageDataBase.UnregisterMakeDirectoryNotifier(mkdirChannel)
    31  	directories := t.imageDataBase.ListDirectories()
    32  	image.SortDirectories(directories)
    33  	for _, directory := range directories {
    34  		imageUpdate := imageserver.ImageUpdate{
    35  			Directory: &directory,
    36  			Operation: imageserver.OperationMakeDirectory,
    37  		}
    38  		if err := conn.Encode(imageUpdate); err != nil {
    39  			t.logger.Println(err)
    40  			return err
    41  		}
    42  	}
    43  	for _, imageName := range t.imageDataBase.ListImages() {
    44  		imageUpdate := imageserver.ImageUpdate{Name: imageName}
    45  		if err := conn.Encode(imageUpdate); err != nil {
    46  			t.logger.Println(err)
    47  			return err
    48  		}
    49  	}
    50  	// Signal end of initial image list.
    51  	if err := conn.Encode(imageserver.ImageUpdate{}); err != nil {
    52  		t.logger.Println(err)
    53  		return err
    54  	}
    55  	if err := conn.Flush(); err != nil {
    56  		t.logger.Println(err)
    57  		return err
    58  	}
    59  	t.logger.Println(
    60  		"Finished sending initial image list to replication client")
    61  	closeChannel := conn.GetCloseNotifier()
    62  	for {
    63  		select {
    64  		case imageName := <-addChannel:
    65  			if err := sendUpdate(conn, imageName,
    66  				imageserver.OperationAddImage); err != nil {
    67  				t.logger.Println(err)
    68  				return err
    69  			}
    70  		case imageName := <-deleteChannel:
    71  			if err := sendUpdate(conn, imageName,
    72  				imageserver.OperationDeleteImage); err != nil {
    73  				t.logger.Println(err)
    74  				return err
    75  			}
    76  		case directory := <-mkdirChannel:
    77  			if err := sendMakeDirectory(conn, directory); err != nil {
    78  				t.logger.Println(err)
    79  				return err
    80  			}
    81  		case err := <-closeChannel:
    82  			if err == nil {
    83  				t.logger.Printf("Image replication client disconnected: %s\n",
    84  					conn.RemoteAddr())
    85  				return nil
    86  			}
    87  			t.logger.Println(err)
    88  			return err
    89  		}
    90  		if err := conn.Flush(); err != nil {
    91  			t.logger.Println(err)
    92  			return err
    93  		}
    94  	}
    95  }
    96  
    97  func (t *srpcType) incrementNumReplicationClients(increment bool) {
    98  	t.numReplicationClientsLock.Lock()
    99  	defer t.numReplicationClientsLock.Unlock()
   100  	if increment {
   101  		t.numReplicationClients++
   102  	} else {
   103  		t.numReplicationClients--
   104  	}
   105  }
   106  
   107  func sendUpdate(encoder srpc.Encoder, name string, operation uint) error {
   108  	imageUpdate := imageserver.ImageUpdate{Name: name, Operation: operation}
   109  	return encoder.Encode(imageUpdate)
   110  }
   111  
   112  func sendMakeDirectory(encoder srpc.Encoder, directory image.Directory) error {
   113  	imageUpdate := imageserver.ImageUpdate{
   114  		Directory: &directory,
   115  		Operation: imageserver.OperationMakeDirectory,
   116  	}
   117  	return encoder.Encode(imageUpdate)
   118  }