func()

in oracle/pkg/database/dbdaemon/dbdaemon_server.go [847:928]


func (s *Server) applyDataPatch(ctx context.Context) (*dbdpb.ApplyDataPatchResponse, error) {
	s.syncJobs.maintenanceMutex.Lock()
	defer s.syncJobs.maintenanceMutex.Unlock()

	klog.InfoS("dbdaemon/applyDataPatch started")

	// Ask proxy to shutdown the DB
	if _, err := s.dbdClient.BounceDatabase(ctx, &dbdpb.BounceDatabaseRequest{
		Operation:    dbdpb.BounceDatabaseRequest_SHUTDOWN,
		DatabaseName: s.databaseSid.val,
		Option:       "immediate",
	}); err != nil {
		return nil, fmt.Errorf("proxy request to shutdown DB failed: %w", err)
	}

	klog.InfoS("dbdaemon/applyDataPatch DB is down, starting in upgrade mode")

	// Ask proxy to startup the DB in NOMOUNT mode
	if _, err := s.dbdClient.BounceDatabase(ctx, &dbdpb.BounceDatabaseRequest{
		Operation:    dbdpb.BounceDatabaseRequest_STARTUP,
		DatabaseName: s.databaseSid.val,
		Option:       "nomount",
	}); err != nil {
		return nil, fmt.Errorf("proxy request to startup DB failed: %w", err)
	}

	// Set upgrade mode (possible OJVM upgrades still require this, but may fail some standard patches).
	if err := s.database.setDatabaseUpgradeMode(ctx); err != nil {
		return nil, err
	}

	klog.InfoS("dbdaemon/applyDataPatch DB is in migrate state, starting datapatch")

	// oracle/product/12.2/db/OPatch/datapatch -verbose
	dpCode := 0
	if err := s.runCommand(datapatch(s.databaseHome), []string{"-verbose"}); err != nil {
		if exitError, ok := err.(*exec.ExitError); !ok {
			return nil, fmt.Errorf("datapatch failed: %w", err)
		} else {
			dpCode = exitError.ExitCode()
		}
	}
	// We will try again in normal mode.
	klog.InfoS("dbdaemon/applyDataPatch datapatch attempt in upgrade mode completed, restarting DB in normal mode", "return code", dpCode)

	// Ask proxy to shutdown the DB
	// SQL> shutdown immediate
	if _, err := s.dbdClient.BounceDatabase(ctx, &dbdpb.BounceDatabaseRequest{
		Operation:    dbdpb.BounceDatabaseRequest_SHUTDOWN,
		DatabaseName: s.databaseSid.val,
		Option:       "immediate",
	}); err != nil {
		return nil, fmt.Errorf("proxy request to shutdown DB failed: %w", err)
	}

	// Ask proxy to startup the DB
	// SQL> startup
	if _, err := s.dbdClient.BounceDatabase(ctx, &dbdpb.BounceDatabaseRequest{
		Operation:    dbdpb.BounceDatabaseRequest_STARTUP,
		DatabaseName: s.databaseSid.val,
		Option:       "",
	}); err != nil {
		return nil, fmt.Errorf("proxy request to startup DB failed: %w", err)
	}

	// SQL> alter pluggable database all open
	if err := s.database.openPDBs(ctx); err != nil {
		return nil, err
	}
	// At this point CDB$ROOT, PDB$SEED and all PDBs should be in normal 'RW' or 'RO' state

	// Retry datapatch in normal mode for those that require it.
	if err := s.runCommand(datapatch(s.databaseHome), []string{"-verbose"}); err != nil {
		if exitError, ok := err.(*exec.ExitError); ok {
			return nil, fmt.Errorf("datapatch failed in normal mode with exit code = %v: %w", exitError.ExitCode(), err)
		}
		return nil, fmt.Errorf("datapatch failed: %w", err)
	}

	klog.InfoS("dbdaemon/applyDataPatch completed, DB is back up")
	return &dbdpb.ApplyDataPatchResponse{}, nil
}