Spring data Couchbase generated query method not thread safe - multithreading

When i extend CouchbaseRepository interface in order to do a findByField exp findByProvider --> the method generated is not thread safe :
My interface :
public interface WarehouseRepository extends CouchbaseRepository<WarehouseEntity, String> {
List<WarehouseEntity> findByProvider(String provider);
}
I created a pool of thread in order to test it :
int threads = 3;
ExecutorService service = Executors.newFixedThreadPool(threads);
Collection<Future<Boolean>> futures = new ArrayList<>(threads);
for (int thread = 0; thread < threads; ++thread) {
String provider ="P1";
if(thread == 0)
provider = "P1";
if (thread == 1)
provider = "P2";
if(thread == 2)
provider = "P3";
String expectedProvider = provider;
Callable<Boolean> booleanSupplier = () -> {
String foundProvider = warehouseService.findByProvider(expectedProvider).get(0).getProvider().toString();
System.out.println("expectedProvider = " + expectedProvider + " foundProvider = " + foundProvider);
return expectedProvider.equals(foundProvider);//should never get false
};
futures.add(service.submit(booleanSupplier));
}
Set<Boolean> foundProviders = new HashSet<>();
for (Future<Boolean> future: futures) {
foundProviders.add(future.get());
}
if (1 != foundProviders.size()) {
System.out.println("got bad provider response for my query");
}
Here is a result of one of my executions :
2019/07/03 13:30:39.056 DEBUG Executing N1QL query: {\"args\":[\"P1\"],\"statement\":\"SELECT META(`oms`).id AS _ID, META(`oms`).cas AS _CAS, `oms`.* FROM `oms` WHERE (`provider` = $1) AND `_class` = \\"com.cmt.WarehouseEntity\\"\",\"scan_consistency\":\"statement_plus\"}
2019/07/03 13:30:39.058 DEBUG Executing N1QL query: {\"args\":[\"P3\"],\"statement\":\"SELECT META(`oms`).id AS _ID, META(`oms`).cas AS _CAS, `oms`.* FROM `oms` WHERE (`provider` = $1) AND `_class` = \\"com.cmt.WarehouseEntity\\"\",\"scan_consistency\":\"statement_plus\"}
2019/07/03 13:30:39.056 DEBUG Executing N1QL query: {\"args\":[\"P1\"],\"statement\":\"SELECT META(`oms`).id AS _ID, META(`oms`).cas AS _CAS, `oms`.* FROM `oms` WHERE (`provider` = $1) AND `_class` = \\"com.cmt.WarehouseEntity\\"\",\"scan_consistency\":\"statement_plus\"}
expectedProvider = P2 foundProvider = P1
expectedProvider = P3 foundProvider = P3
expectedProvider = P1 foundProvider = P1
got bad provider for my query
For the query in the first line expectedProvider = P2 foundProvider = P1 we get result of warehousee p1 for a query to find warehouse p2
But when i add #Query to my method, it becomes by magic thread safe .
#Query("#{#n1ql.selectEntity} WHERE #{#n1ql.filter} AND $1 = provider")
List<WarehouseEntity> findByProvider(String provider);
How it is possible ?
Thanks

this issue seems to have been introduced by this change in November 2018.
Downgrade your spring-data-couchbase to 3.1.2.RELEASE.

Related

How do I get disk space statistics for a clustered disk

I have a working program that retrieves information of disk such as FreeSpace, TotalSpace etc from a remote server. I have a problem however that i cannot get the same statistics for all Clustered Disks configured on the server. The query only returns information for the Local Disk (Logical Disk).
I am able to get sizes for Local Disk(:C) as below :
public List<Disk> GetEnvironmentStatistics()
{
var serverIP = Convert.ToString(System.Web.HttpContext.Current.Session["ServerIP"]);
List<Disk> diskinfo = new List<Disk>();
//Add System.Management to access these utilities
ConnectionOptions options = new ConnectionOptions
{
Username = Convert.ToString(System.Web.HttpContext.Current.Session["Username"]),
Password = Convert.ToString(System.Web.HttpContext.Current.Session["Password"]),
Authority = Convert.ToString(System.Web.HttpContext.Current.Session["Authority"]),
};
//root - root of the tree, cimv2 - version
ManagementScope scope = new ManagementScope("\\\\" + serverIP + "\\root\\CIMV2", options);
scope.Connect();
SelectQuery query = new SelectQuery("Select * from Win32_LogicalDisk");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
ManagementObjectCollection queryCollection = searcher.Get();
foreach (ManagementObject mo in queryCollection)
{
Disk disk = new Disk();
disk.DiskName = mo["Name"].ToString();
disk.DeviceId = mo["DeviceID"].ToString();
disk.SystemName = mo["SystemName"].ToString();
disk.FreeSpace = Convert.ToDecimal(mo["FreeSpace"]);
var formattedFreeSpace = Helpers.DiskSpaceInGigabytes(disk.FreeSpace ?? 0);
disk.FreeSpace = Decimal.Truncate(formattedFreeSpace);
disk.TotalSpace = Convert.ToDecimal(mo["Size"]);
var formattedTotalSpace = Helpers.DiskSpaceInGigabytes(disk.TotalSpace ?? 0);
disk.TotalSpace = Decimal.Truncate(formattedTotalSpace);
disk.UsedSpace = disk.TotalSpace - disk.FreeSpace;
var HDPercentageUsed = 100 - (100 * disk.FreeSpace / disk.TotalSpace);
disk.PercentageUsed = Convert.ToInt32(HDPercentageUsed);
diskinfo.Add(disk);
}
return diskinfo;
}
I have logged into the server and noted the other disks appear as Clustered Disk.
I have researched a bit about the Clustered Disks or Cluster Shared Volumes but the only guides i see include Powershell Scripting like here : ClusteredSharedVolume Disk Space.
My question - how can i write a WMI query that also retrieves information for Clustered Disks. Precisely how i can adapt the query in the provided link for my needs :
$resources = Get-WmiObject -namespace root\MSCluster MSCluster_Resource -filter "Type='Physical
Disk'"
$resources | foreach {
$res = $_
$disks = $res.GetRelated("MSCluster_Disk")
$disks | foreach {
$_.GetRelated("MSCluster_DiskPartition") |
select #{N="Name"; E={$res.Name}}, #{N="Status"; E={$res.State}}, Path, VolumeLabel, TotalSize, FreeSpace
}
} | ft
The solution requires invoking Powershell script in C# :
1. Add System.Management.Automation Reference
This dll enable access to Powershell utilities. The packages available on Nuget seem ahead and are not being recognized so i had to manually add the Reference by References >> Add Reference >> Browse >> C:\Windows\assembly\GAC_MSIL\System.Management.Automation\1.0.0.0__31bf3856ad364e35
Using Powershell i can get disk information for all Clustered Disks by the command :
get-WmiObject win32_logicaldisk -Computername (ComputerName or IPAddress here)
2. Invoke this command in code
I added an extension method that checks for whether the remote host has Clustered Disks (if any) . If it indeed has , then use the Powershell script , if not then use normal WMI query :
public List<Disk> GetEnvironmentStatistics()
{
List<Disk> diskinfo = new List<Disk>();
var serverIP = Convert.ToString(System.Web.HttpContext.Current.Session["ServerIP"]);
var clusterDisksStatus = CheckForClusteredDisks(serverIP);
if (Helpers.HasClusteredDisks(clusterDisksStatus))
{
string getClusterSharedVolumesStatistics = "get-WmiObject win32_logicaldisk -Computername " + serverIP + "";
PowerShell ps = PowerShell.Create();
ps.AddScript(getClusterSharedVolumesStatistics);
var results = ps.Invoke();
foreach (var psobject in results)
{
if (psobject != null)
{
Disk clusteredDisk = new Disk();
clusteredDisk.DiskName = Convert.ToString(psobject.Members["DeviceID"].Value);
clusteredDisk.FreeSpace = Convert.ToDecimal(psobject.Members["FreeSpace"].Value);
var formattedFreeSpace = Helpers.DiskSpaceInGigabytes(clusteredDisk.FreeSpace ?? 0);
clusteredDisk.FreeSpace = Decimal.Truncate(formattedFreeSpace);
clusteredDisk.TotalSpace = Convert.ToDecimal(psobject.Members["Size"].Value);
var formattedTotalSpace = Helpers.DiskSpaceInGigabytes(clusteredDisk.TotalSpace ?? 0);
clusteredDisk.TotalSpace = Decimal.Truncate(formattedTotalSpace);
clusteredDisk.UsedSpace = clusteredDisk.TotalSpace - clusteredDisk.FreeSpace;
clusteredDisk.VolumeName = Convert.ToString(psobject.Members["VolumeName"].Value);
diskinfo.Add(clusteredDisk);
}
}
}
else
{
//Add System.Management to access these utilities
ConnectionOptions options = new ConnectionOptions
{
Username = Convert.ToString(System.Web.HttpContext.Current.Session["Username"]),
Password = Convert.ToString(System.Web.HttpContext.Current.Session["Password"]),
Authority = Convert.ToString(System.Web.HttpContext.Current.Session["Authority"]),
};
//root - root of the tree, cimv2 - version
ManagementScope scope = new ManagementScope("\\\\" + serverIP + "\\root\\CIMV2", options);
scope.Connect();
SelectQuery query = new SelectQuery("Select * from Win32_LogicalDisk");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
ManagementObjectCollection queryCollection = searcher.Get();
try
{
foreach (ManagementObject mo in queryCollection)
{
Disk disk = new Disk();
disk.DiskName = mo["Name"].ToString();
disk.DeviceId = mo["DeviceID"].ToString();
disk.SystemName = mo["SystemName"].ToString();
disk.FreeSpace = Convert.ToDecimal(mo["FreeSpace"]);
var formattedFreeSpace = Helpers.DiskSpaceInGigabytes(disk.FreeSpace ?? 0);
disk.FreeSpace = Decimal.Truncate(formattedFreeSpace);
disk.TotalSpace = Convert.ToDecimal(mo["Size"]);
var formattedTotalSpace = Helpers.DiskSpaceInGigabytes(disk.TotalSpace ?? 0);
disk.TotalSpace = Decimal.Truncate(formattedTotalSpace);
disk.UsedSpace = disk.TotalSpace - disk.FreeSpace;
var HDPercentageUsed = 100 - (100 * disk.FreeSpace / disk.TotalSpace);
disk.PercentageUsed = Convert.ToInt32(HDPercentageUsed);
diskinfo.Add(disk);
}
}
catch (DivideByZeroException ex)
{
ExceptionLogger.SendErrorToText(ex);
}
}
return diskinfo;
}
And the Helper method to check :
public static bool HasClusteredDisks(int status)
{
int hasClusteredDisks = 1;
if (status == hasClusteredDisks)
{
return true;
}
else
{
return false;
}
}

Defining log analytic data sources via C#

How can I add the Windows Performance Counters shown in the screenshot below via a C# application?
I found out this can be done via the OperationalInsightsManagementClient. The code below will add a metric.
void AddWorkspaceDatasources(string resourceGroupName, string objectName, string counterName)
{
var client = new OperationalInsightsManagementClient(GetCredentials()) {SubscriptionId = subscriptionId};
var existing = client.DataSources.ListByWorkspace(
new ODataQuery<DataSourceFilter> {Filter = "kind eq 'WindowsPerformanceCounter'"},
resourceGroupName,
resourceGroupName);
if (!existing.Any(c => (c.Properties as JObject)["objectName"].ToString() == objectName && (c.Properties as JObject)["counterName"].ToString() == counterName))
{
var properties = new JObject();
properties["counterName"] = counterName;
properties["instanceName"] = "*";
properties["intervalSeconds"] = 10;
properties["objectName"] = objectName;
properties["collectorType"] = "Default";
client.DataSources.CreateOrUpdate(
resourceGroupName,
resourceGroupName,
Regex.Replace(objectName, "[^a-zA-Z0-9]", "") + Regex.Replace(counterName, "[^a-zA-Z0-9]", ""),
new DataSource
{
Kind = "WindowsPerformanceCounter",
Properties = properties
});
}
}

I use sqldependency AND signalR AND thread but it goes on infinite loop

I use sqldependency AND signalR AND thread but it goes on infinite loop
combine BackgroundWorker in global.aspx and sqldependency and signalR
I dont know about problem please help me.
void Application_Start(object sender, EventArgs e)
{
//var session = HttpContext.Current.Session;
//if (session != null && HttpContext.Current != null)
//{
try
{
CSASPNETBackgroundWorker.BackgroundWorker worker = new CSASPNETBackgroundWorker.BackgroundWorker();
worker.DoWork += new CSASPNETBackgroundWorker.BackgroundWorker.DoWorkEventHandler(worker_DoWork);
worker.RunWorker(null);
// This Background Worker is Applicatoin Level,
// so it will keep working and it is shared by all users.
Application["worker"] = worker;
// Code that runs on application startup
}
catch { }
// }
System.Data.SqlClient.SqlDependency.Start(connectionstring);
}
string user_id;
void worker_DoWork(ref int progress,
ref object _result, params object[] arguments)
{
// Do the operation every 1 second wihout the end.
while (true)
{
Random rand = new Random();
int randnum = rand.Next(5000, 20000);
Thread.Sleep(randnum);
// This statement will run every 1 second.
// string user_id = "";
// if (HttpContext.Current != null && HttpContext.Current.Session != null)
{
// user_id = "22";// HttpContext.Current.Session["userId"].ToString();
user_id = ConfigurationManager.AppSettings["session_user_id"].ToString();
updatealarm(user_id);
}
// Other logic which you want it to keep running.
// You can do some scheduled tasks here by checking DateTime.Now.
}
}
AND
public class AlarmInfoRepository {
string connectionstr = ConfigurationManager.ConnectionStrings["officeConnectionString"].ConnectionString;
public IEnumerable GetData(string user_id)
{
using (SqlConnection connection = new SqlConnection(connectionstr))
{
//PersianCalendar jc = new PersianCalendar();
//string todayStr = jc.GetYear(DateTime.Now).ToString("0000") + "/" + jc.GetMonth(DateTime.Now).ToString("00") + "/" +
// jc.GetDayOfMonth(DateTime.Now).ToString("00");
//string timeStr = String.Format("{0:00}:{1:00}:{2:00}", jc.GetHour(DateTime.Now.AddSeconds(10)), jc.GetMinute(DateTime.Now.AddSeconds(10)), jc.GetSecond(DateTime.Now.AddSeconds(10)));
if (connection.State == ConnectionState.Closed)
connection.Open();
using (SqlCommand command = new SqlCommand(#"SELECT dbo.[web_alarmkartable].[id],dbo.[web_alarmkartable].peygir_id,dbo.[web_alarmkartable].user_id,
dbo.[web_alarmkartable].[content],dbo.[web_alarmkartable].[latestcreate_date],dbo.[web_alarmkartable].[latestcreate_time],
dbo.[web_alarmkartable].[firstcreate_date],dbo.[web_alarmkartable].[firstcreate_time],dbo.[web_alarmkartable].[duration],
dbo.[web_alarmkartable].[periodtype_id],dbo.[web_alarmkartable].[period],ISNULL(dbo.[web_alarmkartable].[color],'') AS color,dbo.[web_alarmkartable].id_tel FROM dbo.[web_alarmkartable] where dbo.[web_alarmkartable].content !='' AND dbo.[web_alarmkartable].content IS NOT NULL
AND (dbo.[web_alarmkartable].seen IS NULL OR dbo.[web_alarmkartable].seen =0) AND (dbo.[web_alarmkartable].expier IS NULL OR dbo.[web_alarmkartable].expier =0 )
AND (dbo.[web_alarmkartable].del=0 OR dbo.[web_alarmkartable].del IS NULL) AND dbo.[web_alarmkartable].user_id=" + user_id, connection))
{
// Make sure the command object does not already have
// a notification object associated with it.
command.Notification = null;
SqlDependency dependency = new SqlDependency(command);
dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
using (var reader = command.ExecuteReader())
return reader.Cast<IDataRecord>()
.Select(x => new AlarmInfo()
{
id = x.GetInt32(0),
peygir_id = x.GetInt32(1),
user_id = x.GetInt32(2),
content = x.GetString(3),
latestcreate_date = x.GetString(4),
latestcreate_time = x.GetString(5),
firstcreate_date = x.GetString(6),
firstcreate_time = x.GetString(7),
duration = x.GetDecimal(8),
periodtype_id = x.GetInt32(9),
period = x.GetDecimal(10),
color = x.GetString(11),
id_tel = x.GetInt32(12)
}).ToList();
}
//if (connection.State == ConnectionState.Open)
// connection.Close();
}
}
private void dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
if ((e.Info.ToString() == "Insert" || e.Info.ToString() == "Update") && e.Type == SqlNotificationType.Change)
AlermHub.Show(e.Info.ToString());
}
}
AND

Update a SavedQuery (View) from the SDK

I am trying to change all the Business Unit references I got after importing a solution to the ones in the Acceptance environment.
QueryExpression ViewQuery = new QueryExpression("savedquery");
String[] viewArrayFields = { "name", "fetchxml" };
ViewQuery.ColumnSet = new ColumnSet(viewArrayFields);
ViewQuery.PageInfo = new PagingInfo();
ViewQuery.PageInfo.Count = 5000;
ViewQuery.PageInfo.PageNumber = 1;
ViewQuery.PageInfo.ReturnTotalRecordCount = true;
EntityCollection retrievedViews = service.RetrieveMultiple(ViewQuery);
//iterate though the values and print the right one for the current user
int oldValues = 0;
int accValuesUpdated = 0;
int prodValuesUpdated = 0;
int total = 0;
foreach (var entity in retrievedViews.Entities)
{
total++;
if (!entity.Contains("fetchxml"))
{ }
else
{
string fetchXML = entity.Attributes["fetchxml"].ToString();
for (int i = 0; i < guidDictionnary.Count; i++)
{
var entry = guidDictionnary.ElementAt(i);
if (fetchXML.Contains(entry.Key.ToString().ToUpperInvariant()))
{
Console.WriteLine(entity.Attributes["name"].ToString());
oldValues++;
if (destinationEnv.Equals("acc"))
{
accValuesUpdated++;
Console.WriteLine();
Console.WriteLine("BEFORE:");
Console.WriteLine();
Console.WriteLine(entity.Attributes["fetchxml"].ToString());
string query = entity.Attributes["fetchxml"].ToString();
query = query.Replace(entry.Key.ToString().ToUpperInvariant(), entry.Value.AccGuid.ToString().ToUpperInvariant());
entity.Attributes["fetchxml"] = query;
Console.WriteLine();
Console.WriteLine("AFTER:");
Console.WriteLine();
Console.WriteLine(entity.Attributes["fetchxml"].ToString());
}
else
{
prodValuesUpdated++;
string query = entity.Attributes["fetchxml"].ToString();
query = query.Replace(entry.Key.ToString().ToUpperInvariant(), entry.Value.ProdGuid.ToString().ToUpperInvariant());
entity.Attributes["fetchxml"] = query;
}
service.Update(entity);
}
}
}
}
Console.WriteLine("{0} values to be updated. {1} shall be mapped to acceptance, {2} to prod. Total = {3} : {4}", oldValues, accValuesUpdated, prodValuesUpdated, total, retrievedViews.Entities.Count);
I see that the new value is corrected, but it does not get saved. I get no error while updating the record and publishing the changes in CRM does not help.
Any hint?
According to your comments, it sounds like the value you're saving the entity as, is the value that you want it to be. I'm guessing your issue is with not publishing your change. If you don't publish it, it'll still give you the old value of the FetchXml I believe.
Try calling this method:
PublishEntity(service, "savedquery");
private void PublishEntity(IOrganizationService service, string logicalName)
{
service.Execute(new PublishXmlRequest()
{
ParameterXml = "<importexportxml>"
+ " <entities>"
+ " <entity>" + logicalName + "</entity>"
+ " </entities>"
+ "</importexportxml>"
});
}

The method 'Equals' is not supported

public List<Health_Scheme_System.Employee> GetPenEmployeeTable()
{
Health_Scheme_System.Health_Scheme_SystemDB db = new Health_Scheme_System.Health_Scheme_SystemDB();
var x = (from c in db.Employees
where c.Pensioners.Equals (1)
select c);
return x.ToList();
}
//Selecting multiple columns from an HR view table together with the scheme name of scheme.
public List<EmployeesX> GetPensioners()
{
Health_Scheme_System.Health_Scheme_SystemDB db = new Health_Scheme_System.Health_Scheme_SystemDB();
List<Health_Scheme_System.EmployeeDirectory> listEmployeeView = GetPenEmployeeView();
List<Health_Scheme_System.Employee> listEmployeeTable = GetPenEmployeeTable();
List<Health_Scheme_System.Scheme> listSchemes = GetSchemes();
List<EmployeesX> listOfEmployees = new List<EmployeesX>();
//checking for comparision of getemployeeview to getemployee table and then to getschemes
//Then display the scheme name if they are similar.
for (int i = 0; i < listEmployeeView.Count; i++)
{
EmployeesX emp = new EmployeesX();
emp.ID_NO = listEmployeeView[i].ID_NO;
emp.FIRST_NAME = listEmployeeView[i].FIRST_NAME;
emp.LAST_NAME = listEmployeeView[i].LAST_NAME;
emp.LOCATION_CODE = listEmployeeView[i].LOCATION_CODE;
for (int j = 0; j < listEmployeeTable.Count; j++)
{
if (listEmployeeTable[j].EmployeeIDCard == listEmployeeView[i].ID_NO)
{
emp.Pensioners = listEmployeeTable[j].Pensioners;
for (int k = 0; k < listSchemes.Count; k++)
{
if (listEmployeeTable[j].SchemeID == listSchemes[k].SchemeID)
{
emp.SCHEME_NAME = listSchemes[k].Name;
emp.START_DATE = listEmployeeTable[j].StartSchemeDate;
}
}
}
}
listOfEmployees.Add(emp);
}
return listOfEmployees;
}
How can I make the same method with using .equals??
Have you tried this:
var x = (from c in db.Employees
where c.Pensioners == 1
select c)
Additional info:
If you use a method on an object in a linq query subsonic needs to know how to translate that into pur SQL code. That does not work by default and must be implemented for every known method on every supported type for every dataprovider (if differs from default implementation). So there is a bunch of work to do for subsonic.
A good starting point for knowning what's supported and what not is the TSqlFormatter class. Have a look at protected override Expression VisitMethodCall(MethodCallExpression m)
https://github.com/subsonic/SubSonic-3.0/blob/master/SubSonic.Core/Linq/Structure/TSqlFormatter.cs
There is already an implementation for Equals
else if (m.Method.Name == "Equals")
{
if (m.Method.IsStatic && m.Method.DeclaringType == typeof(object))
{
sb.Append("(");
this.Visit(m.Arguments[0]);
sb.Append(" = ");
this.Visit(m.Arguments[1]);
sb.Append(")");
return m;
}
else if (!m.Method.IsStatic && m.Arguments.Count == 1 && m.Arguments[0].Type == m.Object.Type)
{
sb.Append("(");
this.Visit(m.Object);
sb.Append(" = ");
this.Visit(m.Arguments[0]);
sb.Append(")");
return m;
}
else if (m.Method.IsStatic && m.Method.DeclaringType == typeof(string))
{
//Note: Not sure if this is best solution for fixing side issue with Issue #66
sb.Append("(");
this.Visit(m.Arguments[0]);
sb.Append(" = ");
this.Visit(m.Arguments[1]);
sb.Append(")");
return m;
}
}
I suppose Prnsioners is an integer type so you basically have to add another else if and recomplie subsonic.
This should work but I haven't tested it.
else if (!m.Method.IsStatic && m.Method.DeclaringType == typeof(int))
{
sb.Append("(");
this.Visit(m.Arguments[0]);
sb.Append(" = ");
this.Visit(m.Arguments[1]);
sb.Append(")");
return m;
}
(or you can try the == approach like in the example on the top).

Resources